printf重定向简介
C语言中printf函数默认输出设备是显示器,如果要实现在
串口或者LCD上显示,必须重定义标准库函数里调用的与输出设备相关的
函数。比如使用printf输出到串口,需要将fputc里面的输出指向串口,
这一过程就叫重定向。
那么如何让STM32使用printf函数呢?
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
printf函数格式
编写printf重定向程序
uart.h
#ifndef __usart_H
#define __usart_H
#include “system.h”
#include “stdio.h”
void USART1_Init(u32 bound);
#endif
uart.c
#include “usart.h”
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用 { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } /******************************************************************************* * 函 数 名 : USART1_Init * 函数功能 : USART1初始化函数 * 输 入 : bound:波特率 * 输 出 : 无 *******************************************************************************/ void USART1_Init(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //打开时钟 /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */ //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } /******************************************************************************* * 函 数 名 : USART1_IRQHandler * 函数功能 : USART1中断函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void USART1_IRQHandler(void) //串口1中断服务程序 { u8 r; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { r =USART_ReceiveData(USART1);//(USART1-》DR); //读取接收到的数据 USART_SendData(USART1,r); while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); } USART_ClearFlag(USART1,USART_FLAG_TC); }
main.c
#include “system.h” #include “SysTick.h” #include “led.h” #include “usart.h” /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int main() { u8 i=0; u16 data=1234; float fdata=12.34; char str[]=“Hello World!”; SysTick_Init(72); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组 LED_Init(); USART1_Init(9600); while(1) { i++; if(i%20==0) { led1=!led1; printf(“输出整型数data=%drn”,data); printf(“输出浮点型数fdata=%0.2frn”,fdata); printf(“输出十六进制数data=%Xrn”,data); printf(“输出八进制数data=%orn”,data); printf(“输出字符串str=%srn”,str); } delay_ms(10); } }
实验现象
串口打印出了想要的调试信息。
printf重定向简介
C语言中printf函数默认输出设备是显示器,如果要实现在
串口或者LCD上显示,必须重定义标准库函数里调用的与输出设备相关的
函数。比如使用printf输出到串口,需要将fputc里面的输出指向串口,
这一过程就叫重定向。
那么如何让STM32使用printf函数呢?
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
printf函数格式
编写printf重定向程序
uart.h
#ifndef __usart_H
#define __usart_H
#include “system.h”
#include “stdio.h”
void USART1_Init(u32 bound);
#endif
uart.c
#include “usart.h”
int fputc(int ch,FILE *p) //函数默认的,在使用printf函数时自动调用 { USART_SendData(USART1,(u8)ch); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); return ch; } /******************************************************************************* * 函 数 名 : USART1_Init * 函数功能 : USART1初始化函数 * 输 入 : bound:波特率 * 输 出 : 无 *******************************************************************************/ void USART1_Init(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //打开时钟 /* 配置GPIO的模式和IO口 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TX //串口输出PA9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化串口输入IO */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RX //串口输入PA10 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //模拟输入 GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */ //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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); //初始化串口1 USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } /******************************************************************************* * 函 数 名 : USART1_IRQHandler * 函数功能 : USART1中断函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void USART1_IRQHandler(void) //串口1中断服务程序 { u8 r; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { r =USART_ReceiveData(USART1);//(USART1-》DR); //读取接收到的数据 USART_SendData(USART1,r); while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET); } USART_ClearFlag(USART1,USART_FLAG_TC); }
main.c
#include “system.h” #include “SysTick.h” #include “led.h” #include “usart.h” /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int main() { u8 i=0; u16 data=1234; float fdata=12.34; char str[]=“Hello World!”; SysTick_Init(72); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组 LED_Init(); USART1_Init(9600); while(1) { i++; if(i%20==0) { led1=!led1; printf(“输出整型数data=%drn”,data); printf(“输出浮点型数fdata=%0.2frn”,fdata); printf(“输出十六进制数data=%Xrn”,data); printf(“输出八进制数data=%orn”,data); printf(“输出字符串str=%srn”,str); } delay_ms(10); } }
实验现象
串口打印出了想要的调试信息。
举报