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 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u152109648494 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd8451015004 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼4 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志4 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi4 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan5 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘5 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展5 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司5 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设