查看: 1143|回复: 0
打印 上一主题 下一主题

STM32F103串口简单化处理

[复制链接]
跳转到指定楼层
沙发
发表于 2015-9-28 00:05:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32F103串口简单化处理
用过串口的人,是不是觉得用串口时,都有种不是很爽的感觉,因为串口接受数据时,时间是不确定的,有可能随时都会发送过来,这样就必须要用到中断来读取数据,但是读取过来的数据长度也经常并不是确定的,使用DMA也不是很合适,那就要在每接受一个数据,进行一次处理,这样中断函数就变大,并且不能做到统一处理。
想想如果有这么一个串口,接受数据时,它自动接收,不用主线程来做任何干预,直到串口接收完整条贞(5ms间隔算一条贞)时,通知主线程此时接受到一条贞,主线程就可以一次性将整条数据贞读取出来,一次处理完整条贞,而不是像上面一样分散处理。(蓝牙、以太网...就是这样做的,它们是因为有很多层协议组成的,但是串口没有)

想想还是分享出来这个思路吧:
1、在跑裸机时代,我是这样处理的:串口接收到一个数据,将数据存入到缓存区,就开启一个定时器,又接到时,定时器重新定时,当这个定时器到了定时时间,也就是进入了中断程序,说明这个消息贞结束了。然后调用回调通知主线程接受完成一贞,主线程再去读串口缓存区。
问题:(1)消耗了硬件定时器
          (2)调用回调函数的地方,就要放在中断函数里面,这样就会出现万一回调函数里面出现了很占时间的程序,就会导致中断时间占用过长(这个学过单片机的人都知道,这是不理想的)
2、现在使用ucos操作系统,可以开辟一个小线程,来单独处理串口接受事件:
     先讲解一个小知识:等待信号量,可以设置为无限等待(只要不设置这个信号量,就会一直等待),也可以设置为超时等待(有个超时时间,如果超过了这个时间,还没有信号量,会跳过,如果超时时间内有信号量,也会跳过)。

串口初始化函数:
  • USART_Init();   /* 串口各种初始化,配置接收中断模式 */
  • ......
  • OSSemCreate  /* 创建信号量 */
  • OSTaskCreate /* 创建小线程 */

复制代码


线程函数:
  •          while(1){
  •                 /* 等待贞的第一个数据 */
  •                OSSemPend (&sem,0,OS_OPT_PEND_BLOCKING,&ts,&err); /* 等待信号量(无限等待,阻塞方式) */
  •                 /* 有第一个数据后,就要开始判断整条贞的结尾,既5ms没有数据来*/
  •                 while(1){
  •                      OSSemPend (&__modrecive_sem,5,OS_OPT_PEND_BLOCKING,&ts,&err); /* 5ms 的延时等待 */
  •                      if(OS_ERR_TIMEOUT == err){  /* 超时,既5ms内还没有信号 */
  •                          Mb_recive_callback();    /* 调用回调函数,通知主线程数据接收完全 */
  •                          break;
  •                      }
  •                }
  •          }

串口接收中断函数:

  • recive_buffer[recive_buffer_count++] = USART_ReceiveData(); /* 将接收到的数据存入缓存区 */
  • OSSemPost (&__modrecive_sem, OS_OPT_POST_1, &err);     /* 发送消息,既通知上面的线程的等待消息 */



至此,就如果我们将这个思路封装成一个库,也就是只要调用串口初始化函数,并且传入回调函数,我们就可以相当方便的使用串口了,不需要查询,不需要判断,不需要一直处理,只要在回调函数里面,将数据一次性提取出来,统一处理就OK了,这样是不是很爽呢?呵呵
可能有的人会这样想,就是ucos里面还有软件定时器,可以接收到一个数据,马上开启定时器,或者重新启动定时器,这样当定时时间到,就会调用回调函数通知主线程。这种想法是对的,但是开启定时器这个功能是要在中断函数里面开启,但是,ucos的开启定时器函数是不能在中断函数里面调用的。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

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