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适用于智能卡模式。
发送数据重要的标志位
名称 | 描述 |
TE | 使能发送器 |
TXE |
发送寄存器为空,发送单个字节的时候使用
|
TC |
发送完成,发送多个字节数据的时候使用
|
TXIE |
使能发送完成中断
|
接收器
如果USART_CR1的RE置位,使能USART接受,使得接收器在RX线开始搜索起始位。接收数据时,几个比较重要的标志位如下
名称 | 描述 |
RE | 接收使能 |
RXNE | 读数据寄存器非空 |
RXNEIE | 接收完成中断使能 |
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有多个中断请求事件,如下
中断事件 | 事件标志 | 使能控制位 |
发送数据寄存器为空 | TXE | TXEIE |
CTS标志 | CTS | CTSIE |
发送完成 | TC | TCIE |
准备好读取接收到的数据 | RXNE | RXNEIE |
检测到上溢错误 | ORE | |
检测到空闲线路 | IDLE | IDLEIE |
奇偶校验错误 | PE | PEIE |
断路标志 | LBD | LBDIE |
多缓冲通信中的噪声标志、上溢错误和帧错误 | NF/ORE/FE | EIE |
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_TXPA10 ------> 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,子优先级1HAL_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)!='\0');}
中断服务函数
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的USART介绍 二.USART串口通信实践 1.任务要求 2.所用器材 3.主要代码 4.代码解析 三.效果展示 四.总结 五.参考资料 一.STM32的USART介绍 通用 ...
- STM32串口通信详解以及通信异常或者卡死常见问题分析
STM32串口通信详解以及通信异常或者卡死常见问题分析 目录 STM32串口通信详解以及通信异常或者卡死常见问题分析 一.常见的异常问题 二.STM32的串口简介 1.串口的通讯方式 ①按数据传输方向 ...
- stm32串口通信(初学者对于串口通信的理解)
stm32串口通信(初学者对于串口通信的理解) 标签: stm32串口通信单片机 2015-01-24 10:12 987人阅读 评论(0) 收藏 举报 分类: stm32 版权声明:本文为博主原创 ...
- STM32——串口通信
STM32--串口通信 宗旨:技术的学习是有限的,分享的精神是无限的. 一.异步串口通信协议 STM32 的串口非常强大,它不仅支持最基本的通用串口同步.异步通信,还具有 LIN 总线功能(局域互联网 ...
- openmv和stm32串口通信完成二维码识别
openmv和stm32串口通信完成二维码识别 文章目录 前言 一.所用的硬件: 二.openmv端 2.stm32端 总结 前言 注:我只是个大一的小白,本文只完成基本功能,希望能帮助有困惑的人(我 ...
- 安装STM32CubeMX,stm32串口通信
目录 一.串口通信和RS-232标准 1.串口通信 波特率 数据位 停止位 奇偶校验 2.RS-232标准 二.安装STM32CubeMX,搭建STM32的开发环境 1.安装jdk 2.安装STM32 ...
- 【串口通信】K210与STM32串口通信、K210与OpenMV串口通信
[串口通信]K210与STM32串口通信.K210与OpenMV串口通信 串口通信 前言 为何需要串口通信 K210如何进行串口通信 K210串口配置 K210串口发送相关定义 K210串口发送测试 ...
- STM32串口通信学习总结
STM32串口通信学习总结 1.概述 1.1学习目的 ...
- STM32串口通信详解(嵌入式学习)
STM32串口通信 1.通信基础知识 1.1 时钟信号区分 同步通信 异步通信 波特率 总线协议(电气协议) 1.2 通信方式划分 串行通信 并行通信 1.3 通信方向划分 单工通信 半双工通信 全双 ...
最新文章
- 【移动开发】安卓Lab2(01)
- [Python图像处理] 二十六.图像分类原理及基于KNN、朴素贝叶斯算法的图像分类案例
- 基于灰度变换的图像增强
- setupUi()引起的麻烦
- 你必须了解的基础的 Linux 网络命令
- 8. PHP7 安装
- CentOS安装NVidia驱动提示kernel source path问题
- base64编码规则
- 磁共振成像原理-物理基础2(质子在外部磁场的情况)
- C++-dllmain介绍
- 视频行业创业投资与趋势报告
- 新版代挂网站PHP源码+去除授权/支持燃鹅代抽
- vue3 出现 Component inside <Transition> renders non-element root node that cannot be animated.
- 浏览器如何使用HTTP防止ip限制
- SVM中支持向量的通俗解释
- 浅谈图片加载:逐行扫描VS交错扫描
- 树莓派基于ffmpeg+阿里云流媒体服务器实现视频直播
- 【c++图论】【口袋的天空】【部落划分】
- Python 使用 twitter API 获取twitter用户信息
- r星服务器在那个文件,gta5修改host文件连接r星服务器方法介绍
热门文章
- 如何创作一款商业级的安卓独立应用
- 【Qt】 Fractal Designer 4.6 - Help(中文版)
- 邮政快递与物流行业舆情监测系统方案
- Paddle2.0实现中文新闻文本标题分类
- 【雅思阅读】王希伟阅读P4(matching2段落信息配对题【困难】)
- 细细品味hadoop
- (swing读书笔记)Swing Look And Feel(1)
- ThreadX最小移植及tx_initialize_low_level.s的简要分析
- 通过pyautogui和excel插件方方格子来实现excel图片导入
- 快速高效 | iOS银行卡识别