在ucos系统上使用USART1串口中断函数处理串口数据

以前串口中断接收串口数据都是利用了裸机程序,今天把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系统,最先进入这个函数
staticvoidBSP_IntHandler (CPU_DATAint_id) ;从函数看,它才是ucos系统的中断处理函数,
我们看看这个函数程序,到底做了什么;
staticvoidBSP_IntHandler (CPU_DATAint_id)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SRcpu_sr;
#endif
CPU_FNCT_VOIDisr;
CPU_CRITICAL_ENTER(); /* Tell uC/OS-II that we are starting an ISR*/
OSIntNesting++; /* Increment ISR nesting level ,可以用voidOSIntEnter (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_DATAint_id),就会明白,ucos系统的中断是运行的,这里ucos的中断不可以嵌套的,如果需要,必须自己修改。
ucos系统还有很多地方需要学习的。

    推荐阅读