STM32系列 USART通信

0 前言

UART:通用异步收发传输器,是一种通用串行数据线,用于异步通信,双向通信,可以实现全双工传输和接收。
USART:通用同步/异步串行收发器,是一个全双工通用同步/异步串行收发模块。
USART收发模块分为三个部分:时钟发生器、数据发送器和接收器。
时钟发生器由同步逻辑电路(在同步从模式下由外部时钟输入驱动)和波特率发生器组成。发送时钟引脚XCK仅用于同步发送模式下。
发送器部分由一个单独的写入缓冲器(发送UDR)、一个串行移位寄存器、校验位发生器和用于处理不同帧结构的控制逻辑电路构成。使用吸入缓冲器,实现了连续发送多帧数据无延时的通信。
接收器最主要的是时钟和数据接收单元。数据接收单元用作异步数据的接收。除了接收单元,接收器还包括校验位校验器、控制逻辑、移位寄存器和两级接收缓冲器(接收UDR)。接收器支持与发送器相同的帧结构,同时支持帧错误、数据溢出和校验错误的检测。
UART和USART的区别:
从名字上看,USART在UART基础上增加了同步功能,即USART是UART的增加型,使用USART在异步通信时,与UART没什么区别,但是用在同步通信时,区别就明显了,同步通信需要时钟来触发数据传输,也就是说USART相对于UART能提供主动时钟。

1 简介

通用同步异步收发器(USART)能够灵活的与外部设备进行全双工数据交换,满足外部设备对工业标准NRZ异步串行数据格式的要求。通过小数波特率发生器提供了多种波特率。支持同步单向通信和半双工担心通信;还支持LIN(局域互连网络)、智能卡协议与IrDA(红外线数据协会)SIR ENDEC规范,以及调制解调器操作(CTS/RTS)。而且还支持多处理器通信。通过配置多个缓冲区使用DMA可实现高速数据通信。

2 主要特性

  • 全双工异步通信
  • NRZ标准格式(标记/空格)
  • 可配置为16倍过采样或8倍过采样,因而为速度容差与时钟容差的灵活配置提供了可能
  • 小数波特率发生器系统
     - 通用可编程收发波特率
  • 数据字长度可编程(8位或9位)
  • 停止位可配置
     - 支持1或2个停止位
  • LIN主模式同步停止符号发送功能和LIN从模式停止符号检测功能
     - 对USART进行LIN硬件配置时可发生13位停止符合和检测10/11位停止符号
  • 用于同步发送的发送器时钟输出
  • IrDA SIR编码解码器
     - 正常模式下,支持3/16位持续时间
  • 智能卡仿真功能
     - 智能卡接口支持符合ISO 7816-3标准中定义的异步协议智能卡
     - 智能卡工作模式下,支持0.5或1.5个停止位
  • 单线半双工通信
  • 使用DMA(直接存储器访问)实现可配置的多缓冲区通信
     - 使用DMA在预留的SRAM缓冲区中收/发字节
  • 发送器和接收器具有单独使能位
  • 传输检测标志:
     - 接收缓冲区已满
     - 发送缓冲区为空
     - 传输结束标志
  • 奇偶校验控制:
     - 发送奇偶校验位
     - 检查接收的数据字节的奇偶性
  • 四个错误检测标志:
     - 溢出错误
     - 噪声检测
     - 帧错误
     - 奇偶检验错误
  • 十个具有标志位的中断源:
     - CTS变化
     - LIN停止符号检测
     - 发送数据寄存器为空
     - 发送完成
     - 接收数据寄存器已满
     - 接收到线路空闲
     - 溢出错误
     - 帧错误
     - 噪声错误
     - 奇偶检验错误
  • 多处理器通信
     - 
  • 从静模式唤醒(通过线路空闲检测或地址标记检测)
  • 两个接收器唤醒模式:地址位(MSB,第9位),线路空闲

3 功能说明

接口通过三个引脚从外部设备连接到其他设备。任何USART双向通信均需要至少两个引脚:接收数据输入引脚(RX)和发送数据输出引脚(TX)
RX:就是串行数据输入引脚。过采样技术可区分有效输入数据和噪声,从而用于恢复数据
TX:如果关闭发送器,该输出引脚模式由其I/O端口配置决定。如果使能了发送器但没有待发送的数据,则TX引脚处于高电平。在单线和智能卡模式下,该I/O用于发送和接收数据(USART电平下,随后在SW_RX上接收数据)
正常USART模式下,通过这些引脚以帧的形式发送和接收串行数据:

  • 发送或接收前保持空闲线路
  • 起始位
  • 数据(字长8位或9位),最低有效位在前
  • 用于指示帧传输已完成的0.5个、1个、1.5个、2个停止位
  • 该接口使用小数波特率发生器 - 带12位尾数和4位小数
  • 状态寄存器(USART_SR)
  • 数据寄存器(USART_DR)
  • 波特率寄存器(USART_BRR) - 12位尾数和4位小数
  • 智能卡模式下的保存时间寄存器(USART_GTPR)
    在同步模式下连接时需要一下引脚:
    SCLK:发送器时钟输出,用于输出发送器数据时钟,一遍按照SPI主模式进行同步发送(起始位和结束位上无时钟脉冲,可通过软件向最后一位数据位发送时钟脉冲)。RX上可同步接收并行数据。可用于控制带移位寄存器的外设(如LCD驱动器)。时钟相位和极性可通过软件编程。在智能卡模式下,SCLK可向智能卡提供时钟
    在硬件流控制模式下需要以下引脚:
    nCTS:“清除以发送”用于在当前传输结束时阻止数据发送(高电平时)
    nRTS:“请求以发送”用于指示USART已准备好接收数据(低电平时)

4 使用DMA进行通信

USART能够使用DMA进行连续通信,接收缓冲区和发送缓冲区的DMA请求时独立的

  • 使用DMA进行发送
    将USART_CR3寄存器中的DMAT位置1可以使能DMA模式进行发送。当TXE位置1时,可将数据从SRAM区加载到USART_DR寄存器。要映射一个DMA通道以进行USART发送,按以下步骤操作(x表示通道编号):
  1. 在DMA控制寄存器中写入USART_DR寄存器地址,将其配置为传输的目标地址。每次发生TXE事件后,数据都会从存储器移动到此地址。
  2. 在DMA控制寄存器中写入存储器地址,将其配置为传输的源地址。每次发生TXE后,数据都会从这个存储区域加载到USART_DR寄存器中。
  3. 在DMA控制寄存器中配置要传输的总字节数。
  4. 在DMA寄存器中配置通道的优先级
  5. 根据应用的需求,在完成一半或全部传输后产生DMA中断
  6. 向SR寄存器中的TC位写入0,将其清零
  7. 在DMA寄存器中激活该通道
    当达到在DMA控制器中设置的数据传输量时,DMA控制器会在DMA通道中的中断向量生上产生一个中断。
    在发送模式下,DMA对所有要发送的数据执行了写操作(DMA_ISR寄存器中的TCIF标志置1)后,可以对TC标志进行监视,以确保USART通信已完成。在禁止USART或进入停止模式前必须执行此步骤,以避免损坏最后一次发送。软件必须等待直到TC=1。TC标志在所有数据发送期间都必须保持清零状态,然后在最后一帧发送结束后由硬件置1。

使用DMA进行发送
在这里插入图片描述

  • 使用DMA进行接收
    将USART_CR3寄存器中的DMAR位置1可以使能DMA模式进行接收。接收数据字节时,数据会从USART_DR寄存器加载到SRAM区域中。要映射一个DMA通道以进行USART接收,按以下步骤操作:

  • 在DMA控制器中写入USART_DR寄存器地址,将其配置为传输的源地址。每次发生RXNE事件后,数据都会以此地址移动到存储器

  • 在DMA控制寄存器中写入存储器地址,将其配置为传输的目标地址。每次发生RXNE事件后,数据都会从USART_DR寄存器加载到此存储区

  • 在DMA控制寄存器中配置要传输的总字节数

  • 在DMA控制寄存器中配置通道优先级

  • 根据应用的需求,在完成一半或全部传输后产生中断

  • 在DMA控制寄存器中激活该通道
    当达到在DMA控制器中设置的数据传输量时,DMA控制器会在DMA通道的中断向量上产生一个中断。在中断子程序中,USART_CR3寄存器中的DMAR位应有软件清零。
    如果DMA用于接收,则不要使能RXNEIE位。

  • 使用DMA进行接收

在这里插入图片描述
在多缓冲区通信中,如果发生任何错误,都会在当前字节后放置错误标志。如果中断使能置1,则会产生中断。在单字节接收过程中,与RXNE一同置位的帧错误、上溢错误和噪声标志具有单独的错误标志中断使能位(USART_CR3寄存器中的EIE位);如果该位置1,则会因其中任何一个错误而在当前字节后产生中断。

5 USART中断

中断事件 事件标志 使能控制位
发送数据寄存器为空 TXE TXEIE
CTS标志 CTS CTSIE
发送完成 TC TCIE
准备好读取接收到的数据 RXNE RXNEIE
检测到上溢错误 ORE RXNEIE
检测到空闲线路 IDLE IDLEIE
奇偶校验错误 PE PEIE
断路标志 LBD LBDIE
多缓冲区通信中的噪声标志、上溢错误和帧错误 NF或ORE或FE EIE
USART中断事件被连接到相同的中断向量
  • 发送期间:发送完成、清楚以发送或发送数据寄存器为空中断
  • 接收期间:空闲线路检测、上溢错误、接收数据寄存器不为空、奇偶校验错误、LIN断路检测、噪声标志(仅限多缓冲区通信)和帧错误(仅限多缓冲区通信)
    如果相应的使能控制位置1,则这些事件会发生中断

6 代码实现

USART初始化

 void USART_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);         //GPIO时钟使能
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);        //USART时钟使能
	GPIO_PinAFConfig(GPIO_DEBUG, GPIO_PinSource9, GPIO_AF_USART1); //GPIO复用
	GPIO_PinAFConfig(GPIO_DEBUG, GPIO_PinSource10, GPIO_AF_USART1);//GPIO复用

	GPIO_InitStructure.GPIO_Pin = GPIO_PIN_TX | GPIO_PIN_RX;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;             //设置为复用推免输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIO_DEBUG, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;                  //设置波特率
	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_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //无硬件数据流控制
	USART_Init(USART1, &USART_InitStructure);
	
	USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
	USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);   //使能USART接收中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);   //使能检测到空闲线路中断
	
	USART_Cmd(USART1, ENABLE);  //使能USART   
}

USART发送数据
调用USART_SendData函数进行数据发送

void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);
USARTx:选择USART或者UART设备
Data:传输的数据

USART_SendData()只能一个字节一个字节的发送

USART接收数据
可以通过轮询,中断和DMA的发送接收数据

void USART1_IRQHandler(void)
{
	uint32_t temp;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
	{
		RecvBuf[recvcnt] = USART_ReceiveData(USART1);  //接收数据,放入接收buff
		recvcnt++;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除接收中断
	}
	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
	{
	    //清除空闲中断
		temp = USART1->SR;
		temp = USART1->DR;
		idle_flag = 1;
	}
}
uint16_t USART_ReceiveData(USART_TypeDef* USARTx);
USARTx:选择USART或者UART设备

STM32的IDLE的中断在串口无数据接收的情况下,是不会一直产生的,产生的条件是,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一断接收的数据断流,没有接收到数据,即产生IDLE中断。IDLE位不会再次被置高直到RXNE位被置起(即又检测到一次空闲总线)。RXNE接收中断可以不用开启,减少进中断的次数
串口总线空闲检测这一特性,尤其是对收到的数据是不定长时更有效果
在这里插入图片描述
如果数据量比较大的时候,我们可以考虑使用DMA进行数据的传输

posted @ 2021-09-27 21:58  chuadeichuadei  阅读(541)  评论(0编辑  收藏  举报