有一次做一个东西,为了尽量不占用CPU的处理数据时间,所以就使用DMA接收串口的数据,但是呢问题来了.,,,,,怎么样才能确定接收到了一条完整的数据了,,我们都知道只要打开DMA

那家伙就不停的把接收的数据放到我们指定的地方.

只要接收到一条完整的数据我就该去处理了

关于空闲中断,,,就是说每接收到一条完整的数据就会置位空闲标志位,我们只需要判断空闲标志位是否置一,,就能知道是不是接收到了一条完整的数据

用空闲中断的好处就是,,对于以前我写程序通信都会在数据的后面加上尾,,然后另一个接收的单片机通过判断数据的尾来确定是不是一条完整的数据,,,有了空闲中断就不需要在给数据加上尾了,,,,,

直接程序吧

u8  Usart1_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart1_RX_BUF[1024]={0};   //串口1接收缓冲,最大 1024 个字节.
u16 Usart1_REC_Cnt = 0;        //串口1接收的数据个数
u16 Usart1_Current_Cnt = 0;    //串口1当前接收的数据个数
u16 Usart1_Current_cnt = 0;    //串口1当前接收的数据个数
u8  Usart1_AT_flage = 0;       //串口1接收完成标志位u8  Usart2_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart2_RX_BUF[1024]={0};   //串口2接收缓冲,最大 1024 个字节.
u16 Usart2_REC_Cnt = 0;        //串口2接收的数据个数
u16 Usart2_Current_Cnt = 0;    //串口2当前接收的数据个数
u16 Usart2_Current_cnt = 0;    //串口2当前接收的数据个数
u8  Usart2_AT_flage = 0;       //串口2接收完成标志位u8  Usart3_RX_BUF[1024]={0};   //串口3接收缓冲,最大 1024 个字节.
u16 Usart3_REC_Cnt = 0;        //串口3接收的数据个数
u8  Usart3_AT_flage = 0;       //串口3接收完成标志位u8 Free_Read_Rst = 0;//读DR清除空闲中断

void USART123_Init(uint32_t bound_1,uint32_t bound_2,uint32_t bound_3)
{USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB1Periph_USART3, ENABLE);//使能USART2,USART3时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO , ENABLE);//USART1_TX  PA9GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//USART1_RX  PA10GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING ;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_Init(GPIOA, &GPIO_InitStructure);//USART2_TX   GPIOA.2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//USART2_RX      GPIOA.3初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//USART3_TX   GPIOB.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure);//USART3_RX      GPIOB.11初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = bound_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No ;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接受中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启串口接受中断USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); //开启串口1总线空闲中断USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //开启串口2总线空闲中断USART_InitStructure.USART_BaudRate = bound_2;USART_Init(USART2, &USART_InitStructure);USART_InitStructure.USART_BaudRate = bound_3;USART_Init(USART3, &USART_InitStructure);USART_Cmd(USART1, ENABLE);USART_Cmd(USART2, ENABLE);USART_Cmd(USART3, ENABLE);
}

/********************串口 1 中断服务程序**********************/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //正常情况下进入这个接收 {USART_ClearITPendingBit(USART1, USART_FLAG_ORE); USART_ClearITPendingBit(USART1,USART_IT_ORE);    //清除中断标志Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);    //读取接收到的数据Usart1_REC_Cnt++;}else if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)//传输完一条完整的数据就会进入这个{Free_Read_Rst = USART1->DR; //清USART_IT_IDLE标志Usart1_AT_flage = 1;//接收到一条完整的数据Usart1_Current_Cnt = Usart1_REC_Cnt;//复制接收到的数据个数Usart1_REC_Cnt = 0;//清零接收的个数}
}

主函数循环里只需要......

先说一点:单片机的串口可以接收任意波特率的数据,你所写的9600意思是以这个波特率发送....

其实昨天才发现这家伙真的太准确了,,准确到如果碰见通信中速率如果不是设置的波特率,就是说通信的速率慢了不是(我上面设置的波特率是9600)1/9600(S)发过来一位数据了,低于了这个值假设是2400吧!接受到一位数据后如果1/9600(s)后没有接收到数据,那么这家伙也会进空闲中断.......因为你是设置的9600,,,,那么在1/9600(s)后理应接收到下一位数据....而其实是在1/2400(S)后才会接收到另一位数据.....如果能把空闲中断的检测时间降到满足的要求就好了....

所以嘛,,,,,自己写个别这么苛刻的,昨天写好了,不过呢今天主要是把自己遇到的问题说一下

其实思路都知道

串口接收的时候打开一个定时器,并且只要接收到数据就清零一个变量,这个变量是在定时器里面执行自加一操作,,

如果串口一段时间(空闲中断的检测时间)不接收数据了这个变量就能自加到我们设置的数,然后关掉定时器,置位接收完成标志位,...

直接上程序

/********************串口 1 中断服务程序**********************/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  {USART_ClearITPendingBit(USART1, USART_FLAG_ORE); USART_ClearITPendingBit(USART1,USART_IT_ORE);    //清除中断标志Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);    //读取接收到的数据Usart1_REC_Cnt++;TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE );//打开定时器开始计时Time2_cnt = 0;//清零计数}
}

void timer_config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/* Resets the TIM2 */TIM_DeInit(TIM2);//设置了时钟分割。TIM_TimeBaseStructure.TIM_ClockDivision = 0;// 选择了计数器模式。TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//初值TIM_TimeBaseStructure.TIM_Period = 10;//定时时间1ms进一次//设置了用来作为 TIMx 时钟频率除数的预分频值。72M / 7099+1 = 0.01MTIM_TimeBaseStructure.TIM_Prescaler = 7199;//TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ClearITPendingBit(TIM2, TIM_IT_Update);/* Enables the TIM2 counter */TIM_Cmd(TIM2, ENABLE);/* Enables the TIM2 Capture Compare channel 1 Interrupt source */TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );
}

void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);if(Time2_cnt<100)//防止累加循环过去{Time2_cnt ++ ;}if(Time2_cnt>3)//空闲时间大于约3毫秒{TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );//关闭定时器---注意千万不要放到主函数里面关,,,,大家可以试一试会出现什么问题.....Usart1_AT_flage = 1;//接收完成标志位置一Usart1_Current_Cnt = Usart1_REC_Cnt;//赋值接收的数据个数Usart1_REC_Cnt = 0;//清零接收的数据个数}
}

然后昨天又写了一个两个串口的,因为用了两个串口做数据转换(用的串口1和串口3),,,,其实其中一个也可以用空闲中断,,但是担心数据传输过程中万一速率有所变化,,,,,,,,完蛋啦

uint8_t  Usart1_TimeFlage = 0;//串口1空闲变量允许累加标志
uint16_t Usart1_IdealTime = 0;//串口1空闲累加变量
uint8_t  Usart3_TimeFlage = 0;//串口3空闲变量允许累加标志
uint16_t Usart3_IdealTime = 0;//串口3空闲累加变量
u8  Usart1_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart1_RX_BUF[1024]={0};   //串口1接收缓冲,最大 1024 个字节.
u16 Usart1_REC_Cnt = 0;        //串口1接收的数据个数
u16 Usart1_Current_Cnt = 0;    //串口2当前接收的数据个数
u16 Usart1_Current_cnt = 0;    //串口2当前接收的数据个数
u8  Usart1_AT_flage = 0;       //串口1接收完成标志位u8  Usart2_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart2_RX_BUF[1024]={0};   //串口2接收缓冲,最大 1024 个字节.
u16 Usart2_REC_Cnt = 0;        //串口2接收的数据个数
u16 Usart2_Current_Cnt = 0;    //串口2当前接收的数据个数
u16 Usart2_Current_cnt = 0;    //串口2当前接收的数据个数
u8  Usart2_AT_flage = 0;       //串口2接收完成标志位u8  Usart3_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart3_RX_BUF[1024]={0};   //串口2接收缓冲,最大 1024 个字节.
u16 Usart3_REC_Cnt = 0;        //串口2接收的数据个数
u16 Usart3_Current_Cnt = 0;    //串口2当前接收的数据个数
u16 Usart3_Current_cnt = 0;    //串口2当前接收的数据个数
u8  Usart3_AT_flage = 0;       //串口2接收完成标志位

void timer3_config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);/* Resets the TIM2 */TIM_DeInit(TIM3);//设置了时钟分割。TIM_TimeBaseStructure.TIM_ClockDivision = 0;// 选择了计数器模式。TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//初值TIM_TimeBaseStructure.TIM_Period = 10;//定时时间1Ms进一次//设置了用来作为 TIMx 时钟频率除数的预分频值。72M / 7099+1 = 0.01MTIM_TimeBaseStructure.TIM_Prescaler = 7199;//TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);TIM_ClearITPendingBit(TIM3, TIM_IT_Update);/* Enables the TIM2 counter */TIM_Cmd(TIM3, ENABLE);/* Enables the TIM2 Capture Compare channel 1 Interrupt source */TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE );
}

void TIM3_IRQHandler(void)
{if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET){TIM_ClearITPendingBit(TIM3, TIM_IT_Update);if(Usart1_TimeFlage == 1)//开始累加空闲变量{if(Usart1_IdealTime<400)//防止累加过去,造成循环{Usart1_IdealTime++;//空闲变量累加}}if(Usart1_IdealTime>=100)//调节这个值以适应不同的接收速率{Usart1_TimeFlage = 0;//停止空闲变量累加Usart1_IdealTime = 0;//清零空闲累加变量Usart1_AT_flage = 1; //接收标志位置一Usart1_Current_Cnt = Usart1_REC_Cnt;//拷贝接收的数据个数Usart1_REC_Cnt =0;//清零接收的数据个数}if(Usart3_TimeFlage == 1)//开始累加空闲变量{if(Usart3_IdealTime<400)//防止累加过去,造成循环{Usart3_IdealTime++;//空闲变量累加}}if(Usart3_IdealTime>=100)//调节这个值以适应不停的接收速率{Usart3_TimeFlage = 0;//停止空闲变量累加Usart3_IdealTime = 0;//清零空闲累加变量Usart3_AT_flage = 1; //接收标志位置一Usart3_Current_Cnt = Usart3_REC_Cnt;//拷贝接收的数据个数Usart3_REC_Cnt =0;//清零接收的数据个数}}
}

那么主循环里---具体的处理函数,改为自己的就行

源码,,这个是用的板子的空闲中断,,,,板子的其余文件删掉便可,,,,

链接:http://pan.baidu.com/s/1c228q6c 密码:pl3k

关于STM32空闲中断相关推荐

  1. 关于STM32空闲中断极限时间

    今天空了专门做了关于STM32空闲中断极限时间的实验,结果如下: 115200,8,N,1, 1个位理论用时:1/115200=8.68us,实测发送一帧数据的字节间延时超过大约173us时,则出现空 ...

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

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

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

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

  4. STM32 利用空闲中断接收数据

    STM32 利用串口空闲中断接收不定长数据 利用cubeMX打开DMA串口接收中断 利用CubeMX打开串口中断 HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HA ...

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

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

  6. stm32的rxne和idle中断_STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA

    历程详解 详解包括: 中断原理讲解 例程流程详解 库函数分析详解 对应寄存器介绍 对应函数介绍 对应注释详解 本篇文章提供两种方法: 一种是 :IDLE 接收空闲中断+DMA 一种是: IDLE 接收 ...

  7. stm32的串口DMA空闲中断接收不等长数据,stm32F1的usart1-DMA-IDLE收发

    stm32的DMA收发原理,和stm32F4 + USART2 +DMA +IDLE使用,见另一篇:https://blog.csdn.net/Mark_md/article/details/1072 ...

  8. stm32的串口DMA空闲中断接收不等长数据,stm32F4的usart2-DMA-IDLE收发

    1. 串口为什么要使用DMA?好处? 提高系统实时性:stm32单片机的串口没有FIFO,使用字节中断的方式去接收,会频繁进入中断,影响系统实时性.好在stm32的串口可以级联DMA使用,在大数据量连 ...

  9. STM32应用(七)JY901九轴姿态模块(串口DMA空闲中断和I2C通信)

    文章目录 0.相关基础知识介绍 0.1六轴.九轴传感器有什么区别? 1.JY901模块简介 1.1 产品概述 1.2 性能参数 1.3 实物图和接线 2.软件和使用说明书 3.串口通信JY901 3. ...

最新文章

  1. iscsi target 配置(服务端安装)--一
  2. Java程序员的日常—— 《编程思想》关于类的使用常识
  3. Git 分布式版本控制系统
  4. Linux 操作系统原理 — 文件系统 —文件
  5. Protoc Buffer 优化传输大小的一个细节
  6. 《移动项目实践》实验报告——Android组合控件
  7. Java数据类型(基本数据类型)学习
  8. 判断深度学习模型的稳定性_问题引领构建数学模型,讲练结合促进深度学习
  9. 两校合并!新部属大学,来了!
  10. Linux内核社区迁移到github?
  11. Jpa的@Id和@GeneratedValue的使用
  12. 复杂性思维第二版 二、图
  13. 《SQL高级应用和数据仓库基础(MySQL版)》作业 ·006
  14. 玩一下就停不下来的h5休闲小游戏
  15. java 规范 阿里巴巴_阿里巴巴 Java 代码规范
  16. Pytorch ——基础指北_零 [神经元和激活函数介绍]
  17. Win 10 深度隐藏文件夹命令
  18. 高速公路车路协同创新示范情况全扫描(2021版)
  19. 初级会计最后一个月稳过秘籍
  20. Python练习:炉石传说荣誉室返尘最优策略

热门文章

  1. ps人像美白磨皮教程,ps如何修人像美白磨
  2. 【转载】C/C++ 笔试面试(1)—— sizeof
  3. 第3课 弹性之城--故事卡--跟阿西莫夫故事接龙
  4. 如何将pdf在线翻译成英文?
  5. 原来小米手机这么好用,这4大功能,各个都是黑科技,厉害了
  6. java计算机毕业设计智友少儿编程学习平台源码+mysql数据库+系统+部署+lw文档
  7. 腾讯云-即时通讯 IM
  8. CVX约束中需要使用一些中间变量该怎么办
  9. 关于godot第三方功能增强版
  10. flash 和 eeprom 区别和关系、nor flash和nand flash区别