搜索
bottom↓
楼主: lupa

请教如何在IAR上使用代码库自带的printf函数

[复制链接]
(379024561)

出0入0汤圆

发表于 2009-2-22 15:59:53 | 显示全部楼层 |阅读模式
一个主程序,通过USART1向中断输出字符。已经编写了类似int putchar(int c)的函数。问题是如何使用这个函数替换IAR库中的底层函数,使其可以通过调用printf()函数在终端中实现格式化输出。
通过查看手册发现需要Override _Write函数,现在已作如下修改。将库/src/lib/中的write.c拷贝至项目目录。修改nt MyLowLevelPutchar(int x);函数,将其用putchar()的例程代替。但在编译过程中出现
Error[e6]: Program module ?__write redeclared in file E:\STM32 Projects\
的提示。请问如何解决这一问题?
(379024359)

出0入0汤圆

 楼主| 发表于 2009-2-22 16:03:15 | 显示全部楼层
这是IAR手册上的说明:
This procedure is applicable to any source file in the library, which means that
library_module.c in this example can be any module in the library.

1 Copy the appropriate library_module.c file to your project directory.
2 Make the required additions to the file (or create your own routine, using the default
file as a model).
3 Add the customized file to your project.
4 Rebuild your project.
(379023522)

出0入0汤圆

发表于 2009-2-22 16:17:12 | 显示全部楼层
#include "stdio.h"

重写int fputc(int ch, FILE *f)函数

例如
int fputc(int ch, FILE *f)
{
    USART2->DR = (u8) ch;
    /* Loop until the end of transmission */
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    return ch;
}
(379022483)

出0入0汤圆

 楼主| 发表于 2009-2-22 16:34:31 | 显示全部楼层
又出现了如下提示:
Error[Pe020]: identifier "FILE" is undefined E:\STM32 Projects\ex3_EXTI_arm\main.c 284
(379021964)

出0入0汤圆

发表于 2009-2-22 16:43:10 | 显示全部楼层
看stdio.h
如果putchar是函数声明,就重写int putchar(int ch)

如果putchar是宏定义,或者是一个内联函数,则重写int fputc(int ch, FILE *f)
(379021801)

出0入0汤圆

 楼主| 发表于 2009-2-22 16:45:53 | 显示全部楼层
stdio.h 中内容  __INTRINSIC int fputc(int, FILE *);
(379021717)

出0入0汤圆

发表于 2009-2-22 16:47:17 | 显示全部楼层
需要在 IAR的Option -> General Options ->Library Configuration里设置一下函数库,不然printf函数不对
(379021237)

出0入0汤圆

 楼主| 发表于 2009-2-22 16:55:17 | 显示全部楼层
谢谢楼上的建议:
将Library Configuration 中的Library 设置由"Normal"改为"Full"就可以了。
请问这是什么原因呢?
(379021023)

出0入0汤圆

 楼主| 发表于 2009-2-22 16:58:51 | 显示全部楼层
发现Normal和Full设置的一个区别在于,Normal模式下no file descriptor support(没有文件描述符支持)。
请问my_avr :
按照IAR文档上的描述应该可以通过重写_read和_write函数来实现根据实际硬件将输入输出从定向的。这个应该如何实现?
(379017582)

出0入0汤圆

发表于 2009-2-22 17:56:12 | 显示全部楼层
回【8楼】 lupa

你说的这个问题我也一直没有搞清楚,不知道怎么回事,感觉就是和GCC的不一样。

等待高人指点。
(379011913)

出0入0汤圆

发表于 2009-2-22 19:30:41 | 显示全部楼层
IAR LIB设置Normal
重写int putchar(int ch)

IAR LIB设置Full
重写int putchar(int ch) 或者 int fputc(int ch, FILE *f) 都可以。
(379011322)

出0入0汤圆

 楼主| 发表于 2009-2-22 19:40:32 | 显示全部楼层
__stm32f100__ :
为什么在设置为Normal时不能重写fputc()函数。是不是可以理解为当LAB设置为Full时,在Printf函数执行时,调用的是fputc函数;而在LAB设置为Normal时,调用的是putchar()函数。
这两个函数在Printf的实现中具体有什么功能上的区别?谢谢!
(379010941)

出0入0汤圆

发表于 2009-2-22 19:46:53 | 显示全部楼层
都是调用putchar函数。

只是设置Full的时候,putchar函数调用了又调用fputc函数,所以重写fputc也可以。

putchar(ch)相当于与fputc(ch,stdout)
设置NORMAL的时候,不支持文件指针,也没有定义stdout,不能调用fputc(ch,stdout)。
(379010033)

出0入0汤圆

 楼主| 发表于 2009-2-22 20:02:01 | 显示全部楼层
谢谢指导!
我又从手册上找到了以下描述:
“在IAR中所有的输入/输出函数仅调用一个小型初等函数,一个函数集完成一个规定的任务。例如,__open函数用于打开文件,__write函数用于字符输出等。
注意:仅当运行库配置为full时才能支持文件输入\输出功能,即只有允许了配置符号__DLIB_FILE_DESCRIPTOR时运行库才支持文件输入\输出功能操作,否则不能使用带有“FILE *”参数的函数。
如果连接库时采用XLINK选项With I/O emulation modules,将自动链接C-SPY调试器中底层I/O函数以便实现交互调试。


那现在的问题是按照IAR的说法,我们只需要修改这个初等函数库中的函数就可以将输出从定向到我们想要的设备上,如字符LCD,串口等。可那上面的表述相当笼统,请问大侠如何实现这一修改?我尝试过一楼的方法但是编译出现错误。
(371221217)

出0入0汤圆

发表于 2009-5-23 23:35:37 | 显示全部楼层
我按照各位兄弟的教程自己做了一下。何是郁闷啊!老是提出

P2 s0 (原文件名:QQ截图未命名.jpg)

P2 s0是什么意思啊?到底是什么问题啊?
当屏蔽了printf时就没有问题啊!

到底是什么问题啊?
(369540879)

出0入0汤圆

发表于 2009-6-12 10:21:15 | 显示全部楼层
mark
(355029533)

出0入0汤圆

发表于 2009-11-27 09:17:01 | 显示全部楼层
果然是printf的好帖子!
(355023970)

出0入0汤圆

发表于 2009-11-27 10:49:44 | 显示全部楼层
果然是printf的好帖子!
(353476213)

出0入0汤圆

发表于 2009-12-15 08:45:41 | 显示全部楼层
真是不知道什么原因,我的也是P2s0问题
(353475565)

出0入0汤圆

发表于 2009-12-15 08:56:29 | 显示全部楼层
IAR 5.30出现的问题
(353100887)

出0入0汤圆

发表于 2009-12-19 17:01:07 | 显示全部楼层
3.1.2固件库里面的例子
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  USART_SendData(EVAL_COM1, (uint8_t) ch);

  /* Loop until the end of transmission */
  while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
  {}

  return ch;
}
(352926283)

出0入0汤圆

发表于 2009-12-21 17:31:11 | 显示全部楼层
mark
(352925487)

出0入0汤圆

发表于 2009-12-21 17:44:27 | 显示全部楼层
mark
(349277066)

出0入0汤圆

发表于 2010-2-1 23:11:28 | 显示全部楼层
mark
(349231972)

出0入0汤圆

发表于 2010-2-2 11:43:02 | 显示全部楼层
回复【14楼】DVD1478  


-----------------------------------------------------------------------
换成在FLASH中调试试下!
(345938251)

出0入0汤圆

发表于 2010-3-12 14:38:23 | 显示全部楼层
非常好的帖子
我也遇到了此类问题,看了此帖才把问题解决了的
(344869073)

出0入0汤圆

发表于 2010-3-24 23:38:01 | 显示全部楼层
下午调试USART时遇到了,设置了FULL后就可以了
(344830337)

出0入0汤圆

发表于 2010-3-25 10:23:37 | 显示全部楼层
我每次编写代码的时候都会写好第一次创建这个工程的日期,我看了这个帖子在回去研究了一下那个时候还没有做出来的STM的串口,感觉还是非常的不错,当时最让我头晕的就是那个normal和full的区别,当我搞明白的时候发现USB转串口的东西坏了,治好等了一个春节才买到。
其几天的时候由于项目的需要做了一下AVR的串口,以前学一定学过但是一直没有用过,AVR的会的STM的自然也非常的简单,就这样写了一个hello world!!多谢上面热烈的讨论
(331073497)

出0入0汤圆

发表于 2010-8-31 15:44:17 | 显示全部楼层
MARK,楼上几位高人说的很详细啊,基本上这算是入门的人必经问的一问了。
(330897733)

出0入0汤圆

发表于 2010-9-2 16:33:41 | 显示全部楼层
mark
(330808067)

出0入0汤圆

发表于 2010-9-3 17:28:07 | 显示全部楼层
用vsprintf吧。

char printbuffer[256];

int my_printf(const char *format,...)
{
    int chars;
    va_list ap;
   
    va_start(ap, format);
    chars = vsprintf(printbuffer, format, ap);
    va_end(ap);
   
    putstring(printbuffer,chars);

    return chars ;
}

记得带上头文件 stdarg.h
(330635463)

出0入0汤圆

发表于 2010-9-5 17:24:51 | 显示全部楼层
mark printf
(329671356)

出0入0汤圆

发表于 2010-9-16 21:13:18 | 显示全部楼层
mark printf
(329670807)

出0入0汤圆

发表于 2010-9-16 21:22:27 | 显示全部楼层
学习
(318912821)

出0入0汤圆

发表于 2011-1-19 09:42:13 | 显示全部楼层
mark
(318911489)

出0入0汤圆

发表于 2011-1-19 10:04:25 | 显示全部楼层
不用这么麻烦,给你参考一下,非常好用:
头文件自己包含进去吧,编译器自带的

void USART2PC_printf(char *fmt, ...)
{
        char buffer[CMD_BUFFER_LEN+1]; // length自己定义
        u8 i = 0;
       
        va_list arg_ptr;
        va_start(arg_ptr, fmt);  
        vsnprintf(buffer, CMD_BUFFER_LEN+1, fmt, arg_ptr);
        while ((i < CMD_BUFFER_LEN) && buffer)
        {
                USART_SendData(USART2, (u8) buffer[i++]);
                while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);  
        }
        va_end(arg_ptr);
}
(304390650)

出0入0汤圆

发表于 2011-7-6 11:38:24 | 显示全部楼层
好贴!!!!!!
(304382747)

出0入0汤圆

发表于 2011-7-6 13:50:07 | 显示全部楼层
好贴!!!!!!
(302118006)

出0入0汤圆

发表于 2011-8-1 18:55:48 | 显示全部楼层
真不错
(294927328)

出0入0汤圆

发表于 2011-10-24 00:20:26 | 显示全部楼层
mark
(281192452)

出0入0汤圆

发表于 2012-3-30 23:35:02 | 显示全部楼层
31楼的方法用得很多,keil,iar,ads,avrstdio都可以。picc不行
(279086069)

出0入0汤圆

发表于 2012-4-24 08:41:25 | 显示全部楼层
zaxaca 发表于 2011-1-19 10:04
不用这么麻烦,给你参考一下,非常好用:
头文件自己包含进去吧,编译器自带的



你的函数vsnprintf(buffer, CMD_BUFFER_LEN+1, fmt, arg_ptr);  
USART_SendData(USART2, (u8) buffer[i++]);
va_end(arg_ptr);
是从哪里来的?怎么写?
(277672629)

出0入0汤圆

发表于 2012-5-10 17:18:45 | 显示全部楼层
好贴,记一下有用。
(267739306)

出0入0汤圆

发表于 2012-9-2 16:34:08 | 显示全部楼层
好贴 ,明天上班再实时 应该能解决我得问题了
(243125491)

出0入0汤圆

发表于 2013-6-14 13:44:23 | 显示全部楼层
学习了,这个帖子不错
(230244291)

出0入0汤圆

发表于 2013-11-10 15:51:03 | 显示全部楼层
我想问下这段禁止使用半主机模式代码是不是在RVMDK当中需要加,在IAR当中就不需要加了
#pragma import(__use_no_semihosting_swi)            
//标准库需要的支持函数                 
struct __FILE
{
    int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;  
      
//定义_sys_exit()以避免使用半主机模式   
void _sys_exit(int x)
{
        x = x;
}

在IAR当中直接重写fputc函数就可以了吧?
(220207444)

出0入0汤圆

发表于 2014-3-6 19:51:50 | 显示全部楼层
大家讨论的是STM32 ,AVR?我的K60也出现这个问题了,而且解决不了,
(202846729)

出0入0汤圆

发表于 2014-9-23 18:17:05 | 显示全部楼层
__stm32f100__ 发表于 2009-2-22 19:46
都是调用putchar函数。

只是设置Full的时候,putchar函数调用了又调用fputc函数,所以重写fputc也可以。

解释的很清楚,学习了,谢谢
(199134689)

出0入0汤圆

发表于 2014-11-5 17:24:25 | 显示全部楼层
mark,有空试试.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号 )

GMT+8, 2021-2-26 12:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表