STM32 串口接收流程-串口接收中断
串口接收
串口接收流程
- 编程USARTx_CR1的M位来定义字长。
- 编程USARTx_CR2的STOP位来定义停止位位数。
- 编程USARTx_BRR寄存器确定波特率。
- 使能USARTx_CR1的UE位使能USARTx。
- 如果进行多缓冲通信,配置USARTx_CR3的DMA使能(DMAT)。
- 使能USARTx_CR1的RE位为1使能接收器。
- 如果要使能接收中断(接收到数据后产生中断),使能USARTx_CR1的RXNEIE位为1。
当串口接收到数据时
- USARTx_SR(ISR)的RXNE位置1。表明移位寄存器内容已经传输到RDR(DR)寄存器。已经接收到数据并且等待读取。
- 如果开启了接收数据中断(USARTx_CR1寄存器的RXNEIE位为1),则会产生中断。(程序上会执行中断服务函数)
- 如果开启了其他中断(帧错误等),相应标志位会置1。
- 读取USARTx_RDR(DR)寄存器的值,该操作会自动将RXNE位清零,等待下次接收后置位。
串口接收流程(HAL库)
配置过程:
接收配置步骤①~⑥和发送流程一样,调用HAL_UART_Init函数HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);
步骤⑦开启接收中断:HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef*huart, uint8_t *pData, uint16_t Size);
接收数据过程:
步骤①获取状态标志位通过标识符实现:
__HAL_UART_GET_FLAG //判断状态标志位__HAL_UART_GET_IT_SOURCE //判断中断标志位
步骤②~③中断服务函数:
void USARTx_IRQHandler(void) ;//(x=1~3,6)
void UARTx_IRQHandler(void) ;//(x=4,5,7,8)
在启动文件startup_stm32fxxx.s中查找。
步骤④读取接收数据:
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
串口接收中断程序配置过程(HAL库)
- 初始化串口相关参数,使能串口:HAL_UART_Init();
- 串口相关IO口配置,复用配置:
在HAL_UART_MspInit中调用HAL_GPIO_Init函数。 - 串口接收中断优先级配置和使能:
HAL_NVIC_EnableIRQ();
HAL_NVIC_SetPriority(); - 使能串口接收中断:HAL_UART_Receive_IT();
- 编写中断服务函数:USARTx_IRQHandler
经过上面步骤,我们就可以写完整的串口接收实验。我们就可以在中断服务函数中编写中断处理过程。
HAL库提供了详细的中断处理函数HAL_UART_IRQHandler,我们在中断服务函数中会调用此函数处理中断。
在void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)函数里可以找到:UART_Receive_IT(huart);然后找到他的定义static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart),里面可以找到HAL_UART_RxCpltCallback(huart);他是一个接收完成处理回调函数,void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart),用户可以自己编写。
在USART_HandleTypeDef中有如下变量:RxXferSize是接收的数量,RxXferCount是剩余的数据个数,pRxBuffPtr指向数据存储位置的地址。比如,一开始要接收10个数据,pRxBuffPtr指向一个起始位置,初始时RxXferSize=10,RxXferCount=10,每接收一次,RxXferCount的值就减去1,而且pRxBuffPtr指针往下移,直到RxXferCount减为0 。
uint8_t *pRxBuffPtr; /*!< Pointer to USART Rx transfer Buffer */uint16_t RxXferSize; /*!< USART Rx Transfer size */uint16_t RxXferCount; /*!< USART Rx Transfer Counter */
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{uint16_t* tmp;uint16_t uhMask = huart->Mask;/* Check that a Rx process is ongoing */if(huart->RxState == HAL_UART_STATE_BUSY_RX){if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)){tmp = (uint16_t*) huart->pRxBuffPtr ;*tmp = (uint16_t)(huart->Instance->RDR & uhMask);huart->pRxBuffPtr +=2;}else{*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);}if(--huart->RxXferCount == 0){/* Disable the UART Parity Error Interrupt and RXNE interrupt*/CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);/* Rx process is completed, restore huart->RxState to Ready */huart->RxState = HAL_UART_STATE_READY;HAL_UART_RxCpltCallback(huart);return HAL_OK;}return HAL_OK;}else{/* Clear RXNE interrupt flag */__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);return HAL_BUSY;}
}
串口接收中断流程
串口中断服务函数执行流程
串口中断服务函数中调用HAL库串口中断通用处理函数:HAL_UART_IRQHandler(); 该函数会对中断来源进行分析,调用相应函数。
对于不同的中断类型,我们只需要编写最终的中断处理函数:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
串口接收实验
电脑通过串口助手往串口1发送字符,串口1通过中断方式接受字符,每接受一个字符就同时通过串口1返回给电脑。
- 初始化串口相关参数,使能串口:HAL_UART_Init();
- 串口相关IO口配置,复用配置:
在HAL_UART_MspInit中调用HAL_GPIO_Init函数。 - 串口接收中断优先级配置和使能:
HAL_NVIC_EnableIRQ();
HAL_NVIC_SetPriority(); - 使能串口接收中断:HAL_UART_Receive_IT();
- 编写中断服务函数:USARTx_IRQHandler
根据如上步骤,其中1、2步骤和串口发送设置差不多,第三步,HAL_NVIC_SetPriority(USART1_IRQn,3,3);抢占和响应优先级均设置为3.这是因为main中的HAL_Init();有一个设置是 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
#include "sys.h"
#include "delay.h"
#include "usart.h"
u8 rdata[1];//因为是每接收一个就发出去,所以设置为1
UART_HandleTypeDef usart1_handler;
//初始化串口相关参数,使能串口
void uart1_init(void)
{usart1_handler.Instance = USART1;usart1_handler.Init.BaudRate = 115200;usart1_handler.Init.WordLength = UART_WORDLENGTH_8B;usart1_handler.Init.StopBits = UART_STOPBITS_1;usart1_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;usart1_handler.Init.Mode = UART_MODE_TX_RX;usart1_handler.Init.Parity = UART_PARITY_NONE;HAL_UART_Init(&usart1_handler);
}
//串口相关IO口配置,复用配置
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1){__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟__HAL_RCC_USART1_CLK_ENABLE(); //使能USART1时钟GPIO_Initure.Pin=GPIO_PIN_9; //PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP; //复用推挽输出GPIO_Initure.Pull=GPIO_PULLUP; //上拉GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速GPIO_Initure.Alternate=GPIO_AF7_USART1; //复用为USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA9GPIO_Initure.Pin=GPIO_PIN_10; //PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化PA10//串口接收中断优先级配置和使能HAL_NVIC_SetPriority(USART1_IRQn,3,3);//设置中断优先级HAL_NVIC_EnableIRQ(USART1_IRQn);//使能中断通道}
}
//编写中断服务函数
void USART1_IRQHandler()
{HAL_UART_IRQHandler(&usart1_handler);//由于调用一次中断,进入中断回调函数后,中断就结束了,所以还要开启中断HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata));//使能接收中断
}
//编写接收完成中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{u8 rec;if(huart->Instance==USART1){//rec = *((huart->pRxBuffPtr)-1);rec = rdata[0];//保存接收到的数据HAL_UART_Transmit(&usart1_handler,&rec,1,1000);}
}
int main(void)
{Cache_Enable(); //打开L1-CacheHAL_Init(); //初始化HAL库Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz delay_init(216);uart1_init();HAL_UART_Receive_IT(&usart1_handler,rdata,sizeof(rdata));//使能接收中断while(1){}}
STM32 串口接收流程-串口接收中断相关推荐
- STM32串口接收数据
参考串口接收中断处理函数: //------------------------------------------------------------------ //函数名:void USART1 ...
- openmv串口数据 串口助手_STM32 串口接收不定长数据 STM32 USART空闲检测中断
编者注: 单片机串口接收不定长数据时,必须面对的一个问题为:怎么判断这一包数据接收完成了呢?常见的方法主要有以下两种: 1.在接收数据时启动一个定时器,在指定时间间隔内没有接收到新数据,认为数据接收完 ...
- stm32串口接收不定长数据_基于STM32之UART串口通信协议--接收
一.前言 1.简介 回顾上一篇UART发送当中,已经讲解了如何实现UART的发送操作了,接下来这一篇将会继续讲解如何实现UART的接收操作. 2.UART简介 嵌入式开发中,UART串口通信协议是我们 ...
- CubeMX STM32串口1DMA使用IDLE中断接收、串口2DMA接收DMX512信号(标准)
CubeMX STM32串口1DMA使用IDLE中断接收.串口2DMA收发DMX512信号(标准) DMX512协议 CubeMX 代码部分 串口1 串口2 外部中断 定时器1 总结 DMX512协议 ...
- 【STM32入门100步--学习笔记】USART串口接收程序(含教学视频)
STM32串口接收的程序和8051单片机一样,有2种接收方式:中断处理和查询方式. 试过两种方式之后发现,中断处理方式更方便,可以扩展多个数据的接收.推荐中断方式. 我已经将本资料内容整理后录制了视频 ...
- STM32串口接收不定长数据原理与源程序
**STM32串口接收不定长数据原理与源程序**CSDN上有很多关于STM32串口接收不定长数据的文章,但实际使用后发现照搬他们的代码,程序根本就不能正确接收数据,其中最关键的一句有问题.其余内容完全 ...
- STM32串口接收粉尘传感器数据
本文章主要记录STM32实现对粉尘传感器的数据采集及简单处理. 材料: 1.正点原子Mini开发板STM32f103RC 2.ZH03A激光粉尘传感器 3.USB TO TTL线(就是烧写51单片机的 ...
- STM32串口接收数据处理方法
STM32串口接收数据处理方法 STM32串口接收定长数据处理方法 STM32串口接收定长数据的处理方法非常简单,我目前做项目都是用的这个,也可用做处理MODBUS协议,直接上代码. void USA ...
- stm32串口接收不到数据的一些问题
菜鸟写的经验,大佬勿喷!! 最近在搞stm32的接收通信,用的正点原子的例程,打算用串口2进行通信,然后发现各种各样的的问题.比如只能收到一个字符,只能收到首个和末尾两个字符,收到字符时死机-等等一堆 ...
最新文章
- Python 对图像进行base64编码及解码读取为numpy、opencv、matplot需要的格式
- Python字符串常用操作
- 在linux下,如何在C语言中使用正则表达式
- java 数组中某个数出现的概率_剑指Offer解题报告(Java版)——排序数组中某个数的个数 38...
- 有时在Java中,一个布局管理器是不够的
- php imap 附件,学习猿地-PHP-imap 使用参考
- 在深圳呆那么就感觉伤心了有木有?
- Golang笔记——map
- java 在已有的so基础上封装jni_webshell中的分离免杀实践java篇
- java 序列化 缓存_由缓存导致的一个java序列化问题
- 比特币的服务器作用,比特币白皮书解读-时间戳服务器
- 聊聊 | 他在Google Play安全奖励计划贡献榜单上排名第一
- CSS3动画的常见属性(CSS3)
- C++——unique()和unique_copy()
- “舌尖上的安全”:基于区块链构建四位一体的食品安全社会共治体系
- Java通过SSH实现文件上传下载功能
- linux一键烧写应用程序工具--自制
- HASH JOIN ,MERGE JOIN ,NESTED LOOP用法效率比较
- 3DMax2021建模入门篇
- pr爱情模板,2.14情人节爱情告白视频模板素材
热门文章
- iBatis for Net 代码生成器(CodeHelper)附下载地址(已经升级为V 1.1)
- struts2显示列表序号的办法
- Linux ubuntu安装搜狗输入法
- php 识别图片主色调,PHP 判断图片主色调的简单示例
- 如何用计算机算矩阵,【活用工具】教你如何用卡西欧fx82es计算机计算复数 矩阵...
- crt 8.7.3 黑暗模式_科技有意思 | 黑黑黑黑黑黑黑黑暗模式
- php黄页,PHP 黄页的url
- php 放大镜,图片放大镜效果实战总结
- java开发环境怎么写_Java开发基础设置:如何配置Java运行环境
- Windows11安全中心打不开怎么办 Win11打不开安全中心解决方法