持续关注阿杰在线更新保姆式笔记~~坚持日更
参考资料:
《STM32F1开发指南-库函数版本》- 5.3 usart串口文件夹介绍
-第9章 串口实验
《STM32中文参考手册V10》-第25章通用同步异步收发器(USART)
片上外设GPIO配置 --《STM32中文参考手册V10》-8.1.11 外设的GPIO配置
片上外设对应的GPIO可查询对应的数据手册,如正点原子的精英板可用《STM32F103ZET6》
目录
一、串行通信接口背景知识
处理器与外部设备通信的两种方式:
串行通信按照数据传送方向,分为:
串行通信的通信方式:
常见的串行通信接口:
STM32的串口通信接口:
串口通信的三种方式:
二、物理层
三、 协议层
四、STM32的USART简介
五、USART功能框图剖析
六、开发板与上位机的连接
七、STM32串口常用寄存器和库函数
八、串口配置一般步骤
九、代码 区
串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,其通讯协议可分层为协议层和物理层。物理层规定通信协议中具有机械、电子功能的特性,从而确保原始数据在物理媒体的传播;协议层主要规定通讯逻辑,统一双方的数据打包、解包标准。通俗的讲物理层规定我们用嘴巴还是肢体交流,协议层规定我们用中文还是英文交流。下面分析一下串口通讯协议的物理层和协议层。
USART(Universal Synchronous/Asynchronous Receiver/Transmitter):通用同步/异步串行接收/发送器
UART(Universal Asynchronous Receiver/Transmitter):通用异步收发传输器
一、串行通信接口背景知识
处理器与外部设备通信的两种方式:
-传输原理:数据各个位同时传输。
-优点:速度快
-缺点:占用引脚资源多
-传输原理:数据按位顺序传输。
-优点:占用引脚资源少
-缺点:速度相对较慢
串行通信按照数据传送方向,分为:
数据传输只支持数据在一个方向上传输
允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。
串行通信的通信方式:
-SPI,IIC通信接口
异步通信:不带时钟同步信号。
-UART(通用异步收发器),单总线
常见的串行通信接口:
STM32的串口通信接口:
大容量STM32F10x系列芯片,包含3个USART和2个UART
串口通信的三种方式:
1、中断方式进行串口通信
中断方式可以在接收到信息或需要发送数据时产生中断,在中断服务程序中完成数据的接收与发送。相对于查询方式,中断方式的CPU利用率要高。在CPU任务简单的系统中,使用中断方式确实是一种好方法。但是在复杂的系统中,比如移动机器人,处理器需要处理串行口通信,多个传感器数据的采集以及处理,实时轨迹的生成,运动轨迹插补以及位置闭环控制等等任务,牵扯到多个中断的优先级分配问题。为了保证数据发送与接收的可靠性,需要把UART的中断优先级设计较高,但是系统可能还有其他的需要更高优先级的中断,必须保证其定时的准确,这样就有可能造成串行通讯的中断不能及时响应,从而造成数据丢失。
2、DMA方式进行串口通信
DMA是 Direct Memory Access的缩写,意思是“存储器直接访问”,它是一种高速的数据传输操作,允许在外部设备和存储器之间直接读/写数据,即不通过CPU,也不需要 CPU干预。整个数据传输操作是在一个称作DMA控制器的控制下进行的。CPU除了在数据传输开始和结束时做一点处理外,在传输过程中可以进行其他的工作。这样,在大部分时间里,CPU和输入/输出设备都处于并行的操作状态。其基本原理可以查阅教科书,此处不赘述。
3、查询式进行串口通信
查询方式下CPU的负担较重,浪费了处理器的能力,不能够很好的处理其他的事件
UART异步通信方式引脚
-RXD:数据输入引脚。数据接受。
-TXD:数据发送引脚。数据发送。
UART异步通信方式特点:
-发送和接受共用的可编程波特率,最高可达4.5Mbits/s
串口通信过程
STM32串口异步通信需要定义的参数:
二、物理层
1.通讯结构
串口通讯的物理层的主要标准是RS-232标准,其规定了信号的用途、通讯接口及信号的电平标准,其通讯结构如下:
在设备内部信号是以TTL电平标准传输的,设备之间是通过RS-232电平标准传输的,而且TTL电平需要经过电平转换芯片才能转化为RS-232电平,RS-232电平转TTL电平也是如此。
2.电平标准
根据使用的电平标准不同,串口通讯可分为 RS-232标准 及TTL标准,具体标准如下:
在电子电路中常使用TTL的电平标准,但其抗干扰能力较弱,为了增加串口的通讯距离及抗干扰能力,使用RS-232电平标准在设备之间传输信息,经常使用MA3232芯片对TTL电平及RS-232电平进行相互转换。
三、 协议层
1.数据包
串口通讯的数据包由发送设备通过自身的TXD接口传输到接收设备得RXD接口,在协议层中规定了数据包的内容,具体包括起始位、主体数据(8位或9位)、校验位以及停止位,通讯的双方必须将数据包的格式约定一致才能正常收发数据。
在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。
串口收发数据的单位:字节 (Byte) , 1Byte = 8 bits , 串口收发数据格式一般为 :1bit 起始位(一般为0) + 8bits 数据位(一字节) + 1bit 校验位(可有可无) + 1bit结束位(一般为1)
2.波特率
由于异步通信中没有时钟信号,所以接收双方要约定好波特率,即每秒传输的码元个数,以便对信号进行解码,常见的波特率有4800、9600、115200等。STM32中波特率的设置通过串口初始化结构体来实现。
3.起始和停止信号
数据包的首尾分别是起始位和停止位,数据包的起始信号由一个逻辑0的数据位表示,停止位信号可由0.5、1、1.5、2个逻辑1的数据位表示,双方需约定一致。STM32中起始和停止信号的设置也是通过串口初始化结构体来实现。
4.有效数据
有效数据规定了主题数据的长度,一般为8或9位,其在STM32中也是通过串口初始化结构体来实现的。
5.数据校验
在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校(even)、 0 校验(space)、 1 校验(mark)以及无(noparity)。这些也都可以在串口初始化结构体中实现的。
四、STM32的USART简介
USART(通用同步异步收发器)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART,它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一USART 通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。
STM32中一共有5个USART,如示:
USART的USB转串口原理图如下:
USART1的发送和接收端口是事先连接好的,如果要使用其他USART只需要将相应的发送接收端口按图连接好即可。
USART有多个中断请求事件:
五、USART功能框图剖析
下文结合图片看加深理解。
1、功能引脚
TX:发送数据输出引脚。
RX:接收。
SW_RX:数据接收引脚,属于内部引脚。
nRTS:请求以发送,n表示低电平有效。如果使能 RTS 流控制,当USART接收器准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send),n表示低电平有效。如果使能 CTS流控制,发送器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。
USART:下图是STM32F103VET6芯片的USART引脚
USART1的时钟来源于APB2总线时钟,最大频率为72MHZ,其他4个时钟来源于APB1总线时钟,最大频率36MHZ。UART只有异步传输功能,没有SCLK、nCTS和nRTS功能引脚。
2.数据寄存器
USART说数据寄存器(USART_DR)只有低 9 位有效,并且第 9 位数据是否有效要取决于USART 控制寄存器 1(USART_CR1)的 M 位设置,当 M 位为 0 时表示 8 位数据字长,当 M位为 1 表示 9 位数据字长,我们一般使用 8位数据字长。
USART_DR包含了已发送的数据或者接收到的数据。USART_DR实际是包含了两个寄存器,一个专门用于发送的可写 TDR,一个专门用于接收的可读 RDR。当进行发送操作时,往 USART_DR写入数据会自动存储在 TDR内;当进行读取操作时,向 USART_DR读取数据会自动提取 RDR 数据。
TDR和RDR都是介于系统总线和移位寄存器之间。串行通信是一个位一个位传输的,发送时把 TDR 内容转移到发送移位寄存器,然后把移位寄存器数据每一位发送出去,接时把接收到的每一位顺序保存在接收移位寄存器内然后才转移到 RDR。
USART 支持 DMA 传输,可以实现高速数据传输。
3.控制器
USART有专门控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等。
使用USART之前需要向USART_CR1寄存器的UE位置1使能USART,UE位用于开启供给串口的时钟。发送或者接收数据字长可选8或9位,由USARTT_CR1的M位控制。
1)发送器
当USART_CR1寄存器的发送使能位TE置1时,启动数据发送,发送移位寄存器的数据会在TX引脚输出,低位在前,高位在后。如果是同步模式SCLK也输出时钟信号。
一个字符帧发送需要3部分:起始位、数据帧、停止位。起始位是一个位周期的低电平,位周期就是每一位占用的时间 ;数据帧就是我们要发送的8或9位数据,数据是最低位开始传输的;停止位是一定时间周期的高电平。
停止位的时间长短可以通过USART控制寄存器2(USART_CR2)的STOP[1:0]位控制,可选0.5个、1个、1.5个、2个停止位。默认使用1个停止位。2个停止位适用于正常USART模式、单线模式和调制解调器模式。0.5和1.5个停止位用于智能卡模式。
当发使能位TE置1之后,发送器开始会发送一个空闲帧(一个数据帧长度的高电平),接下来就可以往USART_DR寄存器写入要发送的数据。在写入最后一个数据后,需等待USART状态寄存器(USART_SR)的TC位为1,表示数据传输完成。USART_CR1寄存器的TCIE位置1,则产生中断。
发送数据时,几个重要的标志位如下:
TE:发送使能。
TXE:发送寄存器为空,发送单个字节时使用。
TC:发送完成,发送多个字节数据时候使用。
TXIE:发送完成中断使能。
2)接收器
将CR1寄存器的RE位置1,使能USART接收,使得接收器在RX线开始搜索起始位。在确定起始位后,就根据RX线电平状态把数据存放在接收移位寄存器内。接收完成后就把接收移位寄存器的数据移到PDR内,并把USART_SR寄存器的RXNE位置。如果USART_CR2寄存器的RXNEIE置1可以产生中断。
接收数据时,几个重要的标志位如下:
RE: 接收使能。
RXNE:读数据寄存器非空。
RXNEIE:发送完成中断使能。
4.小数波特率生成
USART 的发送器和接收器使用相同的波特率。计算公式如下:
其中,f PLCK 为 USART 时钟, USARTDIV 是一个存放在波特率寄存器(USART_BRR)的一个无符号定点数。其中 DIV_Mantissa[11:0]位定义 USARTDIV 的整数部分,DIV_Fraction[3:0]位定义 USARTDIV 的小数部分。
例如:DIV_Mantissa=24(0x18),DIV_Fraction=10(0x0A),此时 USART_BRR 值为0x18A;那么USARTDIV的小数位10/16=0.625;整数位24,最终USARTDIV的值为24.625。
如果知道 USARTDIV 值为 27.68,那么 DIV_Fraction=16*0.68=10.88,最接近的正整数为 11,所以 DIV_Fraction[3:0]为 0xB;DIV_Mantissa=整数(27.68)=27,即为 0x1B。
波特率的常用值有 2400、9600、19200、115200。下面以实例讲解如何设定寄存器值得到波特率的值。
我们知道 USART1 使用 APB2 总线时钟,最高可达 72MHz,其他 USART 的最高频率为 36MHz。我们选取 USART1 作为实例讲解,即 f PLCK =72MHz。为得到 115200bps 的波特率,此时:
115200 =72000000/(16 ∗ USARTDIV)
解 得 USARTDIV=39.0625 , 可 算 得 DIV_Fraction=0.0625*16=1=0x01 ,DIV_Mantissa=39=0x27,即应该设置 USART_BRR 的值为 0x171。
5.校验控制
STM32F103系列控制器USART支持奇偶校验。使用校验位时,串口传输的长度将在8位数据帧上加上1位的校验位,总共9位,此时USART_CR1寄存器的M位需要设置位1,即9数据位。将USART_CR1寄存器的PCE位置1就可以启动奇偶校验控制,奇偶校验由硬件自动完成。启动了奇偶校验控制之后,发送数据帧时会自动添加校验位,接收数据自动验证校验位。接收数据时如果出现奇偶校验位验证失败,会将USART_SR寄存器的PE置1,并可以产生奇偶校验中断。
使用了奇偶校验控制位后,每个字符帧的格式变成了:起始位+数据帧+校验位+停止位。
6.中断控制
六、开发板与上位机的连接
开发板与上位机之间通过USB线连接,所以在上位机上要配置一个USB转串口 的驱动,以便把USB传输过来的电平转换为TTL电平,TTL电平才能与串口调试助手建立联系。一般使用CH341驱动作为win10下的USB转串口,驱动安装成功的情况下接入USB会在计算机的设备管理器的端口中发现串口:
七、STM32串口常用寄存器和库函数
八、串口配置一般步骤
⑥ 开启中断:USART_ITConfig(); _usart.h->371
⑦ 初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init(); misc.h->197
-->凡是使用中断都要开启NVIC
》编写中断处理函数:USARTx_IRQHandler();startup_stm32f10x_hd.s->117
》串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
》串口传输状态获取:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
_usart.h->371
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
九、代码区
#include "led.h"
#include "delay.h"
#include "beep.h"
#include "sys.h"
#include "key.h"void My_USART1_Init(void)
{GPIO_InitTypeDef GPIO_InitStrue;USART_InitTypeDef USART_InitStrue;NVIC_InitTypeDef NVIC_InitStrue;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIOA时钟 rcc.h->693RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1//USART1_TX GPIOA.9GPIO_InitStrue.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_InitStrue.GPIO_Pin = GPIO_Pin_9;GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOA,&GPIO_InitStrue);//gpio.h->351//USART1_RX GPIOA.10初始化GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_InitStrue.GPIO_Pin = GPIO_Pin_10;GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOA,&GPIO_InitStrue);//gpio.h->351//USART 初始化设置USART_InitStrue.USART_BaudRate = 115200;//串口波特率USART_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStrue.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式USART_InitStrue.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStrue.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStrue.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_Init(USART1,&USART_InitStrue);//_usart.h->366USART_Cmd(USART1,ENABLE);//串口使能 _usart.h->370USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//打开接受中断 _usart.h->371//Usart1 NVIC 配置NVIC_InitStrue.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1NVIC_InitStrue.NVIC_IRQChannelSubPriority = 1;//子优先级1NVIC_Init(&NVIC_InitStrue);//根据指定的参数初始化VIC寄存器 misc.h->197
}void USART1_IRQHandler(void)//startup_stm32f10x_hd.s->117
{u8 res;if(USART_GetITStatus(USART1,USART_IT_RXNE))//判断是否为接受中断类型,//_usart.h->371 为避免任何中断打开都来执行下面的语句体{ res = USART_ReceiveData(USART1); //单片机(下位机)读取接收到的数据 _usart.h->379USART_SendData(USART1,res); //单片机(下位机)向串口1(即上位机 通过串口调试助手显示出来)发送数据 _usart.h->378}
}int main(void)
{ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置NVIC需分组 系统运行后先设置中断优先级分组 misc.h->196My_USART1_Init();while(1);
}