1. 程式人生 > >UART0串列埠程式設計系列 串列埠(UART0)之UC/OS(一)

UART0串列埠程式設計系列 串列埠(UART0)之UC/OS(一)

一.在UC/OS中設計串列埠程式所要考慮的問題

1.     串列埠通訊資料以幀為單位進行處理,如果需要接收大量資料,則幀緩衝區規模必然很大;如果需要傳送大量資料,則可將原始資料快看作緩衝區,不需要另外再建立幀緩衝區。

2.     幀緩衝區是全域性資料結構,通常為共享資源,需要考慮互斥訪問問題(如在任務中關中斷)。但是此時系統的效率就會下降。我們可以通過合理設計通訊任務,將對幀緩衝區進行讀/寫操作的雙方封裝到一個任務裡,是幀緩衝區稱為這個任務的私有資料結構,不再是共享資源, 次時就不需要互斥訊號量了。

3.     在UC/OS作業系統中串列埠傳送和串列埠接收函式都被設計成了任務。

Tiger-john說明:

在UC/OS上編寫串列埠程式設計時,主要是考慮以上問題。其它的方面就是UART0的配置以及如何編寫中斷程式這些方面在前面已經提過,再此不再涉及。

如果你還不是很明白的話請看我《UART0串列埠程式設計系列》文章的前半部分。


二.UC/OS串列埠程式設計

通過一個程式來分析UC/OS串列埠程式設計設計和實現:

程式實現的目標:

通過按鍵來控制串列埠傳送任務80位元組的幀,每次傳送8位元組,分25次傳送完。

1.在UC/OS串列埠程式設計中由那幾個任務組成

1>啟動任務

2>按鍵任務(此任務可以根據不同的程式設計內容來改變)

3>傳送任務

4>串列埠傳送中斷

2.各個任務之間的關係

3.啟動任務流程:

l  定義各種通訊工具(例如:訊號量)

l  系統硬體初始化

l  初始化UART0

l  建立各個任務

l  建立各種通訊工具

l  刪除自己

圖3啟動任務流程圖


程式:

/**********************************************************

* 名稱:                    UART0_Init

* 功能:                    UART0初始化 通訊波特率115200,8位資料位,1位停止位,無奇偶校驗,使能TxFIFO,和THRE中斷

* 入口引數:            bps        串列埠波特率

* 出口引數:            無

**********************************************************/

void      UART0_Init(uint32 bps)

{

    uint16  Fdiv;

    PINSEL0 = (PINSEL0 & ~(0xf) | 0x05) ;      //設定UART0的引腳

    U0LCR = 0x83;            

    Fdiv = (Fpclk>>4)/bps;

    U0DLM = Fdiv>>8;

    U0DLL = Fdiv%256;

    U0LCR = 0x03;  

    U0FCR = 0x05;                             // 使能TxFIFO

    U0IER = 0x02;                            //使能THRE中斷

}

/**********************************************************

* 作者:tiger-john

* 時間:2011年1月21

* 名稱:Task0 啟動任務

* 功能:初始化硬體,建立其他任務,

* 入口引數:pdata

**********************************************************/

void Task0     (void *pdata)

{

pdata = pdata;              

//硬體初始化

TargetInit ();

//初始化串列埠

UART0_Init(115200);

//建立按鍵訊號量                                              

Sem_ButtonFlag =  OSSemCreate(0);  

//建立傳送訊號量                               

Sem_SendFlg =  OSSemCreate(0);

//建立按鍵任務                                    

OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],10);     

OSTaskCreate(Task2,(void *)0, &TaskStk2[1000 - 1],6);               //建立傳送任務

OSTaskDel(OS_PRIO_SELF);                                            //刪除自己

}

4.按鍵任務流程:

l  等待開始訊號量

l  製造模擬資料

l  按鍵按下發送訊號量,否則延遲等待

程式:

/**********************************************************

**                            Task1(按鍵任務)

**********************************************************/

void Task1     (void *pdata)

{

uint8 i;

uint8 err;

pdata = pdata;

while(1)

        {

               OSSemPend(Sem_StartFlag,0,&err); //等帶開始訊號量

               for(i = 0;i < 80;i++)

                      {

                             send_buf[i] = i ;             //製造模擬資料。

                      }     

            while((IO0PIN & KEY ) != 0);     //等帶按鍵

            OSSemPost(Sem_ButtonFlag);   //傳送按鍵訊號量

        }

}

5.傳送任務流程:

l  等待按鍵訊號量

l  開啟串列埠中斷

l  傳送10次

l  等待發送訊號量

l  傳送8位元組

l  關傳送串列埠中斷

l  傳送開始訊號量

程式:

/************************************************************                            Task2(傳送任務)

**********************************************************/

void Task2     (void *pdata)

{

uint8 i,j,err;

pdata = pdata;


while(1)

{

        OSSemPend(Sem_ButtonFlag,0,&err);  //等待按鍵訊號量

        U0IER = U0IER | 0x02;               //開啟串列埠傳送中斷

        for(i = 0;i < 10;i++)                     //傳送10次

               {

                    for(j = 0;j < 8;j++)                //每次8位元組

                      {

                             U0THR = send_buf[i*8+j];

                      }     

               OSSemPend(Sem_SendFlag,0,&err); //等待發送訊號量

         }

               U0IER = U0IER & ~0x02;              //關掉串列埠中斷

               OSSemPost(Sem_StartFlag);           //傳送開始訊號量

}            

}

6.串列埠傳送中斷流程:

l  關中斷

l  清除中斷控制標誌位

l  清除串列埠中斷標誌位

l  開中斷

l  傳送傳送訊號量

/**********************************************************

* 名    稱:            UART0_Exception

* 功    能:            串列埠傳送中斷

* 入口引數:            無

* 出口引數:            data              傳送的資料

**********************************************************/

void  UART0_Exception(void)

{


uint32 data;

OS_ENTER_CRITICAL();             //關中斷

VICVectAddr = 0;                  //清除中斷

data = U0IIR;                            //清除中斷表示暫存器標誌

OS_EXIT_CRITICAL();               //開中斷

OSSemPost(Sem_SendFlag);        //發出傳送訊號量

 }
7.總的程式如下:


view plaincopy to clipboardprint?
/****************************************Copyright (c)**************************************************  
**                                       西安郵電學院  
**                                      graduate school  
**                                       XNMS實驗室  
**                                      Author:冀博  
**                                      Time:2011年1月21日  
**                                 http://blog.csdn.net/tigerjb  
**  
**--------------File Info-------------------------------------------------------------------------------  
** File name:           UART0_while  
** Last modified Date:  2011-01-20  
** Last Version:        1.0  
** Descriptions:        當按鍵按下後,串列埠傳送中斷給上位機發送80位元組資料  
**-----------------------------------------------------------------------------------------------------  
 
 
/******************************************************************************  
** Modified by:         TIGER0-JOHN  
** Modified date:       2011-1-21  
** Version:             1.1    
** Descriptions:        測試成功  
****************************************************************************/ 
#include "config.h"  
#include "stdlib.h"  
 
#define KEY             1<<20        //設定為觸發按鍵  
#define TaskStkLengh    64          //Define the Task0(啟動任務) 堆疊長度  
#define TaskStkLengh    64          //Define the Task1(按鍵任務)  堆疊長度   
#define TaskStkLengh    64          //Define the Task2((傳送任務) 堆疊長度   
  
  
OS_STK  TaskStk0[TaskStkLengh];     //Define the Task0 stack  定義啟動任務堆疊    
OS_STK  TaskStk1[TaskStkLengh];     //Define the Task1 stack  定義按鍵任務堆疊   
OS_STK  TaskStk2[TaskStkLengh];     //Define the Task2 stack  定義傳送任務堆疊   
  
  
void    Task0(void *pdata);         //Task0 啟動任務   
void    Task1(void *pdata);         //Task1 按鍵任務   
void    Task2(void *pdata);         //Task2 傳送任務   
  
uint8   send_buf[80];   
OS_EVENT        *Sem_ButtonFlag;    //定義按鍵訊號量   
OS_EVENT        *Sem_SendFlag;      //定義傳送訊號量   
OS_EVENT        *Sem_StartFlag;      //定義開始訊號量   
  
  
/****************************************************************************  
* 名稱:           UART0_Init  
* 功能:           UART0初始化 通訊波特率115200,8位資料位,1位停止位,無奇偶校驗  
*                   使能TxFIFO,和THRE中斷  
* 入口引數:     bps     串列埠波特率  
* 出口引數:     無  
****************************************************************************/  
void    UART0_Init(uint32 bps)   
{   
    
    uint16  Fdiv;   
    PINSEL0 = (PINSEL0 & ~(0xf) | 0x05) ;       //設定UART0的引腳   
    U0LCR = 0x83;                
    Fdiv = (Fpclk>>4)/bps;   
    U0DLM = Fdiv>>8;   
    U0DLL = Fdiv%256;   
    U0LCR = 0x03;      
    U0FCR = 0x05;                               // 使能TxFIFO   
    U0IER = 0x02;                               // 使能THRE中斷   
      
}   
/****************************************************************************  
* 名    稱:       UART0_Exception  
* 功    能:       串列埠傳送中斷  
* 入口引數:     無  
* 出口引數:     data        傳送的資料  
****************************************************************************/  
void  UART0_Exception(void)   
{   
       
    uint32 data;   
    OS_ENTER_CRITICAL();                            //關中斷   
    VICVectAddr = 0;                                //清除中斷   
    data = U0IIR;                                   //清除中斷表示暫存器標誌   
    OS_EXIT_CRITICAL();                             //開中斷   
    OSSemPost(Sem_SendFlag);                        //發出傳送訊號量   
 }   
/*********************************************************************************************************  
**                              main()函式  
********************************************************************************************************/  
  
int main (void)   
{   
    OSInit ();                                                          //初始化作業系統                                                  
    OSTaskCreate (Task0,(void *)0, &TaskStk0[TaskStkLengh - 1], 2);     //建立啟動任務   
    OSStart ();                                                         //啟動作業系統,開始對任務進行排程管理   
    return 0;                                                              
}   
/*********************************************************************************************************  
**                            Task0(啟動任務)  
********************************************************************************************************/  
  
void Task0  (void *pdata)   
{   
    pdata = pdata;                  
    TargetInit ();                                                     //硬體初始化                                                   
    UART0_Init(115200);                                                //初始化串列埠   
    Sem_ButtonFlag =  OSSemCreate(0);                                  //建立按鍵訊號量   
    Sem_SendFlag   =  OSSemCreate(0);                                     //建立傳送訊號量   
    Sem_StartFlag  =  OSSemCreate(1);    
    OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],5);      //建立按鍵任務   
    OSTaskCreate(Task2,(void *)0, &TaskStk2[TaskStkLengh - 1],4);               //建立傳送任務   
    OSTaskDel(OS_PRIO_SELF);                                           //刪除自己   
           
}   
/*********************************************************************************************************  
**                            Task1(按鍵任務)  
********************************************************************************************************/  
void Task1  (void *pdata)   
{   
    uint8 i;   
    uint8 err;   
    pdata = pdata;    
    while(1)   
        {   
            OSSemPend(Sem_StartFlag,0,&err);           //等帶開始訊號量   
            for(i = 0;i < 80;i++)   
                {   
                    send_buf[i] = i ;           //製造模擬資料。   
                }      
            while((IO0PIN & KEY ) != 0);        //等帶按鍵   
            OSSemPost(Sem_ButtonFlag);          //傳送按鍵訊號量   
               
        }   
}   
/*********************************************************************************************************  
**                            Task2(傳送任務)  
********************************************************************************************************/  
void Task2  (void *pdata)   
{   
    uint8 i,j,err;   
    pdata = pdata;   
       
    while(1)   
    {   
        OSSemPend(Sem_ButtonFlag,0,&err);       //等待按鍵訊號量   
        U0IER = U0IER | 0x02;                   //開啟串列埠傳送中斷   
        for(i = 0;i < 10;i++)                    //傳送10次   
            {   
                for(j = 0;j < 8;j++)             //每次8位元組   
                    {   
                        U0THR = send_buf[i*8+j];   
                    }      
                OSSemPend(Sem_SendFlag,0,&err);    //等待發送訊號量   
                       
            }   
            U0IER = U0IER & ~0x02;              //關掉串列埠中斷   
            OSSemPost(Sem_StartFlag);           //傳送開始訊號量   
    }          
            
}   
     
/*********************************************************************************************************  
**                            End Of File  
********************************************************************************************************/