前言
stm32串口通信是开发中比较常用的功能,基本大家都会需要它来向别的设备或者PC端传递一些信息。然而大多数人却不能很好地设计一个好的串口驱动。对于新手或者比较懒的人一般直接赋值粘贴的网上的代码,一般这些代码包含三个功能:初始化、发送数据、中断入口函数。然后稍微变更一下端口号波特率之类的配置就可以用了。若只是调试这样用也无可厚非,但若要加入到一个系统中则有些不太严谨,对于一个系统来说追求的是占用最少的资源来实现一些外设功能。直接赋值粘贴的代码存在如下问题:
1、通用性比较弱,如初始化函数需要在不同的地方直接更改设置,规范的写法应该将基本配置放在头文件并使用宏定义集中配置。
2、对于STM32来说比较占用资源,如发送函数一般是阻塞发送,而串口通讯速率又相对较低,势必会消耗占用系统时间
3、频繁进入中断来接收数据,一般串口中断会开启接收缓存区非空中断,即每次接收一个字节都要进入一次中断,这样中断资源势必吃紧
总之如果仅仅测试可以随意,但当开发中如果感觉资源不够可以参考本文串口驱动。使用这个驱动的好处是配置简单、后台发送和接收不占用资源、调用简单。驱动适用于STM32F4系列,使用标准外设库。其他系列也可以做参考,因为本文注重介绍的是思路。
串口通信简介
首先还是先简单介绍下串口通信,一般串口通信包含两个接线口:TX接口和RX接口。通讯不分主从直接连接,如设备1和设备2连接时需要交叉连接,即设备1的TX接设备2的RX,设备1的RX接设备2的TX。然后双方使用同一个串口配置即可成功通讯,一般串口设置包括波特率、数据位数、停止位数、校验位数。如果这些不太懂可以百度之,这里就不详细介绍了,其实都是和硬件时序有关。这里向大家普及下波特率,原来一直不太懂波特率,如波特率9600代表什么,其实波特率单位是bps,翻译一下即为bits per second,即比特/每秒。我们一般接收数据都是以字节接收到单片机的,所以有人可能会误认为9600波特率代表每秒9600个字节数据,其实是错的。如下图是使用逻辑分析仪抓取的一个以9600波特率通讯的字节波形
这里使用了标准的配置,数据位是8 bit,停止位 1bit,再加上1 bit起始位一共是10 bit。所以若满负载发送时(即两个字节之间没有空隙)其发送速率为9600/10=960 bytes/s。图上A1和A2之间为这个字节的起始位,测试发现A1-A2=104.16us,这个数大小约为1000000us/9600,这也印证了9600指的是比特而不是字节。
STM32 USART通讯
既然是基于STM32的设计所以这里还需要介绍USART通讯。这里着重介绍下几个寄存器和程序。
stm32关于串口的寄存器列表如下:
寄存器 | 描述 |
---|---|
USART_SR | 状态寄存器 |
USART_DR | 数据寄存器 |
USART_BRR | 波特率寄存器 |
USART_CR1 | 控制寄存器 1 |
USART_CR2 | 控制寄存器 2 |
USART_CR3 | 控制寄存器 3 |
对于一般我们复制的初始化程序一般如下
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOC时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//使能USART4时钟
//串口4对应引脚复用映射
GPIO_PinAFConfig(GPIOC,GPIO_PinSource10,GPIO_AF_UART4); //GPIOA10复用为USART4
GPIO_PinAFConfig(GPIOC,GPIO_PinSource11,GPIO_AF_UART4); //GPIOA11复用为USART4
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //GPIOA10与GPIOA11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化
//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(UART4, &USART_InitStructure); //初始化串口4
USART_ITConfig