stm32标准库usart1,usrat2,usart3三个串口的配置以及printf重定向(串口输出)

本文主要是介绍stm32标准库usart1,usrat2,usart3三个串口的配置以及printf重定向(串口输出),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        我刚开始学串口时,因为要用到多个串口,自己又懒得改,总是在网上要找半天。下面将stm32的三个串口配置罗列下来,方便大家直接copy。

1、串口1

引脚:TX:PA9;

           RX:PA10;

重定向函数:printf();

usart.c

#include "sys.h"
#include "usart.h"	  
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#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((USART2->SR&0X40)==0);//循环发送,直到发送完毕   USART2->DR = (u8) ch;      return ch;
}
#endif #if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  void uart1_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟//USART1_TX   GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX	  GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器//USART 初始化设置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); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE);                    //使能串口1 }void USART1_IRQHandler(void)                	//串口1中断服务程序
{u8 Res;
#if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntEnter();    
#endifif(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res =USART_ReceiveData(USART1);	//读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始else USART_RX_STA|=0x8000;	//接收完成了 }else //还没收到0X0D{	if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  }		 }}   		 } 
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntExit();  											 
#endif
} 
#endif	

usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" #define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart1_init(u32 bound);
#endif

2、串口2

引脚:TX:PA2;

           RX:PA3;

重定向函数:u2_printf();

usart2.c

#include "sys.h"
#include "usart2.h"	  
#include <stdarg.h>
#include <string.h>u8 USART_RX_BUF2[USART_REC_LEN];
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA2=0;       //接收状态标记	  void uart2_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);	//使能USART2时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//使能GPIOA时钟USART_DeInit(USART2);  //复位串口2//USART1_TX   GPIOA.2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2//USART1_RX	  GPIOA.3初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3 //Usart2 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;  //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器//USART 初始化设置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(USART2, &USART_InitStructure); //初始化串口2USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART2, ENABLE);                    //使能串口2 }void USART2_IRQHandler(void)                	//串口2中断服务程序
{u8 Res;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res =USART_ReceiveData(USART2);	//读取接收到的数据if((USART_RX_STA2&0x8000)==0)//接收未完成{if(USART_RX_STA2&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA2=0;//接收错误,重新开始else USART_RX_STA2|=0x8000;	//接收完成了 }else //还没收到0X0D{	if(Res==0x0d)USART_RX_STA2|=0x4000;else{USART_RX_BUF2[USART_RX_STA2&0X3FFF]=Res ;USART_RX_STA2++;if(USART_RX_STA2>(USART_REC_LEN-1))USART_RX_STA2=0;//接收数据错误,重新开始接收	  }		 }}   		 } }char UART2_TX_BUF[200];
void u2_printf(char* fmt, ...)    //无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表
{u16 i, j;va_list ap;          //va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。va_start(ap, fmt);   //va_start函数来获取参数列表中的参数,使用完毕后调用va_end()结束vsprintf((char*)UART2_TX_BUF, fmt, ap);	// 把生成的格式化的字符串存放在这里va_end(ap);i = strlen((const char*)UART2_TX_BUF);              //此次发送数据的长度for(j = 0; j < i; j++)                                                    //循环发送数据{while((USART2->SR & 0X40) == 0);                    //循环发送,直到发送完毕USART2->DR = UART2_TX_BUF[j];}
}

usart2.h

#ifndef __USART2_H
#define __USART2_H
#include "stdio.h"	
#include "sys.h" #define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART2_RX 			1		//使能(1)/禁止(0)串口1接收extern u8  USART_RX_BUF2[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA2;         		//接收状态标记	void uart2_init(u32 bound);
void u2_printf(char* fmt, ...);
#endif

3、串口3

引脚:TX:PB10;

           RX:PB11;

重定向函数:u3_printf();

usart3.c

#include "sys.h"
#include "usart3.h"
#include "stdarg.h"	 	 
#include "stdio.h"	 	 
#include "string.h"	
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif#if EN_USART3_RX
u8  USART3_RX_BUF[USART3_REC_LEN]; 	//接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
u8  USART3_TX_BUF[USART3_SED_LEN]; 	//发送缓冲,最大USART3_SED_LEN个字节.末字节为换行符
u16 USART3_RX_STA = 0;         			//接收状态标记	void u3_printf(char* fmt,...)  
{  u16 i,j; va_list ap; va_start(ap,fmt);vsprintf((char*)USART3_TX_BUF,fmt,ap);va_end(ap);i=strlen((const char*)USART3_TX_BUF);		//此次发送数据的长度for(j=0;j<i;j++)							//循环发送数据{while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   USART_SendData(USART3,USART3_TX_BUF[j]); } 
}void uart3_init(u32 bound)
{NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	// GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能USART_DeInit(USART3);  //复位串口3//USART3_TX   PB10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10//USART3_RX	  PB11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;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(USART3, &USART_InitStructure); //初始化串口	3USART_Cmd(USART3, ENABLE);                    //使能串口 //使能接收中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断   //设置中断优先级NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器USART3_RX_STA=0;		//清零
}void USART3_IRQHandler(void) // 串口3中断服务函数
{u8 res;if(USART_GetITStatus(USART3,USART_IT_RXNE)) // 中断标志{res= USART_ReceiveData(USART3);  // 串口3 接收if((USART3_RX_STA&0x8000)==0)//接收未完成{if(USART3_RX_STA&0x4000)//接收到了0x0d{if(res!=0x0a)USART3_RX_STA=0;//接收错误,重新开始else USART3_RX_STA|=0x8000;	//接收完成了 }else{ 							//还没收到0X0Dif(res==0x0d)USART3_RX_STA|=0x4000;else{USART3_RX_BUF[USART3_RX_STA&0X3FFF]=res ;USART3_RX_STA++;if(USART3_RX_STA>(USART3_REC_LEN-1))USART3_RX_STA=0;//接收数据错误,重新开始接收	  }		 }} }
}#endif

usart3.h

#ifndef __USART3_H
#define __USART3_H
#include "stdio.h"	
#include "sys.h" #define USART3_REC_LEN  			200  	//定义最大接收字节数 200
#define USART3_SED_LEN  			200  	//定义最大发送字节数 200
#define EN_USART3_RX 			1			//使能(1)/禁止(0)串口3接收
extern u8  USART3_RX_BUF[USART3_REC_LEN]; 	//接收缓冲,最大USART3_REC_LEN个字节.末字节为换行符 
extern u8  USART3_TX_BUF[USART3_SED_LEN]; 	//发送缓冲,最大USART3_SED_LEN个字节.末字节为换行符
extern u16 USART3_RX_STA;         			//接收状态标记	
void uart3_init(u32 bound);
void u3_printf(char* fmt,...);
#endif

这篇关于stm32标准库usart1,usrat2,usart3三个串口的配置以及printf重定向(串口输出)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1029205

相关文章

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle

如何配置Spring Boot中的Jackson序列化

《如何配置SpringBoot中的Jackson序列化》在开发基于SpringBoot的应用程序时,Jackson是默认的JSON序列化和反序列化工具,本文将详细介绍如何在SpringBoot中配置... 目录配置Spring Boot中的Jackson序列化1. 为什么需要自定义Jackson配置?2.

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

Spring中配置ContextLoaderListener方式

《Spring中配置ContextLoaderListener方式》:本文主要介绍Spring中配置ContextLoaderListener方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录Spring中配置ContextLoaderLishttp://www.chinasem.cntene

浅谈配置MMCV环境,解决报错,版本不匹配问题

《浅谈配置MMCV环境,解决报错,版本不匹配问题》:本文主要介绍浅谈配置MMCV环境,解决报错,版本不匹配问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录配置MMCV环境,解决报错,版本不匹配错误示例正确示例总结配置MMCV环境,解决报错,版本不匹配在col

Nginx中配置HTTP/2协议的详细指南

《Nginx中配置HTTP/2协议的详细指南》HTTP/2是HTTP协议的下一代版本,旨在提高性能、减少延迟并优化现代网络环境中的通信效率,本文将为大家介绍Nginx配置HTTP/2协议想详细步骤,需... 目录一、HTTP/2 协议概述1.HTTP/22. HTTP/2 的核心特性3. HTTP/2 的优

Python 安装和配置flask, flask_cors的图文教程

《Python安装和配置flask,flask_cors的图文教程》:本文主要介绍Python安装和配置flask,flask_cors的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,... 目录一.python安装:二,配置环境变量,三:检查Python安装和环境变量,四:安装flask和flas

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.