串口接收

串口接收流程

  1. 编程USARTx_CR1的M位来定义字长。
  2. 编程USARTx_CR2的STOP位来定义停止位位数。
  3. 编程USARTx_BRR寄存器确定波特率。
  4. 使能USARTx_CR1的UE位使能USARTx。
  5. 如果进行多缓冲通信,配置USARTx_CR3的DMA使能(DMAT)。
  6. 使能USARTx_CR1的RE位为1使能接收器。
  7. 如果要使能接收中断(接收到数据后产生中断),使能USARTx_CR1的RXNEIE位为1。

当串口接收到数据时

  1. USARTx_SR(ISR)的RXNE位置1。表明移位寄存器内容已经传输到RDR(DR)寄存器。已经接收到数据并且等待读取。
  2. 如果开启了接收数据中断(USARTx_CR1寄存器的RXNEIE位为1),则会产生中断。(程序上会执行中断服务函数)
  3. 如果开启了其他中断(帧错误等),相应标志位会置1。
  4. 读取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库)

  1. 初始化串口相关参数,使能串口:HAL_UART_Init();
  2. 串口相关IO口配置,复用配置:
    在HAL_UART_MspInit中调用HAL_GPIO_Init函数。
  3. 串口接收中断优先级配置和使能:
    HAL_NVIC_EnableIRQ();
    HAL_NVIC_SetPriority();
  4. 使能串口接收中断:HAL_UART_Receive_IT();
  5. 编写中断服务函数: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返回给电脑。

  1. 初始化串口相关参数,使能串口:HAL_UART_Init();
  2. 串口相关IO口配置,复用配置:
    在HAL_UART_MspInit中调用HAL_GPIO_Init函数。
  3. 串口接收中断优先级配置和使能:
    HAL_NVIC_EnableIRQ();
    HAL_NVIC_SetPriority();
  4. 使能串口接收中断:HAL_UART_Receive_IT();
  5. 编写中断服务函数: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 串口接收流程-串口接收中断相关推荐

  1. STM32串口接收数据

    参考串口接收中断处理函数: //------------------------------------------------------------------ //函数名:void USART1 ...

  2. openmv串口数据 串口助手_STM32 串口接收不定长数据 STM32 USART空闲检测中断

    编者注: 单片机串口接收不定长数据时,必须面对的一个问题为:怎么判断这一包数据接收完成了呢?常见的方法主要有以下两种: 1.在接收数据时启动一个定时器,在指定时间间隔内没有接收到新数据,认为数据接收完 ...

  3. stm32串口接收不定长数据_基于STM32之UART串口通信协议--接收

    一.前言 1.简介 回顾上一篇UART发送当中,已经讲解了如何实现UART的发送操作了,接下来这一篇将会继续讲解如何实现UART的接收操作. 2.UART简介 嵌入式开发中,UART串口通信协议是我们 ...

  4. CubeMX STM32串口1DMA使用IDLE中断接收、串口2DMA接收DMX512信号(标准)

    CubeMX STM32串口1DMA使用IDLE中断接收.串口2DMA收发DMX512信号(标准) DMX512协议 CubeMX 代码部分 串口1 串口2 外部中断 定时器1 总结 DMX512协议 ...

  5. 【STM32入门100步--学习笔记】USART串口接收程序(含教学视频)

    STM32串口接收的程序和8051单片机一样,有2种接收方式:中断处理和查询方式. 试过两种方式之后发现,中断处理方式更方便,可以扩展多个数据的接收.推荐中断方式. 我已经将本资料内容整理后录制了视频 ...

  6. STM32串口接收不定长数据原理与源程序

    **STM32串口接收不定长数据原理与源程序**CSDN上有很多关于STM32串口接收不定长数据的文章,但实际使用后发现照搬他们的代码,程序根本就不能正确接收数据,其中最关键的一句有问题.其余内容完全 ...

  7. STM32串口接收粉尘传感器数据

    本文章主要记录STM32实现对粉尘传感器的数据采集及简单处理. 材料: 1.正点原子Mini开发板STM32f103RC 2.ZH03A激光粉尘传感器 3.USB TO TTL线(就是烧写51单片机的 ...

  8. STM32串口接收数据处理方法

    STM32串口接收数据处理方法 STM32串口接收定长数据处理方法 STM32串口接收定长数据的处理方法非常简单,我目前做项目都是用的这个,也可用做处理MODBUS协议,直接上代码. void USA ...

  9. stm32串口接收不到数据的一些问题

    菜鸟写的经验,大佬勿喷!! 最近在搞stm32的接收通信,用的正点原子的例程,打算用串口2进行通信,然后发现各种各样的的问题.比如只能收到一个字符,只能收到首个和末尾两个字符,收到字符时死机-等等一堆 ...

最新文章

  1. Python 对图像进行base64编码及解码读取为numpy、opencv、matplot需要的格式
  2. Python字符串常用操作
  3. 在linux下,如何在C语言中使用正则表达式
  4. java 数组中某个数出现的概率_剑指Offer解题报告(Java版)——排序数组中某个数的个数 38...
  5. 有时在Java中,一个布局管理器是不够的
  6. php imap 附件,学习猿地-PHP-imap 使用参考
  7. 在深圳呆那么就感觉伤心了有木有?
  8. Golang笔记——map
  9. java 在已有的so基础上封装jni_webshell中的分离免杀实践java篇
  10. java 序列化 缓存_由缓存导致的一个java序列化问题
  11. 比特币的服务器作用,比特币白皮书解读-时间戳服务器
  12. 聊聊 | 他在Google Play安全奖励计划贡献榜单上排名第一
  13. CSS3动画的常见属性(CSS3)
  14. C++——unique()和unique_copy()
  15. “舌尖上的安全”:基于区块链构建四位一体的食品安全社会共治体系
  16. Java通过SSH实现文件上传下载功能
  17. linux一键烧写应用程序工具--自制
  18. HASH JOIN ,MERGE JOIN ,NESTED LOOP用法效率比较
  19. 3DMax2021建模入门篇
  20. pr爱情模板,2.14情人节爱情告白视频模板素材

热门文章

  1. iBatis for Net 代码生成器(CodeHelper)附下载地址(已经升级为V 1.1)
  2. struts2显示列表序号的办法
  3. Linux ubuntu安装搜狗输入法
  4. php 识别图片主色调,PHP 判断图片主色调的简单示例
  5. 如何用计算机算矩阵,【活用工具】教你如何用卡西欧fx82es计算机计算复数 矩阵...
  6. crt 8.7.3 黑暗模式_科技有意思 | 黑黑黑黑黑黑黑黑暗模式
  7. php黄页,PHP 黄页的url
  8. php 放大镜,图片放大镜效果实战总结
  9. java开发环境怎么写_Java开发基础设置:如何配置Java运行环境
  10. Windows11安全中心打不开怎么办 Win11打不开安全中心解决方法