STM32 printf函数重定向到USATR1输出打印

printf重定向

  • fputc函数实现
  • 使用 Use MicroLIB

usart.h

复制代码
#ifndef __USART_H
#define __USART_H

#include "system.h"
#include "stdio.h"  //要实现int fputc(int ch,FILE *p) 原型,需要包含该头文件

void USART1_Init(u32 bound);

#endif

usart.c

复制代码
#include "usart.h"

int fputc(int ch,FILE *p)  //函数默认的,函数原型不能改变,在使用printf函数时自动调用
{
	USART_SendData(USART1,(u8)ch);	
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //USART_FLAG_TXE状态标志表示可以发送下一个数据了,发送数据寄存器已经空了(发送移位寄存器数据可能没有发完)
	return ch;
}

//bound:参数为输入波特率
void USART1_Init(u32 bound)
{
	GPIO_InitTypeDef MY_GPIO_Init; //定义结构体变量
	USART_InitTypeDef USART_InitStructure; 
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//默认引脚 PA9/PA10,没有重映射 → 不需要使能 AFIO 时钟!
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能串口1时钟
	
	MY_GPIO_Init.GPIO_Pin = GPIO_Pin_9; //TX -- PA9
	MY_GPIO_Init.GPIO_Mode = GPIO_Mode_AF_PP; //设置复用推挽输出模式
	MY_GPIO_Init.GPIO_Speed = GPIO_Speed_50MHz; //设置传输速率
	GPIO_Init(GPIOA, &MY_GPIO_Init); 	 

	MY_GPIO_Init.GPIO_Pin = GPIO_Pin_10; //RX -- PA10
	MY_GPIO_Init.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置浮空输入
	MY_GPIO_Init.GPIO_Speed = GPIO_Speed_50MHz; //设置传输速率
	GPIO_Init(GPIOA, &MY_GPIO_Init); 

	
	USART_InitStructure.USART_BaudRate = bound; //设置波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; //设置数据位为8位 
	USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置停止位为1位
	USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控 
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送使能和接收使能
	USART_Init(USART1, &USART_InitStructure);	
	USART_Cmd(USART1, ENABLE); //使能 USART1串口
	
	//清除USART_FLAG_TC发送完成标志位,这个是状态标志位,并非中断标志位
	USART_ClearFlag(USART1, USART_FLAG_TC); //清除USART_FLAG_TC发送完成标志位
	
	//设置串口中断类型并使能
	//USART_IT_RXNE ------ 接收数据寄存器非空中断,"我收到了一个字节数据,已经放进接收寄存器了,快来读!"
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //我们选择的是接收中断
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //在"stm32f10x.h"查看
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	
}

void USART1_IRQHandler(void)
{
	u8 data = 0;
	
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //串口接收中断标志位,检查指定的 USART 中断发生与否,当调用接收函数时会被自动清除。
	{
		//当你调用 USART_ReceiveData() 读取数据时,硬件会自动清除 USART_IT_RXNE!
		data = USART_ReceiveData(USART1);
		USART_SendData(USART1, data); //将接收的数据发送出去
		//USART_FLAG_TC发送完成标志位,表示当移位寄存器的最后一位数据被发送到 TX 引脚,且总线空闲时,才置 1。表示数据已经完全发完,总线已经空闲。
		//USART_FLAG_TXE发送数据寄存器空,当 TDR 寄存器的数据被转移到移位寄存器后,立刻置 1,表示 "我可以写下一个数据了"。
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); //USART_FLAG_TC发送完成标志位
		//while(USART_GetITStatus(USART1, USART_FLAG_TC) != SET); //开始错用了这个函数,导致中断程序在这里卡死!!!
	}
	USART_ClearFlag(USART1, USART_FLAG_TC); //清除USART_FLAG_TC发送完成标志位,这个是状态标志位,并非中断标志位
}	

main.c

复制代码
#include "system.h"  //已经包含了"stm32f10x.h" 以及定义了位带操作的宏,后续只包含该头文件就可以了
#include "SysTick.h" //使用delay_ms和delay_us
#include "usart.h"
#include "led.h" //需要调用Led_Init()对8个LED GPIO初始化
#include "stdio.h" //使用printf函数时需要包含

//这里不用定义SystemInit函数,是因为在system_stm32f10x.c中已有实现

int main()
{
	u8 i = 0;
	u16 j = 0;
	u16 data = 1234;
	float fdata=12.34;
	char str[]="Hello World!";	
	
	SysTick_Init(72); //72为SYSCLK delay_ms延时函数需要使用
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组2:2 在使用中断回调函数时都需要调用
	Led_Init();
	USART1_Init(9600); //在之后才能使用printf函数
	
	while(1)
	{
		i++;
		if(i%20 == 0)
		{
			PCout(4) = !PCout(4); //LED5状态取反 20*10ms = 200ms
			
			j++;
			if(j%25 == 0) //5S打印一次
			{
				printf("打印整数类型 data = %d\r\n", data);
				printf("打印浮点数 fdata = %f\r\n", fdata);
				printf("打印字符串 str = %s\r\n", str);
			}
		}
		delay_ms(10);	
	}	
}

现象,每间隔5S打印一次,如图:

相关推荐
踏着七彩祥云的小丑4 小时前
嵌入式——认识电子元器件——温度保险丝系列
单片机·嵌入式硬件
12.=0.4 小时前
【stm32_6.1】串行异步接口USART,串口的原理和应用
c语言·stm32·单片机·嵌入式硬件
雅斯驰5 小时前
4Gbit密度+16位总线宽度:H5AN4G6NBJR-UHC在DDR4成熟期的产品定位
运维·单片机·嵌入式硬件·物联网·自动化
weixin_456808385 小时前
【沁恒蓝牙开发】电压监控
单片机·嵌入式硬件
LCG元5 小时前
STM32实战:基于RT-Thread的STM32开发环境搭建与LED任务
stm32·单片机·嵌入式硬件
ye150127774555 小时前
220V转12V1000mA恒流驱动WT5112
单片机·嵌入式硬件·其他·硬件工程
青山_FPGA5 小时前
以太网 MAC-PHY 接口总结
嵌入式硬件·macos
振南的单片机世界5 小时前
函数调用时,返回地址和局部变量都存“栈”里
stm32·单片机·嵌入式硬件
ye150127774556 小时前
220V降12V降24V风扇驱动WT5112
单片机·嵌入式硬件·其他·硬件工程