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、在串口文件中添加如下代码:
#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
当然,头文件#include "stdio.h"别忘了加上。同样的,修改相应的串口号,初始化,就能使用printf了。
如果编译的时候出现FILE __stdout;编译不过,可以打开stdio.h文件,将typedef struct __FILE FILE;
修改为
typedef struct __FILE{}FILE;
即可。
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、在串口文件中添加如下代码:
#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
当然,头文件#include "stdio.h"别忘了加上。同样的,修改相应的串口号,初始化,就能使用printf了。
如果编译的时候出现FILE __stdout;编译不过,可以打开stdio.h文件,将typedef struct __FILE FILE;
修改为
typedef struct __FILE{}FILE;
即可。
举报