第一步:在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系統還有很多地方需要學習的。