在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系統,最先進入這個函數
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系統還有很多地方需要學習的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章