在STM32中使用printf函数

一、目的

    利用printf函数使得输出打印到串口中。

二、工作原理

    我们在C语言中为什么能够调用printf函数打印数据到控制台中,那是因为printf函数又调用了fputc()函数。那么我们我们可不可以说printf函数之所以能够打印数据到控制台中几乎都是fput()函数的功劳呢?答案是显而易见的。因此,在这我们只需要重写fput函数即可。

三、代码展示

1、重写fput()函数

    在这里我们需要注意的是,在实际的代码运行过程中该函数是自调用的,不需要我们刻意调用它。

/******************************************************************************
*	函数功能 相当于串口发送数据
*	参数 
*	返回值
*	注意 该函数是stdio.h文件中默认函数 当我们使用printf函数时会自调用
*		 这里的printf函数跟C语言的printf用法一样
******************************************************************************/
int fputc(int ch,FILE *p)
{
	USART_SendData(USART1,(u8)ch);	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
	return ch;
}

2、GPIO初始化

/****************************************************************
*	函数功能	printf的初始化
*	参数	无
*	返回值	无
****************************************************************/
void printf_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef  USART_InitStructure;
	
	/*  打开端口时钟  */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*  配置GPIO的模式和IO口 */
	//选择TX		 串口输出PA9
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;	
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	 //复用推挽输出
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;	   
	GPIO_Init(GPIOA,&GPIO_InitStructure);  
	/* 初始化串口输入IO */
	//选择RX	串口输入PA10
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	  //模拟输入
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;		
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	/*  USART串口初始化  */
	//波特率设置为9600	
	USART_InitStructure.USART_BaudRate=9600;   
	//数据长8位
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;	
	//1位停止位	
	USART_InitStructure.USART_StopBits=USART_StopBits_1;		
	//无效验	
	USART_InitStructure.USART_Parity=USART_Parity_No;				
	//失能硬件流
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; 
	//开启发送和接受模式
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;	 
	USART_Init(USART1,&USART_InitStructure);	
	
	/* 使能USART1 */
	USART_Cmd(USART1, ENABLE);		   
	//使能或者失能指定的USART中断 接收中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	//清除USARTx的待处理标志位	
	USART_ClearFlag(USART1,USART_FLAG_TC);
}

3、一个简单的hello输出

int main()
{
	printf_init();
	while(1)
	{		
		printf("hello!");
	}
}

四、keil中的配置

    实际上直接使用上述代码是不能够完成我们最初的设计目的的,单单这样它不会输出任何东西到串口中,我们还需要在keil中小小的配置一下。样例如下图:
在这里插入图片描述

五、总结

    小编个人认为,在这个项目中,实际上的printf函数就是一个串口输出函数,只不过它相比之前我们直接调用串口发送函数更加方便、更加实用,无非是在GPIO的定义与初始化上有点儿区别。因此,我们完全可以将printf函数看成一个串口发送函数。

  • 10
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32使用printf函数输出信息需要进行重定向。通过重定向,可以将printf函数的输出发送到仿真器连接的PC机上的终端窗口。具体实现方法如下: 1. 首先,需要在工程添加一个文件,命名为retarget.c,并将其加入到工程。 2. 在retarget.c文件,需要实现fputc函数,该函数将会被printf函数调用。在fputc函数,可以利用ITM(Instrumentation Trace Macrocell)机制提供的寄存器,将数据发送给仿真器,然后仿真器将数据发送到PC机上的终端窗口。以下是一个示例的fputc函数的实现: ```c #include <stdio.h> #define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000 + 4*n))) #define ITM_Port16(n) (*((volatile unsigned short *)(0xE0000000 + 4*n))) #define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000 + 4*n))) #define DEMCR (*((volatile unsigned long *)(0xE000EDFC))) #define TRCENA 0x01000000 struct __FILE { int handle; /* Add whatever you need here */ }; FILE __stdout; FILE __stdin; int fputc(int ch, FILE *f) { if (DEMCR & TRCENA) { while (ITM_Port32(0) == 0); ITM_Port8(0) = ch; } return ch; } ``` 3. 在工程的main函数,需要添加以下代码来重定向printf函数的输出: ```c #include <stdio.h> extern void initialise_monitor_handles(void); int main() { initialise_monitor_handles(); // 其他代码 printf("Hello, world!"); // 其他代码 return 0; } ``` 通过以上步骤,就可以在STM32使用printf函数并将输出重定向到仿真器连接的PC机上的终端窗口了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值