1. 程式人生 > >GEC210(S5PV210)裸機驅動之串列埠及串列埠中斷

GEC210(S5PV210)裸機驅動之串列埠及串列埠中斷

主機平臺:Linux CentOS 6.5

arm平臺:粵嵌GEC210開發板(S5PV210)

這次寫一下串列埠的驅動,功能是在linux終端中鍵入並向arm傳送一個字元,arm返回這個字元將其在終端上顯示。

其中,串列埠採用串列埠0,非FIFO模式,波特率115200,8位資料為,無較檢位,接收用中斷方式,傳送用查詢方式。

既然用到中斷,那還是按就之前寫中斷的步驟進行:

8.編寫外設對應的中斷服務程式

8.1.根據標誌為判斷髮生了什麼中斷。(當多箇中斷共享一箇中斷號時通常需要做此判斷)

8.2.根據發生的中斷執行相應的任務

8.3.清除所發生中斷的中斷標誌位

8.4.清除全部VICxADDR(置0)

8.5.重新使能全域性IRQ中斷(進入中斷後,全域性IRQ中斷會被關閉)

9.設定外設暫存器初始化外設(包括清除中斷標誌位,使能中斷等操作)

9.1.關閉外設暫存器的中斷使能

9.2.清除外設中斷標誌位

9.3.初始化設定與外設相關的其它暫存器。例如I/O的功能選擇(這個容易忘記),設定輸入時鐘頻率等等。

9.4開啟外設對應中斷

10.根據外設查詢中斷源表獲得其中斷號

11.根據中斷號設定對應的中斷服務程式入口地址暫存器(VICxVECTADDRx)

12.根據中斷號使能對應中斷

下面就是針對串列埠將每個步驟具體化:

8.編寫外設對應的中斷服務程式

8.1.判斷該次中斷是否串列埠的傳送中斷、接收中斷、還是錯誤中斷

8.2.執行對應任務,此處是隻當為接收中斷時,通過查詢方式將獲得的資料傳送出去

8.3.清除對應中斷標誌位(UINTSP0和UINTP0)

8.4.清除全部VICxADDR(置0)

8.5.重新使能全域性IRQ中斷(進入中斷後,全域性IRQ中斷會被關閉)

9.設定外設暫存器初始化外設(包括清除中斷標誌位,使能中斷等操作)

9.1.關閉串列埠0中斷使能(UINTM0[3:0])

9.2.清除串列埠0中斷所有標誌位 (UINTSP0[3:0]和UINTP0[3:0])

9.3

(1)將串列埠0對應的IO引腳功能設定為UART_0_RXDGPA0CON[3:0] 和 UART_0_TXD(GPA0CON[7:4])

(2)設定波特率。波特率由PCLK時鐘、UCON[10]、UBRDIV、UDIVSLOT暫存器確定


公式:

DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16
DIV_VAL = (PCLK / (bps x 16)) −1
or
DIV_VAL = (SCLK_UART / (bps x 16)) −1
此處,時鐘源選擇PCLK(UCON[10]=0),為66M,且UDIVSLOTn=0,因此由第1、2條公式得:

UBRDIV0 = (66M/(115200*16))-1 = 35

(3)設定幀格式,包括資料位位數、停止位位數、較檢方式(ULCON0)

(4)配置UCON暫存器,裡面有很多設定,我講一些個人認為比較重要的,其它沒看懂的話就保持預設值吧

[10]:波特率時鐘源選擇位

[9:8]:Tx/Rx Interrupt Type:手冊上寫這兩位必須置1

[5]:Loop-back Mode ,即迴環測試模式,可以自發自收

[3:2]:Transmit Mode:什麼情況下允許寫串列埠傳送暫存器 00:不可寫;01:可通過中斷或查詢方式寫入;10:在DMA模式下可寫

[1:0]:Receive Mode:什麼情況下允許讀串列埠接收暫存器 00:不可寫;01:可通過中斷或查詢方式寫入;10:在DMA模式下可寫

9.4.使能串列埠中斷,這裡只使能接收中斷(UINTM0[0])

10.根據外設查詢中斷源表獲得其中斷號,可知中斷號為42

11.根據中斷號設定對應的中斷服務程式入口地址暫存器(VIC3VECTADDR10)

12.根據中斷號使能對應中斷(VIC3INTENABLE[10])

跟著再講下如何傳送和接收,這裡比較簡單

傳送:先判斷串列埠是否空閒,然後向傳送緩衝暫存器寫入資料

接收:在中斷中直接讀接收緩衝暫存器就可以了

具體實現看下面程式碼:

void uart0_int_func()
{
    unsigned long temp;

    if(UTRSTAT0&0x1)   //判斷是否為接收中斷
    {
        temp=URXH0;                         //讀取接收暫存器
        while(!(UTRSTAT0&0x2));    //等待串列埠空閒
        UTXH0=temp;               <span style="font-size:14px;">//</span>傳送接收到的內容
        
        UINTSP0|=0xf;                //清除中斷標誌位
        UINTP0|=0xf;                 //清除中斷標誌位
        clear_vicaddress();          <span style="font-size:14px;">/</span>/清除全部VICADDR暫存器
    }
    enable_global_IRQ();             //使能全域性IRQ中斷
        
}

void uart0_init()
{
    ULCON0|=0x3;                  //設定幀格式
    UCON0=0x305;                //時鐘源、讀寫傳送接收暫存器模式
    UBRDIV0=35;                   //設定波特率
    UINTM0=0xf;                    //遮蔽所有串列埠中斷

    GPA0CON=0x22;         //設定引腳功能為串列埠收發
    UINTSP0|=0xf;         //清除中斷標誌
    UINTP0|=0xf;          //清除中斷標誌
    
    
    
    set_int_vectaddr(42,uart0_int_func);  //設定42號中斷服務程式入口地址
    interrupt_enable(42);                            //使能中斷系統42號中斷
    UINTM0=0xe;                                        //使能串列埠接收中斷

    
}


好了,這就是一個簡單的串列埠程式,串列埠還有很多種模式的例如FIFO、Infrared、DMA等模式,這些就要以後慢慢去深入學習了。