独闷闷网

 找回密码
 立即注册
搜索
查看: 3413|回复: 0
打印 上一主题 下一主题
收起左侧

[分享] STM32F103串口简单处理

[复制链接]
跳转到指定楼层
楼主
发表于 2014-4-16 14:50:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
用过串口的人,是不是觉得用串口时,都有种不是很爽的感觉,因为串口接受数据时,时间是不确定的,有可能随时都会发送过来,这样就必须要用到中断来读取数据,但是读取过来的数据长度也经常并不是确定的,使用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的开启定时器函数是不能在中断函数里面调用的。(具体是什么原因,这里就不讲解了,有兴趣的同学可以去看源代码哦。呵呵)

祝大家使用愉快哈。




乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-11-29 18:41 , Processed in 0.181834 second(s), 18 queries .

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