2、怎么对printf重定向的?

原文见这篇文章.以及这篇.

调试代码时,需要将需要的信息发送到串口,这就要对printf进行重定向,正点原子的重定向代码如下:

//printf打印串口函数
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{
      
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{
      
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{
      	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif 

代码是使用标准库+fputc的方式。

问题1:阐述标准库中的printf与fputc的功能

printf 定义在 头文件中,如下:

int printf(const char *format, ...);

printf 函数根据 format 字符串给出的格式打印输出到 stdout(标准输出)中,当然,printf 函数是不会一个字符一个字符去输出,它会调用更底层的 I/O 函数:fputc去逐个字符打印。
fputc 也定义于头文件 中,如下:

int fputc(int ch, FILE *stream);

fputc 函数写入字符 ch 到给定输出流 stream,printf函数在调用该函数时,会向stream参数传入stdout从而打印数据到标准输出。

那么,要实现printf打印到串口就变得非常简单了,只需要重新定义fputc函数,在fputc的函数中将数据通过串口发送,称之为:fputc重定向或者printf重定向。

问题2、如何使用MicroLib重定向printf
MicroLib是对标准C库进行了高度优化之后的库,供MDK默认使用,相比之下,MicroLIB的代码更少,资源占用更少:

#if 0
#include 

int fputc(int ch, FILE *stream)
{
     
    /* 堵塞判断串口是否发送完成 */
    while((USART1->SR & 0X40) == 0);

    /* 串口发送完成,将该字符发送 */
    USART1->DR = (u8) ch;

    return ch;
}
#endif

问题3、如何使用标准库重定向printf
printf 函数使用了半主机模式,所以直接使用标准库会导致程序无法运行,因此必须提前告知编译器不使用半主机模式:

//方法1:使用标准库来重定向printf
#if 1

//告诉链接器不从标准库链接使用半主机的函数
#pragma import(__use_no_semihosting) 

//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{
      
	x = x; 
} 

//标准库需要的支持类型          
struct __FILE 
{
      
	int handle; 
}; 

FILE __stdout;       

//重定义fputc函数 
int fputc(int ch, FILE *stream)
{
      	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif 

也可以自己实现一个打印函数
过程见原文。

你可能感兴趣的:(STM32杂谈)