Chinaunix首页 | 论坛 | 博客
  • 博客访问: 24838
  • 博文数量: 7
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-16 10:01
文章分类
文章存档

2016年(7)

我的朋友

分类: 嵌入式

2016-08-31 23:23:53

以前串口中断接收串口数据都是利用了裸机程序,今天把ucos系统在STM32跑了起来,当然也想利用串口中断接收一下串口数据,下面看看具体步骤。
第一步:在OS系统的start任务中,调用USART1的初始化程序。串口1的初始化程序和裸机同样这里不多说了,但是在最后使能串口中断的时候要注意了,需要添加2条语句
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  BSP_IntVectSet(BSP_INT_ID_USART1, BSP_IntHandlerUSART1); //设置串口1的中断向量,必须要有的
  BSP_IntEn(BSP_INT_ID_USART1);

/*在uC/OS II下使用ST的库函数直接操作STM32的串口是可以的,只是楼主的程序少了一项设置!所以导致无法开串口中断。
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE); 
这个两个函数只是使能了串口1功能,并设置了STM32外设寄存器中的串口接收中断,还必须设置Cortex-M3内核的NVIC寄存器才能真正打开串口中断。
增加下面的设置:
NVIC_InitTypeDefNVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); 
uC/OS II提供的BSP_IntEn(BSP_INT_ID_USART1)的作用和上面的这段程序作用完全一样。所以如果使用BSP_IntEn()打开串口中断的话就可以省去上面那段程序了。
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)和BSP_IntEn(BSP_INT_ID_USART1)要一起使用才能真正打开串口中断。*/


第二步:编写串口1中断函数
static void BSP_IntHandlerUSART1 (void)
{   
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)    //进中断的标志
      {                                                                                                    
       USART_ClearITPendingBit(USART1,USART_IT_RXNE); 
       USART_SendData(USART1, USART_ReceiveData(USART1));        //接收到的数据重新发送到串口                             
 //    OSMboxPost(MSGBOX,&rec_len);
      }  
}

这就是中断服务函数,和裸机程序一样,如果需要和其他任务通信,利用绿色的那句邮箱就可以了,这里我没有,只是将收到数据返回,因为这里暂时不说任务间通信问题。
到这里在ucos系统上使用串口中断程序就完成了,但是前提是你的ucos系统运行正常。也许很迷糊的,这么简单。下面我具体说一下ucos中中断进入流程,这样就会明白了啊。

首先初始化串口1的寄存器,就是设置IO口,波特率和其他串口需要的东西。
 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  BSP_IntVectSet(BSP_INT_ID_USART1, BSP_IntHandlerUSART1); //设置串口1的中断向量,必须要有的
  BSP_IntEn(BSP_INT_ID_USART1);
这三句语句在初始化函数中不可以少的,上面说的很清楚了, BSP_IntVectSet(BSP_INT_ID_USART1, BSP_IntHandlerUSART1); 就是讲串口1的中断服务函数和串口1的中断号相关联,就是利用指针数组,中断向量表就是一个256大小的数组,BSP_INT_ID_USART1是数组的标号,也即是0-255;IntVect[BSP_INT_ID_USART1]=BSP_IntHandlerUSART1;BSP_IntHandlerUSART1就是上面中断服务函数的函数名称,也就是中断服务函数指针,也是中断服务函数的入口地址。如果还不明白,你看看C语言函数那个章节吧。

到目前为止,串口初始化了,串口中断使能了,串口中断向量表配置了,接下来就是等待串口数据了,一旦有数据,ucos系统就会进入中断处理函数,这个时候非常重要,和裸机有点不同。假如这个时候串口收到数据,产生串口接收中断了,在ucos系统,最先进入这个函数
static  void  BSP_IntHandler (CPU_DATA  int_id);从函数看,它才是ucos系统的中断处理函数,
我们看看这个函数程序,到底做了什么;
static  void  BSP_IntHandler (CPU_DATA  int_id)
{
    #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR         cpu_sr;
    #endif
    CPU_FNCT_VOID  isr;
    CPU_CRITICAL_ENTER();                                       /* Tell uC/OS-II that we are starting an ISR            */
    OSIntNesting++;                                                   /* Increment ISR nesting level ,可以用void  OSIntEnter (void)代替*/
    CPU_CRITICAL_EXIT();                                        //ucos系统中进入中断要使用临界区,这个不用多说了。
    if (int_id < BSP_INT_SRC_NBR)                            //判断中断号的合法性,此时的中断号就是BSP_INT_ID_USART1
        {
        isr = BSP_IntVectTbl[int_id];                            //将中断函数服务函数赋值为中断向量表中的一个元素,我们带入看看isr是什么//
        if (isr != (CPU_FNCT_VOID)0)                          //BSP_IntVectTbl[BSP_INT_ID_USART1]=BSP_IntHandlerUSART1;看到了吧,
                                                                            //转了一圈最后中断服务函数isr还是指向了上面,我们自己编写的中断服务函数。

         {
            isr();                                                         //执行中断服务函数,也即是我们自己编的BSP_IntHandlerUSART1函数
        }
    }
    OSIntExit();                                                /* Tell uC/OS-II that we are leaving the ISR            */
}


读清楚 BSP_IntHandler (CPU_DATA  int_id),就会明白,ucos系统的中断是运行的,这里ucos的中断不可以嵌套的,如果需要,必须自己修改。
ucos系统还有很多地方需要学习的。





阅读(2110) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~