基于STM32之UART串口通信协议(一)详解
一、前言
1、简介
写的这篇博客,是为了简单讲解一下UART通信协议,以及UART能够实现的一些功能,还有有关使用STM32CubeMX来配置芯片的一些操作,在后面我会以我使用的STM32F429开发板来举例讲解(其他STM32系列芯片大多数都可以按照这些步骤来操作的),如有不足请多多指教。
2、UART简介
嵌入式开发中,UART串口通信协议是我们常用的通信协议(UART、I2C、SPI等)之一,全称叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)。
3、准备工作
1)Keil5
链接:点击下载
提取码:wrt9
2)STMCubeMX5.1.0版本
链接:点击下载
提取码:20xs
3)STMF429开发板
注:
只要是stm32的开发板都可以用到的,在STM32CubeMx里选对型号、配置好就行了。
二、UART详解
1、UART简介
嵌入式开发中,UART串口通信协议是我们常用的通信协议(UART、I2C、SPI等)之一,全称叫做通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输,它能将要传输的资料在串行通信与并行通信之间加以转换,能够灵活地与外部设备进行全双工数据交换。
注:
在此开发板中,是有USART(Universal Synchronous Asynchronous Receiver and Transmitter通用同步异步收发器)串口的,USART相当于UART的升级版,USART支持同步模式,因此USART 需要同步始终信号USART_CK(如STM32 单片机),通常情况同步信号很少使用,因此一般的单片机UART和USART使用方式是一样的,都使用异步模式。因为USART的使用方法上跟UART基本相同,所以在此就以UART来讲该通信协议了。
2、UART通信协议
1)起始位
当未有数据发送时,数据线处于逻辑“1”状态;先发出一个逻辑“0”信号,表示开始传输字符。
2)数据位
紧接着起始位之后。资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。从最低位开始传送,靠时钟定位。
3)奇偶校验位
资料为加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。
4)停止位
它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
5)空闲位或起始位
处于逻辑“1”状态,表示当前线路上没有资料传送,进入空闲状态。
处于逻辑“0”状态,表示开始传送下一数据段。
6)波特率
表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。
常用的波特率有:9600、115200……
时间间隔计算:1秒除以波特率得出的时间,例如,波特率为9600的时间间隔为1s / 9600(波特率) = 104us。
3、UART功能说明
接口通过三个引脚从外部连接到其它设备。任何 USART 双向通信均需要 至少两个引脚:接收数据输入引脚 (RX) 和发送数据引脚输出 (TX):
RX:接收数据输入引脚就是串行数据输入引脚。过采样技术可区分有效输入数据和噪声,从而用于恢复数据。
TX:发送数据输出引脚。如果关闭发送器,该输出引脚模式由其 I/O 端口配置决定。如果使 能了发送器但没有待发送的数据,则 TX 引脚处于高电平。在单线和智能卡模式下,该 I/O 用于发送和接收数据(USART 电平下,随后在 SW_RX 上接收数据)。
1)正常 USART 模式下,通过这些引脚以帧的形式发送和接收串行数据:
- 发送或接收前保持空闲线路
- 起始位
- 数据(字长 8 位或 9 位),最低有效位在前
- 用于指示帧传输已完成的 0.5 个、1 个、1.5 个、2 个停止位
- 该接口使用小数波特率发生器 - 带 12 位尾数和 4 位小数
- 状态寄存器 (USART_SR)
- 数据寄存器 (USART_DR)
- 波特率寄存器 (USART_BRR) - 12 位尾数和 4 位小数。
- 智能卡模式下的保护时间寄存器 (USART_GTPR)。
2)在同步模式下连接时需要以下引脚:
- SCLK:发送器时钟输出。该引脚用于输出发送器数据时钟,以便按照 SPI 主模式进行同步发送(起始位和结束位上无时钟脉冲,可通过软件向最后一个数据位发送时钟脉冲)。RX 上可同步接收并行数据。这一点可用于控制带移位寄存器的外设(如 LCD 驱动器)。时钟相位和极性可通过软件编程。在智能卡模式下,SCLK 可向智能卡提供时钟。在硬件流控制模式下需要以下引脚:
- nCTS:“清除以发送”用于在当前传输结束时阻止数据发送(高电平时)。
- nRTS:“请求以发送”用于指示 USART 已准备好接收数据(低电平时)。
USART框图如下:
4、UART工作原理
1)发送接收
2)波特率产生
波特率除数(baud-rate divisor)是一个22 位数,它由16 位整数和6 位小数组成。波特率发生器使用这两个值组成的数字来决定位周期。通过带有小数波特率的除法器,在足够高的系统时钟速率下,UART 可以产生所有标准的波特率,而误差很小。
3)数据收发
发送时,数据被写入发送FIFO。如果UART 被使能,则会按照预先设置好的参数(波特率、数据位、停止位、校验位等)开始发送数据,一直到发送FIFO 中没有数据。一旦向发送FIFO 写数据(如果FIFO 未空),UART 的忙标志位BUSY 就有效,并且在发送数据期间一直保持有效。BUSY 位仅在发送FIFO 为空,且已从移位寄存器发送最后一个字符,包括停止位时才变无效。即 UART 不再使能,它也可以指示忙状态。
在UART 接收器空闲时,如果数据输入变成“低电平”,即接收到了起始位,则接收计数器开始运行,并且数据在Baud16 的第8 个周期被采样。如果Rx 在Baud16 的第8 周期仍然为低电平,则起始位有效,否则会被认为是错误的起始位并将其忽略。
4)中断控制
出现以下情况时,可使UART 产生中断:
- FIFO 溢出错误
- 线中止错误(line-break,即Rx 信号一直为0 的状态,包括校验位和停止位在内)
- 奇偶校验错误
- 帧错误(停止位不为1)
- 接收超时(接收FIFO 已有数据但未满,而后续数据长时间不来)
- 发送
- 接收
由于所有中断事件在发送到中断控制器之前会一起进行“或运算”操作,所以任意时刻 UART 只能向中断产生一个中断请求。通过查询中断状态函数,软件可以在同一个中断服务函数里处理多个中断事件(多个并列的if 语句)。
5)FIFO 操作
FIFO 是“First-In First-Out”的缩写,意为“先进先出”,是一种常见的队列操作。 Stellaris 系列ARM 的UART 模块包含有2 个16 字节的FIFO:一个用于发送,另一个用于接收。可以将两个FIFO 分别配置为以不同深度触发中断。可供选择的配置包括:1/8、 1/4、1/2、3/4 和7/8 深度。例如,如果接收FIFO 选择1/4,则在UART 接收到4 个数据时产生接收中断。
6)回环操作
UART 可以进入一个内部回环(Loopback)模式,用于诊断或调试。在回环模式下,从Tx 上发送的数据将被Rx 输入端接收。
三、CubeMx配置
说明:
在使用STM32CubeMx配置的时候,首先要选择正在使用的芯片的型号,再配置芯片的时钟,然后才去配置所需要用到的功能。
1、新建项目
1)选择新建
2)选择芯片型号
2、时钟配置
1)配置界面
2)时钟模式配置
3)设置调试接口
4)时钟配置(尽量将下面方框内的值设成最高值即可)
3、功能配置
1)启用串口
2)配置串口(默认即可,波特率为115200)
4、生成工程
1)项目信息设置
2)选择生成必要的代码
3)生成代码
4)打开项目(生成代码成功后会弹出窗口,可以直接打开工程)
注:
因为STM32CubeMX自动生成的代码中,没有设置把每次下载烧写都重置一下,所以生成代码后,我们需要自己选上该功能,步骤如下:
1)功能界面
2)选择小锤子
3)选择Debug->Settings
4)选择Flash Download->勾选Reset and Run
完成上面的操作后,在每次烧写都会重置,并运行新下载烧写的程序了。
四、HAL库关键函数说明
1、初始化/还原初始化函数
/* Initialization/de-initialization functions **********************************/
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart); //根据UART_InitTypeDef中指定的参数初始化UART模式,并创建关联的句柄。
HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart); //根据UART_InitTypeDef中指定的参数初始化半双工模式并创建关联句柄。
HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength); //根据UART_InitTypeDef中指定的参数初始化LIN模式,并创建关联的句柄。
HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod); //根据UART_InitTypeDef中指定的参数初始化多处理器模式,并创建关联的句柄。
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart); //非初始化UART外围设备。
void HAL_UART_MspInit(UART_HandleTypeDef *huart); //弱函数UART MSP初始化
void HAL_UART_MspDeInit(UART_HandleTypeDef *huart); //弱函数UART MSP初始化还原
2、IO口操作函数
/* IO operation functions *******************************************************/
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);//以阻塞模式发送大量数据。
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); //在阻塞模式下接收大量数据。
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //以非阻塞模式发送大量数据。
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //在非阻塞模式下接收大量数据。
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //以非阻塞模式发送大量数据。
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); //在非阻塞模式下接收大量数据。
HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); //暂停DMA传输。
HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); //恢复DMA传输。
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); //停止DMA传输。
3、传输中断函数
/* Transfer Abort functions */
HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart); //中止正在进行的传输(阻塞模式)。
HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart); //中止正在进行的传输传输(阻塞模式)。
HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart); //中止正在进行的接收传输(阻塞模式)。
HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart); //中止正在进行的传输(中断模式)。
HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); //中止正在进行的传输(中断模式)。
HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart); //中止正在进行的接收传输(中断模式)。
4、中断处理及回调函数
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //函数处理UART中断请求。
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //Tx传输完成回调函数。
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); //Tx半传输完成回调函数。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //Rx传输完成回调函数。
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart); //Rx完成一半传输回调函数。
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart); //UART错误回调函数。
void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart); //UART中止完成回调函数。
void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart); //UART中止完成回调函数。
void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart); //UART中止接收完整的回调函数。
五、结尾
1、总结
这篇博客主要是讲解一下UART串口通信协议的时序、功能以及工作原理,还有使用STM32CubeMX来配置USART。而还未讲到有关HAL库函数的函数调用,有了STM32CubeMX生成的这个HAL库函数,我们基本不用管协议上的事情了,可以直接调用里面的发送或接收函数来实现UART通信。而我也会在后续继续编写有关HAL库的调用说明,详细说一下HAL库是如何使用的。
2、后续
1)UART发送
2)UART接收
3)待续未完……
~
~
~
~
最后~最后~最后~
欢迎大家关注我的博客,一起分享嵌入式知识~
基于STM32之UART串口通信协议(一)详解的更多相关文章
- 基于STM32之UART串口通信协议(四)Printf发送
一.前言 1.简介 前面在UART发送中已经讲解过如何调用HAL库的HAL_UART_Transmit函数来实现串口发送,而在调用这个函数来实现串口发送的话,但是在发送数据或者字符的时候,需要将数据或 ...
- 基于STM32之UART串口通信协议(二)发送
一.前言 1.简介 在上一篇UART详解中,已经有了关于UART的详细介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会讲解一下如何实现UART串口的发送功能. ...
- 基于STM32之UART串口通信协议(三)接收
一.前言 1.简介 回顾上一篇UART发送当中,已经讲解了如何实现UART的发送操作了,接下来这一篇将会继续讲解如何实现UART的接收操作. 2.UART简介 嵌入式开发中,UART串口通信协议是我们 ...
- STM32 Bootloader基于ymodem传输协议串口IAP升级详解
硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 1 预备知识 2 Bootloader 2.1 启动流程 2.2 校验跳转地址是否有效 ...
- 基于集合成工控机Ubuntu系统安装分区详解
基于集合成工控机Ubuntu系统安装分区详解 硬件描述:双核的CPU,128G的固态硬盘 软件描述:使用Ubuntu12.04系统,内核3.8.0-29版本,QT4.8.1版本 1.新建分区表 /de ...
- C#串口通信程序详解
C#串口通信程序详解 摘要:创建C#串口通信程序需要注意什么呢?创建C#串口通信程序的步骤是什么?那么本文就向你详细介绍创建C#串口通信程序集体的内容. 在.NET平台下创建C#串口通信程序,.NET ...
- 基于双向BiLstm神经网络的中文分词详解及源码
基于双向BiLstm神经网络的中文分词详解及源码 基于双向BiLstm神经网络的中文分词详解及源码 1 标注序列 2 训练网络 3 Viterbi算法求解最优路径 4 keras代码讲解 最后 源代码 ...
- spring基于通用Dao的多数据源配置详解【ds1】
spring基于通用Dao的多数据源配置详解 有时候在一个项目中会连接多个数据库,需要在spring中配置多个数据源,最近就遇到了这个问题,由于我的项目之前是基于通用Dao的,配置的时候问题不断,这种 ...
- 基于ORA-12170 TNS 连接超时解决办法详解
转自原文 基于ORA-12170 TNS 连接超时解决办法详解 1.开始----程序-----Oracle------配置和移植工具-----Net Manager----本地----服务命名---o ...
随机推荐
- WPF(C#)中Bitmap与BitmapImage相互转换
原文:WPF(C#)中Bitmap与BitmapImage相互转换 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/wangshubo1989/art ...
- ThreadingTest(线程测试)领先的白框进入这个行业
测试一直是黑色的,白点.在一般情况下,因为白盒测试需要逻辑思维能力是比较高的技术要求比一般开发商的项目经验和谨慎甚至更高,和较长的测试时间,用于单元测试,昂贵的工具,因此,国内企业普遍忽视白盒测试.这 ...
- WPF: FishEyePanel/FanPanel - 自定义Panel
原文:WPF: FishEyePanel/FanPanel - 自定义Panel 原文来自CodeProject,主要介绍如何创建自定义的Panel,如同Grid和StackPanel. 1) Int ...
- Matlab随笔之矩阵入门知识
原文:Matlab随笔之矩阵入门知识 直接输入法创建矩阵 – 矩阵的所有元素必须放在方括号“[ ]”内: – 矩阵列元素之间必须用逗号“,”或空格隔开,每行必须用“;”隔开 – 矩阵元素可以是任何不含 ...
- MATLAB利用散点进行函数曲线拟合
原文:MATLAB利用散点进行函数曲线拟合 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/laobai1015/article/details/77 ...
- mac 安装使用Liteide
1.下载go 官网下载地址(需要FQ)golang 中国镜像网站下载golangtc 下载go1.5.1.darwin-amd64.tar.gz包,解压得到一个Go目录,把go目录移动到你想要的路径下 ...
- c# windows程序调用本地输入法
原文:c# windows程序调用本地输入法 好久没写博客了,今天写了一个DEMO,在WINform程序中调用本地输入法,并在窗体中显示出来.其中使用到了很多API,现把代码贴出来,供大家参考 ...
- WPF——TargetNullValue(如何在绑定空值显示默认字符)
原文:WPF--TargetNullValue(如何在绑定空值显示默认字符) 说明:在数据绑定时,如果有些字段为空值,那么在数据绑定时可以用默认值来显示为空的字段. </Grid> { L ...
- wpf事件绑定,比如一个控件的左键按下事件
<i:Interaction.Triggers> <i:EventTrigger EventName="MouseLeftButtonDown"> < ...
- C++没有库则寸步难行,有库则几乎可以做任何事情——Bjarne Stroustrupi
"Without a good library, most interesting tasks are hard to do in C++; but given a good library ...