以前串口中断接收串口数据都是利用了裸机程序,今天把 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
ucos 系统的中断处理函数,
我们看看这个函数程序,到底做了什么;
static
{
int_id);从函数看,它才是
BSP_IntHandler (CPU_DATA
void
void
BSP_IntHandler (CPU_DATA
int_id)
#if (CPU_CFG_CRITICAL_METHOD ==
CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR
#endif
cpu_sr;
CPU_FNCT_VOID
CPU_CRITICAL_ENTER();
isr;
/* Tell uC/OS-II that we are starting an
ISR
*/
OSIntNesting++;
nesting level ,可以用 void
CPU_CRITICAL_EXIT();
OSIntEnter (void)代替*/
//ucos 系统中进入中断要使用临界
/* Increment ISR
区,这个不用多说了。
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();
ISR
}
/* Tell uC/OS-II that we are leaving the
*/
读清楚 BSP_IntHandler (CPU_DATA
int_id),就会明白,ucos 系统的中断
是运行的,这里 ucos 的中断不可以嵌套的,如果需要,必须自己修改。
ucos 系统还有很多地方需要学习的。