说明:该博客为汇总性质,内容皆为转载
#include
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
USART_SendData(USART1, (u16) ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
return ch;
}
之后如若编译出现identifier “FILE” is undefined,即将Options->GeneralOptions->Library Configuation中的Library选为full即可。
二、IAR中使用printf的几种方法
1、修改库文件
2、
1、option->C/C++ compiler--->defined symbols 下添加一行_DLIB_FILE_DESCRIPTOR
3、
错误 : FILE is undefined
FILE 是stdio.h 里的,所以查看这个文件
#if _DLIB_FILE_DESCRIPTOR
typedef _Filet FILE;
#endif /* _DLIB_FILE_DESCRIPTOR */
要用FILE先要开 _DLIB_FILE_DESCRIPTOR
查了一下
stdio.h中
/* Module consistency. */
#pragma rtmodel="__dlib_file_descriptor",_STRINGIFY(_DLIB_FILE_DESCRIPTOR)
再查到DLib_Defaults.h
#ifndef _DLIB_FILE_DESCRIPTOR
#define _DLIB_FILE_DESCRIPTOR 0
#endif
把0 改为1 就可以了,先去除只读属性。
三、 搜索互联网上,关于此类问题的解决文章资料也比较丰富,不过按照其思路还是遇到了不少问题。
首先,贴代码,大部分代码都是类似的方案,重写putchar或者fputc函数。
#ifdef USE_IAR
#define PUTCHAR_PROTOTYPE int putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch,FILE *f)
#endif
PUTCHAR_PROTOTYPE{
HAL_UART_Transmit(&huart1, (char *)(&(ch)), 1, 10);
return ch;
}
实际程序我定义了宏 USE_IAR,也就是实现了putchar()函数,不过实际调试,printf()函数会依次调用putchar()及fputs(),所以实际中实现其中任一一个函数即可。也就是上述的代码,即使我不定义USE_IAR,仍然是可用的。
需要注意的一点是重写的putchar()函数必须要返回ch变量,否则只会打印首个字符一次。
使用STM32的串口发送是阻塞的,也就是发送完一个字符程序才会继续运行发送下一个字符。
记得配置IAR的环境 Options->General Options->Library Configuation的Library为Full。
加入printf()函数在未使用IAR的优化功能前提下,会增加8.5KBytes左右的readonly code memory,30Bytes的readonly data memory,及2.4KBytes左右的readwrite data memory。
四、
今天看到这样一段代码,值摘取其中宏定义的部分,如下:
#define DEBUG(fmt,args...) printf("%s(%d)-%s -> " #fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##args);
相信很多初入编程界的新人朋友们(我也是新人,汗。。。),看到这就会有疑问:
1.fmt及#fmt是什么? 2.##args是什么?
在此对这些问题做一个容易理解的解释:
1.fmt就是宏定义的第一个参数,在代码中展开时直接代入,需注意的是#fmt的意思为把fmt传进来的内容以字符串形式输出。
2.args..代表一个可变化的参数表,##args如果前面的可变参数被忽略或为空,“##”操作将使预处理器去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,它会把这些可变参数放到逗号后面。
#include
#include
#define DEBUG_PRINT(fmt,args...) printf("%s(%d)-%s -> " #fmt "\n", __FILE__, __LINE__, __FUNCTION__, ##args);
void main(void)
{
char a = 'T', b = 'e', c = 's', d = 't';
DEBUG_PRINT(%c%c%c%c,a,b,c,d);
}
五、标准C只支持可变参数的函数,意味着函数的参数是不固定的,例如printf()函数
的原型为:
int printf( const char *format [, argument]... );
而在GNU C中,宏也可以接受可变数目的参数,例如:
#define pr_debug(fmt,arg...) \
printk(fmt,##arg)
这里arg 表示其余的参数可以是零个或多个,这些参数以及参数之间的逗号构成
arg 的值,在宏扩展时替换arg,例如下列代码:
pr_debug("%s:%d",filename,line)
会被扩展为:
printk("%s:%d", filename, line)
六.本人的IAR工程中用的重定向的printf配置,iar for arm,华大136平台
#define CONFIG_RELASE 0
#if (CONFIG_RELASE == 0)
#define Debug(fmt,arg...) printf(fmt,##arg)
#else
#define Debug(fmt,arg...)
#endif
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART */
//USART_SendData(USART3, (uint8_t) ch);
Uart_SendData(UARTCH0, (uint8_t) ch);
/* Loop until transmit data register is empty */
while (Uart_GetStatus(UARTCH0, UartTxe) == 0)//注意这里用的Txe而不是TC,TC在Uart_SendData函数中用的
{
}
return ch;
}
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */