找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2240|回复: 1
打印 上一主题 下一主题
收起左侧

STM32的RXNE+IDLE接收不定长的数据包源程序

[复制链接]
跳转到指定楼层
楼主
ID:320800 发表于 2018-5-2 21:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近跟老师一起准备省电子设计竞赛了,老师要求先准备好基础的调试环境,当然选择usart的调试接收方法啦,由于没确定这个项目后期会加进来什么功能,不好确定每个包的大小,于是先写好串口的不定长接收包,想到的方式自然是IDLE+RXNE的查询


1->
     在IDLE里头通过systick检测接收空闲的时间,如果空闲时间>10ms就给标记,停止IDLE中断而去处理这个数据包
//USART1 IRQ handler
  1. void USART1_IRQHandler(void)
  2. {
  3.     #if defined (USART_RECIEVE_BY_DMA)
  4.     //handle by DMA + IDLE inquiry
  5.     uint16_t dmaCounter = DMA_GetCurrDataCounter(DMA1_Channel5);
  6.     if ( USART_GetITStatus( USART1 , USART_IT_IDLE ) != RESET ) {

  7.         printf("DMA counter:%d\r\n",dmaCounter);
  8.         //has dealt rx buffer
  9. //        if (dmaCounter != USART_BUFF_SIZE) {
  10.             usartRx.isDeal = false;
  11.             DMA_Cmd(DMA1_Channel5,DISABLE);
  12.             DMA_ClearFlag(DMA1_FLAG_GL3);
  13.             usartRx.buffHead = USART_BUFF_SIZE - dmaCounter;
  14.             DMA_SetCurrDataCounter( DMA1_Channel5 , USART_BUFF_SIZE );   
  15.             //reset the counter register
  16. //        }
  17.         USART_ClearITPendingBit(USART1,USART_IT_IDLE);
  18.         
  19.         USART_ITConfig(USART1,USART_IT_IDLE,DISABLE);   
  20.         //close usart IDLE interrupt
  21.     }
  22.     #else
  23.     //IRQ handle by SYSTICK + IDLE inquiry
  24.     static uint32_t thisRcvTime = 0;
  25.    
  26.     if ( USART_GetITStatus( USART1 , USART_IT_RXNE ) != RESET ) {        
  27.         usartRx.endTime = thisRcvTime;
  28.         thisRcvTime = millis();
  29.         //update lastTime recieved a byte
  30.         usartRx.buff[usartRx.buffHead] = USART1->DR;
  31.         
  32.         //interval > 10ms
  33.         if(thisRcvTime - usartRx.endTime > 10){
  34.             usartRx.frameHead = usartRx.buffHead;
  35.         }else{
  36. //            usartRx.isDeal = true;
  37.             usartRx.frameEnd = usartRx.buffHead;
  38.             //if interval < 10ms ,stream belong to same frame
  39.             USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
  40.             //start idle time detect
  41.         }
  42.         usartRx.buffHead = (usartRx.buffHead + 1)%USART_BUFF_SIZE;
  43.         
  44.         USART_ClearITPendingBit(USART1,USART_IT_RXNE);
  45.     }
  46.     //detect IDLE time
  47.     if ( USART_GetITStatus( USART1 , USART_IT_IDLE ) != RESET ) {
  48.         if(millis() - thisRcvTime > 10 ){
  49.             USART_ITConfig(USART1,USART_IT_IDLE,DISABLE);
  50.             //close idle interrupt for save CPU
  51.             usartRx.isDeal = false;
  52.         }
  53.         USART_ClearITPendingBit(USART1,USART_IT_IDLE);
  54.     }
  55.     #endif
  56. }
复制代码
2->
      然后再处理函数里头实现一个简单的回显
  1. #if defined(USART_RECIEVE_BY_SYSTICK)
  2. //USART1 recieve frame by systick + RXNE
  3. void usart_recieve_systick_handler(void)
  4. {
  5.         uint16_t i;
  6.         if(usartRx.isDeal == false){
  7.                 USART_ITConfig(USART1,USART_IT_IDLE|USART_IT_RXNE,DISABLE);
  8.                 if(usartRx.frameHead < usartRx.frameEnd){
  9. //                        printf("%d < %d\r\n",usartRx.frameHead,usartRx.frameEnd);
  10.                         for(i=usartRx.frameHead; i<=usartRx.frameEnd; i++){
  11.                                 while((USART1->SR & 0X40)==0);
  12.                                 USART1->DR = usartRx.buff[i];
  13.                         }
  14.                 }else{
  15. //                        printf("%d > %d\r\n",usartRx.frameHead,usartRx.frameEnd);
  16.                         for(i=usartRx.frameHead; i<USART_BUFF_SIZE; i++){
  17.                                 while((USART1->SR & 0X40)==0);
  18.                                 USART1->DR = usartRx.buff[i];
  19.                         }
  20.                         for(i=0; i<usartRx.frameEnd; i++){
  21.                                 while((USART1->SR & 0X40)==0);
  22.                                 USART1->DR = usartRx.buff[i];
  23.                         }
  24.                 }
  25.                 USART_ITConfig(USART1,USART_IT_IDLE|USART_IT_RXNE,ENABLE);
  26.                 usartRx.isDeal = true;
  27.         }
  28. }
  29. #endif
复制代码

全部资料51hei下载地址:
ST.rar (264.57 KB, 下载次数: 11)


评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:320800 发表于 2018-5-2 21:44 | 只看该作者
我这里还没用DMA+IDLE查询来写数据包的接收,这段代码能实现的基础是知道发送端发送数据的最小间隔大于10ms

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表