历史上的今天
今天是:2025年01月07日(星期二)
2019年01月07日 | STM32 IDLE中断
2019-01-07 来源:eefocus
今天说一下STM32单片机的接收不定长度字节数据的方法。由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。
IDLE中断什么时候发生?
IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。
如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。
看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。
如何配置好IDLE中断?
下面我们就配置好串口IDLE中断吧。

这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)
(RXNE中断和IDLE中断的区别? 当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。)

这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1.
需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的)
下面以STM32F103为例给出源程序。
我们先来看程序中的主要部分。
串口初始化函数片段

%E7%A9%BA%E9%97%B2%E4%B8%AD%E6%96%AD.png?imageView2/2/w/550 (17.99 KB, 下载次数: 45)
下载附件 保存到相册 2015-10-29 23:11 上传
如果你原来的串口初始化函数具有打开串口接收中断的话,实际上就是在初始化函数中多了一条打开空闲中断的语句。
串口中断函数

串口中断函数里面,最重要的两条语句,就是上图中圈出来的两条语句。第一条语句用来判断是否接收到1个字节,第二条语句用来判断是否接收到1帧数据。(是不是感觉超级方便?妈妈再也不用担心我如何判断是否接收完1帧数据了。)
主函数

我写的这个主函数,是用来验证接收的正确性的。RxCounter表示的是这一帧数据有几个字节,接收完一帧数据,会在中断函数里面把ReceiveState置1,然后,通过串口把接收到的数据发送回串口。这样,既验证了接收了多少字节的正确性,又验证了接收到的数据是否正确。

上图是结果验证。
我是瑞生,毫无保留的给大家透露电子设计经验,不定时分享实用的落地的电子设计技巧,希望能够帮助到大家。
/**
******************************************************************************
* @file 串口接收不定长字节数据
* @author 瑞生
* @version V1.0
* @date 2015.10.23
* @brief Main program body
******************************************************************************
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "uart.h"
volatile uint8_t aRxBuffer[100]={0x00};
volatile uint8_t RxCounter=0;
volatile uint8_t ReceiveState=0;
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
uint8_t i=0;
USART1_Init();
while (1)
{
if(ReceiveState==1)//如果接收到1帧数据
{
ReceiveState=0;
i=0;
while(RxCounter--)// 把接收到数据发送回串口
{
USART_SendData(USART1, aRxBuffer[i++]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
RxCounter=0;
}
}
}
史海拾趣
|
在生产过程自动化装置中,PLC、DCS是两类应用最广泛的控制系统,上世纪80年代之前,这些控制系统的I/O卡件均集中在远离现场的控制室内,与现场装置(其中包括AI/AO模拟量输入输出装置和DI/DO 开关量输入输出装置等)的连接线都是 ...… 查看全部问答> |
|
中国科学院深圳先进技术研究院是中国科学院、深圳市政府和香港中文大学 共建的国立科研机构,定位为工业研究院,从事先进制造业和信息产业的研究、 开发以及产业化 参见www.siat.ac.cn 现招聘微波、电磁场方向博士研究人员 要求: 1.微波、电 ...… 查看全部问答> |
|
业界致力于为家庭网络建立一个网状网络(mesh)标准的行动,招致各方不同的反应;支持者宣扬该计划是为覆盖全家庭的网络创造未来,敌对阵营却批评他们是后知后觉。至于那些曾经从事其他无线网状网络标准的人,表示那不会是一项简单任务,甚至有些人表 ...… 查看全部问答> |
|
HANDLE hevt = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT(\"SYSTEM/ShellAPIReady\")); ASSERT(NULL != hevt); & ...… 查看全部问答> |
|
我在用NRF905做一个无线通信的模块时,但是始终收不到信号。我身边只有万用表,没有频谱仪之类的,大伙觉得用万用表可以测量天线上面是否有信号吗 … 查看全部问答> |
|
前段时间做了1块DSP28335的板卡。基本功能都已经实现,程序在内部FLASH运行正常。 目前遇到新的问题: 后期有可能程序比较大,内部FLASH存放不下,于是通过XZCS7外扩了1片FLASH(SST39VF1602B-70) 目前想测试将程 ...… 查看全部问答> |
|
为什么在程序中加了math头文件后,程序还是识别不了里面的库函数,例如sinf。急急.... 本人是新手,接触VxWorks时间不长。本人在Tornado的开发环境中编译没有任何问题。单下载到DSP上就报错 说无法识别math里面的库函数。程序中也加了头文件,不知问题出在哪里,还请各位大神帮帮忙。很急很急。… 查看全部问答> |




