历程详解

详解包括:

中断原理讲解

例程流程详解

库函数分析详解

对应寄存器介绍

对应函数介绍

对应注释详解

本篇文章提供两种方法:

一种是 :IDLE 接收空闲中断+DMA

一种是: IDLE 接收空闲中断+RXNE接收数据中断

都可完成串口数据的收发

知识点介绍:

STM32 IDLE 接收空闲中断

功能:

在使用串口接受字符串时,可以使用空闲中断(IDLEIE置1,即可使能空闲中断),这样在接收完一个字符串,进入空闲状态时(IDLE置1)便会激发一个空闲中断。在中断处理函数,我们可以解析这个字符串。

接受完一帧数据,触发中断

STM32的IDLE的中断产生条件:

在串口无数据接收的情况下,不会产生,当清除IDLE标志位后,必须有接收到第一个数据后,才开始触发,一但接收的数据断流,没有接收到数据,即产生IDLE中断

STM32 RXNE接收数据中断

功能:

当串口接收到一个bit的数据时,(读取到一个停止位) 便会触发 RXNE接收数据中断

接受到一个字节的数据,触发中断

比如给上位机给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。

串口CR1寄存器

对bit4写1开启IDLE接受空闲中断

,对bit5写1开启RXNE接收数据中断。

串口ISR寄存器

此寄存器为串口状态查询寄存器

当串口接收到数据时,bit5 RXNE就会自动变成1,当接收完一帧数据后,bit4就会变成1.

清除RXNE中断标志位的方法为:

只要把接收到的一个字节读出来,就会清除这个中断

在STM32F1 /STM32F4 系列中 清除IDLE中断标志位的方法为:

先读SR寄存器,

再读DR寄存器。

memset()函数

extern void *memset(void *buffer, int c, int count)

buffer:为指针或是数组

c:是赋给buffer的值

count:是buffer的长度.

USART采用DMA接收时,如何读取当前接收字节数?

#define __HAL_DMA_GET_COUNTER(__HANDLE__) ((__HANDLE__)->Instance->CNDTR);

DMA接收时该宏将返回当前接收空间剩余字节

实际接受的字节= 预先定义的接收总字节 - __HAL_DMA_GET_COUNTER()

其本质就是读取NTDR寄存器,DMA通道结构体中定义了NDTR寄存器,读取该寄存器即可得到未传输的数据数呢,

NTDR寄存器

实现方法:

两种利用串口IDLE空闲中断的方式接收一帧数据,方法如下:

方法1:实现思路:采用STM32F103的串口1,并配置成空闲中断IDLE模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这次接受的数据长度是200个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区数组里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);函数计算出当前DMA接收存储空间剩余字节

本次的数据接受长度=预先定义的接收总字节-接收存储空间剩余字节

比方说 本次串口接受200个字节,

HAL_UART_Receive_DMA(&huart1,rx_buffer,200);//打开DMA接收

然后我发送了 Zxiaoxuan 9个字节的数据长度

那么此时 GET_COUNTER函数读出来 接收存储空间剩余字节 就是191个字节

实际接受的字节(9) = 预先定义的接收总字节(200) - __HAL_DMA_GET_COUNTER()(191)

9 = 200-191

应用对象:适用于各种串口相关的通信协议,如:MODBUS,PPI ;还有类似于GPS数据接收解析,串口WIFI的数据接收等,都是很好的应用对象。

方法2:实现思路:直接利用stm32的RXNE和IDLE中断进行接收不定字节数据。 每次接收到一个字节的数据,触发RXNE中断 将该字节数据存放到数组里,传输完成之后,触发一次IDLE中断,对已经获取到的数据进行处理

例程1

本例程功能:

使用DMA+串口接受空闲中断 实现将接收的数据完整发送到上位机的功能

接收数据的流程:

首先在初始化的时候打开DMA接收,当MCU通过USART接收外部发来的数据时,在进行第①②③步的时候,DMA直接将接收到的数据写入缓存rx_buffer[100] //接收数据缓存数组,程序此时也不会进入接收中断,在软件上无需做任何事情,要在初始化配置的时候设置好配置就可以了。

数据接收完成的流程:

当数据接收完成之后产生接收空闲中断④

在中断服务函数中做这几件事:

判断是否为IDLE接受空闲中断

在中断服务函数中将接收完成标志位置1

关闭DMA防止在处理数据时候接收数据,产生干扰。

计算出接收缓存中的数据长度,清除中断位,

while循环 主程序流程:

主程序中检测到接收完成标志被置1

进入数据处理程序,现将接收完成标志位置0,

将接收到的数据重新发送到上位机

重新设置DMA下次要接收的数据字节数,使能DMA进入接收数据状态。

例程代码:

uart.c

volatile uint8_t rx_len = 0;  //接收一帧数据的长度

volatile uint8_t recv_end_flag = 0; //一帧数据接收完成标志

uint8_t rx_buffer[100]={0};  //接收数据缓存数组

void MX_USART1_UART_Init(void)

{

huart1.Instance = USART1;

huart1.Init.BaudRate = 115200;

huart1.Init.WordLength = UART_WORDLENGTH_8B;

huart1.Init.StopBits = UART_STOPBITS_1;

huart1.Init.Parity = UART_PARITY_NONE;

huart1.Init.Mode = UART_MODE_TX_RX;

huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;

huart1.Init.OverSampling = UART_OVERSAMPLING_16;

if (HAL_UART_Init(&huart1) != HAL_OK)

{

Error_Handler();

}

//下方为自己添加的代码

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能IDLE中断

//DMA接收函数,此句一定要加,不加接收不到第一次传进来的实数据,是空的,且此时接收到的数据长度为缓存器的数据长度

HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);

}

uart.h

extern UART_HandleTypeDef huart1;

extern DMA_HandleTypeDef hdma_usart1_rx;

extern DMA_HandleTypeDef hdma_usart1_tx;

/* USER CODE BEGIN Private defines */

#define BUFFER_SIZE  100

extern  volatile uint8_t rx_len ;  //接收一帧数据的长度

extern volatile uint8_t recv_end_flag; //一帧数据接收完成标志

extern uint8_t rx_buffer[100];  //接收数据缓存数组

main.c

/*

*********************************************************************************************************

* 函 数 名: DMA_Usart_Send

* 功能说明: 串口发送功能函数

* 形  参: buf,len

* 返 回 值: 无

*********************************************************************************************************

*/

void DMA_Usart_Send(uint8_t *buf,uint8_t len)//串口发送封装

{

if(HAL_UART_Transmit_DMA(&huart1, buf,len)!= HAL_OK)   //判断是否发送正常,如果出现异常则进入异常中断函数

{

Error_Handler();

}

}

/*

*********************************************************************************************************

* 函 数 名: DMA_Usart1_Read

* 功能说明: 串口接收功能函数

* 形  参: Data,len

* 返 回 值: 无

*********************************************************************************************************

*/

void DMA_Usart1_Read(uint8_t *Data,uint8_t len)//串口接收封装

{

HAL_UART_Receive_DMA(&huart1,Data,len);//重新打开DMA接收

}

while循环

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

if(recv_end_flag == 1)  //接收完成标志

{

DMA_Usart_Send(rx_buffer, rx_len);

rx_len = 0;//清除计数

recv_end_flag = 0;//清除接收结束标志位

//

for(uint8_t i=0;i

//

{

//

rx_buffer[i]=0;//清接收缓存

//

}

memset(rx_buffer,0,rx_len);

}

HAL_UART_Receive_DMA(&huart1,rx_buffer,BUFFER_SIZE);//重新打开DMA接收

}

stm32f1xx_it.c中

#include "usart.h"

void USART1_IRQHandler(void)

{

uint32_t tmp_flag = 0;

uint32_t temp;

tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位

if((tmp_flag != RESET))//idle标志被置位

{

__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位

//temp = huart1.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能

//temp = huart1.Instance->DR; //读取数据寄存器中的数据

//这两句和上面那句等效

HAL_UART_DMAStop(&huart1); //  停止DMA传输,防止

temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);// 获取DMA中未传输的数据个数

//temp  = hdma_usart1_rx.Instance->NDTR;// 读取NDTR寄存器,获取DMA中未传输的数据个数,

rx_len =  BUFFER_SIZE - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数

recv_end_flag = 1;

// 接受完成标志位置1

}

HAL_UART_IRQHandler(&huart1);

}

注释详解:

注释1:

temp = UartHandle.Instance->SR;  //清除状态寄存器SR,读取SR寄存器可以实现清除SR寄存器的功能

temp = UartHandle.Instance->DR; //读取数据寄存器中的数据

这两句被屏蔽的原因是它们实现的功能和这下面串口IDLE状态寄存器SR标志位清零的宏定义实现的功能是一样的:

__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位

我们可以点击这个宏定义进去看看,它实现的功能和上面两句是一样的:

#define __HAL_UART_CLEAR_IDLEFLAG(HANDLE) __HAL_UART_CLEAR_PEFLAG(HANDLE)

注释2:

temp  = hdma_usart1_rx.Instance->NDTR;// 获取DMA中未传输的数据个数,NDTR寄存器分析见下面

同理, 这句被屏蔽的原因是因为他和上面的__HAL_DMA_GET_COUNTER的作用也是一样的,都可以获取DMA中未传输的数据个数

测试正常:

此程序可以进

关键字:

STM32

HAL

CubeMX

串口

IDLE接收

空闲中断

DMA

编辑:什么鱼 引用地址:

http://news.eeworld.com.cn/mcu/ic507322.html

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

stm32的rxne和idle中断_STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA相关推荐

  1. STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA

    关于DMA原理部分讲解,及CubeMx配置部分,请参考该文章 [STM32]HAL库 STM32CubeMX教程十一-DMA (串口DMA发送接收) 本篇文章我们仅针对例程进行详解剖析 历程详解 详解 ...

  2. GD32F303调试小记(一)之USART(接收中断、接收空闲中断+DMA、发送DMA)

    前言 之前写了GD32F103调试小记(二)之USART(接收中断.接收空闲中断+DMA.发送DMA)一文.这次我们来看看GD32F303的USART是如何配置的,结合这两篇文章,相信大家GD32的U ...

  3. hal库开启中断关中断_STM32 HAL库学习系列第9篇---NVIC按键外部中断函数

    原文首发于同名微信公号「Allen5G」,欢迎大家搜索关注! **针对HAL库的中断操作,使用按键实例进行说下,以供参考---------------------------**void HAL_GP ...

  4. hal库串口dma卡死_STM32 HAL库 串口DMA发送完成中断

    近期使用STM32驱动MAX3485进行485通信,发现STM32F103C8并不自带硬件485首发功能,需要软件上控制IO高低来驱动MAX3485进行485接收.485发送. 根据MAX3485手册 ...

  5. hal 双串口同时接收丢失数据_【STM32Cube_06】使用USART发送和接收数据(查询模式)...

    寻求更简洁舒适的阅读体验,请移步Mculover666的个人博客: [STM32Cube_06]使用USART发送和接收数据(查询模式)​www.mculover666.cn 本篇文章主要介绍如何使用 ...

  6. stm32LL库串口空闲中断+DMA接收

    stm32LL库串口空闲中断+DMA接收 俺用的STM32F407VGT6,cubemx生成的代码. cubemx的串口配置 这里就按默认参数配就行,主要是要打开后面的DMA 在这里点添加就完事了,如 ...

  7. stm32: 串口空闲中断的实现(HAL库)

    STM32利用串口空闲中断来分包(HAL库) 文章目录 STM32利用串口空闲中断来分包(HAL库) 1. 开发环境 2. 串口中断接收的问题和解决办法 3. 串口空闲中断分包的原理 4. STM32 ...

  8. STM32使用串口IDLE中断的两种接收不定长数据的方式

    现在有很多数据处理都要用到不定长数据,而单片机串口的RXNE中断一次只能接收一个字节的数据,没有缓冲区,无法接收一帧多个数据,现提供两种利用串口IDLE空闲中断的方式接收一帧数据,方法如下: 方法1: ...

  9. stm32 USART接收总线空闲中断--USART_IT_IDLE

    stm32 USART接收总线空闲中断--USART_IT_IDLE 版权声明:转载请注明作者和链接 https://blog.csdn.net/Hola_ya/article/details/815 ...

最新文章

  1. 【Sql Server】DateBase-事务
  2. Windows Phone访问web service和WCF服务
  3. android studio module不识别 红色j,androidstudio 不显示 Module-- 新年第一波
  4. boost::hana::is_nothing用法的测试程序
  5. 写论文,这个神器不能少!
  6. Exception: SQLSTATE[22001]
  7. SPT20 协议_过户协议书模板五篇
  8. ios java 通信_Kurento Java Spring Client IOS – Web到IOS通信
  9. Shiro【授权过滤器、与ehcache整合、验证码、记住我】
  10. spark压缩和序列化相关
  11. python库-密码学库pynacl
  12. 最新小米线刷救砖工具分享+支持全系通用
  13. 最适合程序猿的笔记软件
  14. Android——启动本地QQ,实现与指定的QQ号临时会话
  15. Vue3配置路由ERROR in [eslint]报错问题
  16. Intellij IDEA 2019 最新优化配置
  17. 【高数】如何由解倒求微分方程?及微分方程的阶数、任意常数、特征根的关系
  18. linux sniffer 程序使用,Linux下Sniffer程序的实现
  19. phpStudy的建站与踩坑,与微信公众号对接
  20. 吸拖一体机和扫地机器人哪个好,吸拖一体机值得买吗

热门文章

  1. Nginx的启动、停止、重启
  2. 如何合理命名你的代码
  3. [改善Java代码]枚举项的数量限制在64个以内
  4. [转发] 老叶观点:MySQL开发规范之我见
  5. 用SQL中的isnull函数注意了
  6. 去雾综述_图像去雾的算法历史与综述
  7. android 上传头像工具类,Android开发中如何实现头像的更换与上传
  8. Python+sklearn随机森林算法使用入门
  9. Python花式编程:6种方法计算1!+2!+...+n!
  10. Python+matplotlib数据可视化设置图例3个精选案例