printf 函数一般是打印到终端的, stm32 芯片调试中经常需要用到串口来打印调试信息, 那能不能用串口实现类似 windows 的 Console 中的 printf 呢?
答案是肯定的, 那就是 printf 函数的重定向.
使用 KEIL5 对 stm32 的 printf 函数进行重定向, 有两种方法: 一种是使用微库, 另一种是不使用微库.
方法 1-- 使用微库:
1, 使用微库, 在 KEIL5 中点击 options for target, 在 Target 标签下有个 Use MicroLIB--- 勾选, 使用微库.
2, 在串口文件中添加如下代码:
- #include "stdio.h"
- #ifdef __GNUC__
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE* f)
- #endif /* __GNUC__ */
- #ifdef __cplusplus
- extern "C" {
- #endif //__cplusplus
- PUTCHAR_PROTOTYPE
- {
- while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
- ;
- USART_SendData(USART2, (uint8_t)ch);
- return (ch);
- }
- #ifdef __cplusplus
- }
- #endif //__cplusplus
修改相应的串口号, 初始化, 就能使用 printf 了.
方法 2-- 不使用微库 (那么就要强调不使用半主机(no semihosting) 模式)
1, 使用微库(平台式 keil-MDK), 点击 options for target, 在 Target 标签下有个 Use MicroLIB--- 取消勾选, 不使用微库.
2, 在串口文件中添加如下代码:
- #include "stdio.h"
- #ifdef __GNUC__
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE* f)
- #endif /* __GNUC__ */
- #ifdef __cplusplus
- extern "C" {
- #endif
- // 加入以下代码, 支持 printf 函数, 而不需要选择 use MicroLIB
- #pragma import(__use_no_semihosting)
- // 定义_sys_exit()以避免使用半主机模式
- void _sys_exit(int x)
- {
- x = x;
- }
- void _ttywrch(int x)
- {
- x = x;
- }
- // 标准库需要的支持函数
- struct __FILE
- {
- int handle;
- };
- FILE __stdout;
- // 重定义 fputc 函数
- PUTCHAR_PROTOTYPE
- {
- while((USART2->SR & 0X40) == 0);// 循环发送, 知道发送完毕
- USART2->DR = (u8)ch;
- return ch;
- }
- #ifdef __cplusplus
- }
- #endif //__cplusplus
同样的, 修改相应的串口号, 初始化, 就能使用 printf 了.
如果编译的时候出现 FILE __stdout; 编译不过, 可以打开 stdio.h 文件, 将 typedef struct __FILE FILE;
修改为
- typedef struct __FILE {}
- FILE;
即可.
来源: https://www.cnblogs.com/jasonchan1202/p/9673548.html