STM32串口通信-USART全面讲解

发布者:sumig最新更新时间:2022-01-12 来源: eefocus关键字:STM32  串口通信  USART 手机看文章 扫描二维码
随时随地手机看文章

通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个全双工的串行通信设备;UART(Universal Asynchronous Receiver and Transmitter)是在USART基础上裁掉了同步通信功能,只有异步通信。


USART满足外部设备对工业标准NRZ异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率。USART支持同步单向通信和半双工单线通信;还支持局域互连网络、智能卡协议与LrDA SIR ENDEC规范;还支持DMA,可实现高速数据通信


如下图是USART功能框图,我们将对此框图进行分析。

1.功能引脚

TX:发送数据输出引脚


RX:接收数据输入引脚


SW_RX:数据接收引脚,内部引脚,只用于单线和智能卡模式


nRTS:发送请求输出端,n表示低电平有效。如果是能RTS流控制,当USART接收器准备好接收新的数据时会将nRTS编程低电平;当接收寄存器已满时,nRTS将会被设置为高电平,该引脚至适用于硬件流控制。


nCTS:请求发送输入端,n表示低电平有效。如果使能CTS流控制,发送器在发送下一帧数据之前会检测nCTS引脚,如果为低电平则发送数据,如果为高电平则在发送完当前数据之后停止发送,该引脚只适用于硬件流控制。


SCLK:发送器时钟输出引脚,仅适用于同步模式。


注意:UART只有异步传输功能,故没有SCLK、nRTS和nCTS引脚。


2.数据寄存器

USART数据寄存器(USART_DR)包含TDR和RDR,两者是介于系统总线和移位寄存器之间,只有低9位或低8有效,两者选择取决于USART控制寄存器1(USART_CR1)的M位,M=0为8位数据字长,M=1为9位数据字长。


3.控制器

USART有专门的控制发送的发送器、控制接收的接收器,还有唤醒单元、中断控制等。使用USART之前,需要将USART_CR1的UE置1,使能串口时钟供给。


发送器:


USART_CR1的TE置1,启动数据发送,发送移位寄存器的数据会以低位在前、高位在后的形式从TX引脚输出,如果是同步模式SCLK也将输出时钟信号。


如下,字符发送时序图所示,一个字符帧发送需要三个部分:起始位+数据帧+停止位。起始位是一个位周期的低电平;数据帧是我们发送的8位或9位数据;停止位是一定时间周期的高电平,可以设置为0.5、1、1.5、2个停止位,默认使用1个停止位,2个停止位适用于USART模式、单线模式和调制解调器模式,0.5和1.5适用于智能卡模式。

发送数据重要的标志位

image.png

接收器


如果USART_CR1的RE置位,使能USART接受,使得接收器在RX线开始搜索起始位。接收数据时,几个比较重要的标志位如下

image.png

4.小波特率生成

波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,单位为波特。比特率指单位时间内传播的比特数。对于USART波特率与比特率相等。


USART的发送器和接收器使用相同的波特率,计算公式如下

其中,f为USART时钟,USARTDIV是一个放在波特率寄存器(USART_BRR)的一个无符号定点数。其中 DIV_Mantissa[11:0]位定义USARTDIV的整数部分,DIV_Fraction[3:0]位定义USARTDIV 的小数部分。


5.校验控制

USART支持奇偶校验。使用校验位时,串口传输的数据长度将是在8位的数据帧基础上加上1位,此时需要将USART_CR1的M为置1,然后将USART_CR1的PCE置1启动奇偶校验。


奇偶校验在发送和接收都是由硬件自动完成,如果在接收出现奇偶校验失败,会将USART_SR的PE置1,并可以产生奇偶校验中断。


6.中断控制

USART有多个中断请求事件,如下

image.png

7.USART初始化结构体详解

HAL库函数对每个外设都建立了一个初始化结构体和初始化配置函数,如USART_InitTypeDef和USART_Init(),USART_InitTypeDef用于配置外设工作参数,USART_Init()则将参数配置到相应的寄存器。


typedef struct {

 uint32_t BaudRate; //波特率

 uint32_t WordLength; //字长

 uint32_t StopBits; //停止位

 uint32_t Parity; //校验位

 uint32_t Mode; //UART 模式

 uint32_t HwFlowCtl; //硬件流控制

 uint32_t OverSampling; // 过采样模式

 uint32_t CLKLastBit; // 最尾位时钟脉冲

} USART_InitTypeDef;

BaudRate:波特率设置。一般设置为 2400、9600、19200、115200。HAL 库函数会根据设定值计算得到 UARTDIV 值。

WordLength:数据帧字长,可选 8 位或 9 位。

StopBits:停止位设置,可选 0.5 个、1 个、1.5 个和 2 个停止位。

Parity : 奇 偶 校 验 控 制 选 择 , 可 选 USART_PARITY_NONE ( 无校验 ) 、USART_PARITY_EVEN (偶校验)以及 USART_PARITY_ODD (奇校验)。

Mode:UART 模式选择,有 USART_MODE_RX 和 USART_MODE_TX,允许使用逻辑或运算选择两个,它设定 USART_CR1 寄存器的 RE 位和 TE 位。

8.编程要点

1) 使能 RX 和 TX 引脚 GPIO 时钟和 USART 时钟;


2) 初始化 GPIO,并将 GPIO 复用到 USART 上;


3) 配置 USART 参数;


4) 配置中断控制器并使能 USART 接收中断;


5) 使能 USART;


6) 在 USART 接收中断服务函数实现数据接收和发送


9.代码分析

GPIO和USART宏定义


//串口波特率

#define DEBUG_USART_BAUDRATE                    115200

 

//引脚定义

/*******************************************************/

#define DEBUG_USART                             USART1

#define DEBUG_USART_CLK_ENABLE()                __HAL_RCC_USART1_CLK_ENABLE();

 

#define DEBUG_USART_RX_GPIO_PORT                GPIOA

#define DEBUG_USART_RX_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOA_CLK_ENABLE()

#define DEBUG_USART_RX_PIN                      GPIO_PIN_10

 

#define DEBUG_USART_TX_GPIO_PORT                GPIOA

#define DEBUG_USART_TX_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()

#define DEBUG_USART_TX_PIN                      GPIO_PIN_9

 

#define DEBUG_USART_IRQHandler                  USART1_IRQHandler

#define DEBUG_USART_IRQ                      USART1_IRQn

/************************************************************/

 

void Usart_SendString(uint8_t *str);

void DEBUG_USART_Config(void);

int fputc(int ch, FILE *f);

int fgetc(FILE *f);

extern UART_HandleTypeDef UartHandle;

USART初始化配置。函数体中UartHandle 是定义为 UART_HandleTypeDef 结构体类型的全局变量,它管理着串口的所有配置,该函数与硬件无关。


具体的MCU底层硬件相关的配置如引脚、时钟、DMA、中断等等是在HAL_UART_MspInit(UART_HandleTypeDef *huart)中完成,该函数被HAL_UART_Init 函数所调用,所以我们只需要重新定义HAL_UART_MspInit函数即可完成底层硬件的配置。


/**

  * @brief  DEBUG_USART GPIO 配置,工作模式配置。115200 8-N-1

  * @param  无

  * @retval 无

  */  

void DEBUG_USART_Config(void)

  

  UartHandle.Instance          = DEBUG_USART;

  

  UartHandle.Init.BaudRate     = DEBUG_USART_BAUDRATE;

  UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;

  UartHandle.Init.StopBits     = UART_STOPBITS_1;

  UartHandle.Init.Parity       = UART_PARITY_NONE;

  UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;

  UartHandle.Init.Mode         = UART_MODE_TX_RX;

  

  HAL_UART_Init(&UartHandle);

   

 /*使能串口接收断 */

  __HAL_UART_ENABLE_IT(&UartHandle,UART_IT_RXNE);  

}

/**

  * @brief UART MSP 初始化 

  * @param huart: UART handle

  * @retval 无

  */

void HAL_UART_MspInit(UART_HandleTypeDef *huart)

{  

  GPIO_InitTypeDef  GPIO_InitStruct;

  

  DEBUG_USART_CLK_ENABLE();

DEBUG_USART_RX_GPIO_CLK_ENABLE();

  DEBUG_USART_TX_GPIO_CLK_ENABLE();

  

/**USART1 GPIO Configuration    

  PA9     ------> USART1_TX

  PA10    ------> USART1_RX 

  */

  /* 配置Tx引脚为复用功能  */

  GPIO_InitStruct.Pin = DEBUG_USART_TX_PIN;

  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

  GPIO_InitStruct.Pull = GPIO_PULLUP;

  GPIO_InitStruct.Speed =  GPIO_SPEED_FREQ_HIGH;

  HAL_GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStruct);

  

  /* 配置Rx引脚为复用功能 */

  GPIO_InitStruct.Pin = DEBUG_USART_RX_PIN;

  GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT; //模式要设置为复用输入模式!

  HAL_GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStruct); 

 

  HAL_NVIC_SetPriority(DEBUG_USART_IRQ ,0,1); //抢占优先级0,子优先级1

  HAL_NVIC_EnableIRQ(DEBUG_USART_IRQ );     //使能USART1中断通道  

}

字符发送函数


/*****************  发送字符串 **********************/

void Usart_SendString(uint8_t *str)

{

unsigned int k=0;

  do 

  {

      HAL_UART_Transmit(&UartHandle,(uint8_t *)(str + k) ,1,1000);

      k++;

  } while(*(str + k)!='');

  

}

中断服务函数


void  DEBUG_USART_IRQHandler(void)

{

  uint8_t ch=0; 

  

if(__HAL_UART_GET_FLAG( &UartHandle, UART_FLAG_RXNE ) != RESET)

{

    ch=( uint16_t)READ_REG(UartHandle.Instance->DR);

    WRITE_REG(UartHandle.Instance->DR,ch); 

 

}

}

在嵌入式中,串口经常用作日志打印工具,下面代码功能是重定向printf和scanf函数,fputc是printf的内部函数,而fgetc是scanf的内部函数。


//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数

int fputc(int ch, FILE *f)

{

/* 发送一个字节数据到串口DEBUG_USART */

HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 1000);

return (ch);

}

 

//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数

int fgetc(FILE *f)

{

int ch;

HAL_UART_Receive(&UartHandle, (uint8_t *)&ch, 1, 1000);

return (ch);

}

关键字:STM32  串口通信  USART 引用地址:STM32串口通信-USART全面讲解

上一篇:STM32基本定时器 HAL库
下一篇:STM32系统定时器-SysTick

推荐阅读最新更新时间:2024-11-16 20:52

stm32 mmc卡写文件然后读出来 串口输出
硬件环境:神州一号板 软件环境:MDK 1、sd卡硬件初始化 PA5---------CLK PA6---------MISO PA7---------MOSI PB7---------CS void TurnToSD(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_A
[单片机]
<font color='red'>stm32</font> mmc卡写文件然后读出来 串口输出
STM32——GPIO(1)
【对单片机的操作就是控制IO口】 一、GPIO(通用输入输出口) 1、选定需要的引脚(对应哪一个IO口); 2、配置需要的功能(输入还是输出); 3、设置需要的高低电平; 二、GPIO寄存器 配置寄存器:输入还是输出 数据寄存器:保存输入电平或将要输出电平 位控制寄存器:控制电平的输出 锁定寄存器:设置某锁定引脚后,不能修改配置 每4位控制一个引脚。寄存器都是32位的。 三、STM32地址映射 Cortex-M3 有 32 根地址线,所以它的寻址空间大小为 2^32 bit=4GB。 ARM 公司设计时,预先把这 4GB 的寻址空间大致地分配好了。地址从 0x4000 0000 至 0x5FFF FFFF(
[单片机]
<font color='red'>STM32</font>——GPIO(1)
STM32串口第一个字节丢失问题的分析过程
STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03 0x04..接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x06丢失。错误依旧。 故障排除过程: 1、刚开始怀疑是接收端的错误,我是使用电脑串口,运行串口辅助调试工具接收,换成其他软件后,发现故障依旧,而且电脑软件一直是开启状态,不像和电脑软件有关。 2、使用单步调试,单步运行各个发送指令,都正常。能收到0x01 0
[单片机]
STM32关于BOOT0和BOOT1设置
BOOT0和BOOT1 STM32三种启动模式对应的存储介质均是芯片内置的,它们是: 1)用户闪存 = 芯片内置的 Flash。 2)SRAM = 芯片内置的 RAM区,就是内存啦。 3)系统存储器= 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段 Bootloader,就是通常说的 ISP程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个 ROM区。 在每个 STM32的芯片上都有两个管脚 BOOT0和 BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序,见下表: BOOT1=x BOOT0=0 从用户闪存启动,这是正常的工作模式。 BOOT1=0 BOOT0=1 从系
[单片机]
基于STM32的触摸屏学习笔记
本文共有三个内容:一、电阻触摸屏的原理;二、XPT2046的控制字与数字接口;三、程序源码讲解(参考正点原子的代码) 一、电阻触摸屏的原理,上图: 图上的文字介绍了触摸的原理,下面总结一下触摸的原理: 触摸屏工作主要是两个电阻屏(上下两层)在工作,如上图,当某一层电级加上电压时,会在该网络上形成电压梯度。如果有外力使得上下两层在某一点接触,则在未加电压的那一层可以测得接触点的电压,从而得出接触点的坐标(X或Y)。举个例子:当我们在上层的电极间(Y+和Y-)加上电压,则会在上层形成电压梯度(这里读者可以想想AD转换的原理),当有外力使得上下两层在某一点接触时,在底层X层就可以测得接触点处的电压(每个点电压都不同),再根据测得电
[单片机]
基于<font color='red'>STM32</font>的触摸屏学习笔记
stm32定时器输入捕获pwm
花了两天时间终于把stm32f103的定时器输入捕获弄懂了,这里以TIM3的通道ch1为例,要实现输入捕获需要配置一下寄存器,TIMx_ARR,TIMx_PSC,TIMx_CCMR1,TIMx_CCER,TIMx_DIER,TIMx_CR1,TIMx_CCR1.这里抓取了一些收据手册中寄存器描述的图 下面一一介绍: TIMx_ARR寄存器为自动重装载的值 TIMx_CR1这里了只要用到它的第0位即使能位。 TIMx_CCMR可以配置对应通道映射到那个IC,TI。 这里我们是第一通道故只需配置低8位,cc1s为配置ch1映射到那个TI,IC1PSC为配置是否分频,1c1f为配置是否滤波。 TIMx_psc寄存器 T
[单片机]
stm32怎么读取串口发来的指令
读取串口发来的指令是嵌入式系统中一项常见的任务,特别是在与外部设备进行通信时。在STM32系列微控制器中,提供了多个串口接口(USART、UART等),可以用于读取和处理串口接收到的数据。下面将详细介绍使用STM32读取串口指令的步骤。 初始化串口:在开始读取串口指令之前,首先需要初始化串口接口。这包括设置串口的波特率、数据位长度、校验位和停止位等。可以使用STM32提供的HAL库函数来完成串口的初始化。例如,可以使用HAL_UART_Init()函数来初始化UART串口。 定义接收缓冲区:为了存储串口接收到的数据,需要定义一个接收缓冲区。缓冲区的大小应根据实际需求确定,一般建议设置为足够大以容纳预期的命令或数据。 设置中断
[单片机]
ST推四套价格低廉STM32评估及开发工具 均由第三方开发
Hitex、IAR、Keil和Raisonance公司的评估及开发工具与ST的量产的ARM Cortex-M3内核微控制器同步上市 中国,2007年10月15日 — 意法半导体(纽约证券交易所代码:STM)今天推出四套价格低廉的评估及开发工具,这些工具是由ST的主要的第三方软件供应商开发的,支持ST最近推出的基于具有突破性的ARM Cortex-M3内核的STM32微控制器。这些开发入门工具的开发厂商分别是Hitex、IAR、Keil和Raisonance,通过使用这些开发工具,用户可以轻松了解STM32的特性和功能,只需很少的时间和资金就能开始正式的应用程序开发,这些开发工具的价位在109美元到239美元之间。 全系列产品
[单片机]

推荐帖子

【难懂的数学】傅里叶、拉普拉斯、卷积、欧拉方程、梯度散度、拉格朗日方程、奈奎...
【难懂的数学】傅里叶、拉普拉斯、卷积、欧拉方程、梯度散度、拉格朗日方程、奈奎...1
btty038 RF/无线
顶尖创意来自高度好奇心
客户包括微软、苹果及百事可乐等业界巨头的顶尖创意管理公司IDEO的执行长兼总裁布朗(TimBrown)把问题看得比答案更重要。他回忆自己的第一份专业设计工作是在英格兰北部的一家小公司,那是一家从工业大革命时期开始营运,生产木工机械的老公司,以前不曾雇用设计师。他花6个月把这家公司的设备重新设计后,董事长对他说,「我真的欣赏你在这所做的事。我想带你到我们在全英格兰的所有其他部门,我希望你对业务负责人建议他们在设计方面应该怎么做。」布朗说,「那时我才21、22岁,而他是英格兰一家相当大的公
banana 创意市集
选用单端探头还是差分探头?
新的有源探头体系结构使GHz级以上的千兆信号的完整性测量变得更加容易、精度也更高,但这只对于了解探头的工作原理和探头的两种拓扑结构之间优劣的用户而言的。选用单端探头还是差分探头?
feifei PCB设计
2020-7-5-腹式呼吸训练教练仪(因上一贴有丢图重发一遍)
腹式呼吸训练教练仪作者:7905 项目背景(100-200字)无论是古老的印度瑜伽还是佛教的观智禅定,再到中国道家的丹道胎息以及普通的气功练习,各种习练方法的入门技术里都能或多或少找到腹式呼吸训练的影子,腹式呼吸训练确实是辅助身心锻炼入门的好方法。可习练时人越想清静,意识就越发像洪水猛兽一样频繁无序的跳出来,意识思绪一跑路,呼吸锻炼的流程就时时打断,后续的练习进
7905 ST MEMS传感器创意设计大赛专区
盘点十大最酷炫车载数字化仪表盘(转)
本帖最后由同林鸟于2014-12-118:10编辑 上周参加一场媒体研讨会,富士通专家主讲的汽车虚拟仪表解决方案的演讲和现场模拟Demo展示台让大家很让俺等小白耳目一新,特别是他家强大的Triton(MB86R20)系列SoC的全景视频和虚拟仪表盘解决方案很强大,据说他们家的方案的360度的汽车辅助视觉应用已经在国外量产,在汽车数字仪表上的应用更多。不过回来搜了下,360度的全景视频ADAS好像公开报道的很少,大部分还是可视倒车的低级应用,不知道他们宣称的应用是什么高大上的豪
同林鸟 汽车电子
[教程] Protel封装库转换allegro封装库
长期使用Protel作PCB设计,我们总会积累一个庞大的经过实践检验的Protel封装库,当设计平台转换时,如何保留这个封装库总是令人头痛。这里,我们将使用OrcadLayout,和Layout2allegro来完成这项工作。步骤如下:a)在Protel中将PCB封装放置(可以一次将所有需要转换的全部放置上来)到一张空的PCB中,并将这个PCB文件用ProtelPCB2.8ASCII的格式导出(export);b)使用OrcadLayout导入(import)这个Protel
电子资料者 PCB设计
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved