电子技术论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1903|回复: 0

STM32F103串口简单化处理

[复制链接]

624

主题

627

帖子

416

积分

专栏作家

Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25Rank: 25

积分
416
发表于 2015-4-15 17:18:53 | 显示全部楼层 |阅读模式
STM32F103串口简单化处理
用过串口的人,是不是觉得用串口时,都有种不是很爽的感觉,因为串口接受数据时,时间是不确定的,有可能随时都会发送过来,这样就必须要用到中断来读取数据,但是读取过来的数据长度也经常并不是确定的,使用DMA也不是很合适,那就要在每接受一个数据,进行一次处理,这样中断函数就变大,并且不能做到统一处理。
想想如果有这么一个串口,接受数据时,它自动接收,不用主线程来做任何干预,直到串口接收完整条贞(5ms间隔算一条贞)时,通知主线程此时接受到一条贞,主线程就可以一次性将整条数据贞读取出来,一次处理完整条贞,而不是像上面一样分散处理。(蓝牙、以太网...就是这样做的,它们是因为有很多层协议组成的,但是串口没有)

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

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


线程函数:
  1.          while(1){
  2.                 /* 等待贞的第一个数据 */
  3.                OSSemPend (&sem,0,OS_OPT_PEND_BLOCKING,&ts,&err); /* 等待信号量(无限等待,阻塞方式) */

  4.                 /* 有第一个数据后,就要开始判断整条贞的结尾,既5ms没有数据来*/              
  5.                 while(1){
  6.                      OSSemPend (&__modrecive_sem,5,OS_OPT_PEND_BLOCKING,&ts,&err); /* 5ms 的延时等待 */

  7.                      if(OS_ERR_TIMEOUT == err){  /* 超时,既5ms内还没有信号 */
  8.                          Mb_recive_callback();    /* 调用回调函数,通知主线程数据接收完全 */
  9.                          break;
  10.                      }
  11.                }
  12.          }
复制代码


串口接收中断函数:
  1. recive_buffer[recive_buffer_count++] = USART_ReceiveData(); /* 将接收到的数据存入缓存区 */
  2. OSSemPost (&__modrecive_sem, OS_OPT_POST_1, &err);     /* 发送消息,既通知上面的线程的等待消息 */
复制代码


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

本版积分规则

手机版|电子技术论坛 ( 鄂ICP备09003585号-2 )

GMT+8, 2019-2-20 06:13 , Processed in 0.042291 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 2001-2018 Comsenz Inc.

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