天天看點

嵌入式軟體開發技術實驗報告-定時器

  • 實驗目的

(1)掌握嵌入式系統軟體設計方法,培養分析問題、解決問題、應用知識的能力和創新精神,全面提高綜合素質。

(2)熟悉嵌入式Linux開發環境,學會基于UP-CUP6410-II型平台的Linux開發環境的配置和使用,利用arm-linux-gcc交叉編譯程式,使用基于NFS的挂載方式進行GPIO實驗,了解嵌入式開發的基本過程;

(3)了解嵌入式Linux裁剪、移植及驅動的編寫。

  • 實驗内容

(1)基礎實驗——熟悉嵌入式Linux開發環境,嵌入式資料庫應用實驗。

(2)圖形界面應用程式設計——安裝與建立QT桌面運作環境,使用Qt Designer。

(3)核心與根檔案系統實驗(選做)——Linux核心裁剪、編譯、移植,根檔案系統建立。

(4)嵌入式Linux驅動實驗——LED驅動及控制實驗。

  • 實驗原理及實驗内容

1.實驗原理

S3C2440提供具備定時器功能的部件如下,都可以精确的每隔一段時間産生中斷:

(1)Timer0—Timer4共5個定時器, Timer0—Timer3可以通過TOUT0—TOUT3引腳輸出PWM波,Timer4沒有輸出引腳。對于每個定時器,每次開始計數時,硬體将TCNTBn 數值加載到TCNTn ,将TCMPBn 數值加載到TCMPn;之後每個計數時鐘周期TCNTn自減。

(2)其數值減到等于TCMPn時,TOUTn引腳上的電平發生反轉,減至0觸發INT_TIMERn内部中斷。  RTC實時時鐘部件具備毫秒級時間片計時器,産生時間片中斷INT_TICK,可以程式設計設定時間片,每次中斷時間最大為小于等于1秒。

(3)看門狗部件可以作為1個正常定時器,計數減到為0則觸發INT_WDT内部中斷(INT_WDT_AC97的子中斷)并自動加載計數。  另外,LED燈連接配接的引腳為GPB5(nLED1)、GPB6(nLED2)、GPB7(nLED3)、GPB8(nLED4),當引腳輸出低電平時,相應LED發光;輸出低電平時,相應LED滅。

2.實驗内容

S3C2440具有5個16為定時器,每個定時器可以按照中斷模式或DMA模式工作。定時器0、1、2、3具有PWM功能。定時器是一個内部定時器,不具有對外輸出口線。定時器0還具有死區發生器,通常用于大電流裝置。

在單次觸下發模式下,定時器完成一次倒計時并産生中斷請求後,定時器便停止了。如果要啟動下一次計時,需要重新向TCNBn中寫入計時值,并重新啟動定時器開始工作。

void Test_TimerInt(void)

{variable0 = 0;variable1 = 0;variable2 = 0;variable3 = 0;variable4 = 0;

/* Timer0,1,2,3,4 Interrupt service is available */

    rINTMSK = ~(BIT_TIMER4 | BIT_TIMER3 | BIT_TIMER2 | BIT_TIMER1 | BIT_TIMER0);

// Uart_Printf("rINTMSK (After)  = 0x%8x   <= Timer4,3,2,1 Bit[14:10]\n",rINTMSK);

    /* Timer0,1,2,3,4 Interrupt Service Routine Entry Point Determine */

    pISR_TIMER0 = (int)Timer0Done;

    pISR_TIMER1 = (int)Timer1Done;

    pISR_TIMER2 = (int)Timer2Done;

    pISR_TIMER3 = (int)Timer3Done;

    pISR_TIMER4 = (int)Timer4Done;

    Uart_Printf("\n[Timer 0,1,2,3,4 Interrupt Test]\n\n");

    rTCFG0 = rTCFG0 & ~(0xffffff) | 0xff | 0xff<<8; //Dead zone=0,Prescaler1=255(0x0f),Prescaler0=255(0x0f)

    rTCFG1  =rTCFG1 & ~(0xffffff) | 0x001233; //All interrupt,Mux4=1/2,Mux3=1/4,Mux2=1/8,Mux1=1/16,Mux0=1/16

    rTCNTB0 = 30000;         

    rTCNTB1 = 30000;           

    rTCNTB2 = 30000;           

    rTCNTB3 = 30000;        

    rTCNTB4 = 30000;         

    rTCMPB0 = 15000;

    rTCMPB1 = 15000;

    rTCMPB2 = 15000;

    rTCMPB3 = 15000;

    rTCON  = rTCON & ~(0xffffff) | 0x1<<1 | 0x1<<9 | 0x1<<13 | 0x1<<17 | 0x1<<21 ; //Manual update

    rTCON  = rTCON & ~(0xffffff) | 0x1  ; //Timer 0 Start, Auto-reload

    rTCON  = rTCON | 0x1<<8 ; //Timer 1 Start, Auto-reload

    rTCON  = rTCON | 0x1<<12 ; //Timer 2 Start, Auto-reload

    rTCON  = rTCON | 0x1<<16; //Timer 3 Start, Auto-reload

    rTCON  = rTCON | 0x1<<20; //Timer 4 Start, Auto-reload   

    while(1)

{

 if(old_v3!=variable3)

     {//重新啟動定時器3   

     rTCON= rTCON&0xf6ffff;

     rTCON  = rTCON | 0x1<<16 ;

     old_v3=variable3;           

     }

       if(old_v2!=variable2)

     {   //重新啟動定時器2

     rTCON= rTCON&0xff6fff;

     rTCON  = rTCON | 0x1<<12 ;

     old_v2=variable2;           

     }

     if(old_v1!=variable1)

     {//重新啟動定時器1

        rTCON= rTCON&0xfff6ff;

     rTCON  = rTCON | 0x1<<8 ;

     old_v1=variable1;

      }

     if(old_v0!=variable0)

     {//重新啟動定時器0   

     rTCON= rTCON&0xfffff6;

     rTCON  = rTCON | 0x1<<0 ;

     old_v0=variable0;           

     }

     if(old_v4!=variable4)

     {//重新啟動定時器4

        rTCON= rTCON&0x6fffff;

     rTCON  = rTCON | 0x1<<20 ;

     old_v4=variable4;           

     }

     if(variable4 == 8)

     break;

    }

    //Delay(1); //To compensate timer error(<1 tick period)

    rTCON = 0x0; //Stop Timers

    if(variable4==8 && variable3==4 && variable2==2 && variable1==1 && variable0==1)

{Uart_Printf("Timer 0,1,2,3,4 Auto-reload Interrupt Test => OK!\n");}        

    else

    {Uart_Printf("Timer 0,1,2,3,4 Auto-reload Interrupt Test => Fail............\n");}    

    Uart_Printf("Timer0: %d (=1)\nTimer1: %d (=1)\nTimer2: %d (=2)\nTimer3: %d (=4)\nTimer4: %d (=8)\n",

        variable0,variable1,variable2,variable3,variable4);        

/* Timer0,1,2,3,4 Interrupt Service is masked */

    rINTMSK |= (BIT_TIMER4 | BIT_TIMER3 | BIT_TIMER2 | BIT_TIMER1 | BIT_TIMER0);

Uart_Printf("Press any key\n");      

while(!Uart_Getch());       //Key board press check      

}

定義變量old_v0——old_v4,在Timer.c檔案中變量variable0,variable1,variable2,variable3,variable4定義之處添加,如下:

Static volatile int dmaDone,variable0,variable1,variable2,variable3,variable4,old_v4,old_v3,old_v2,old_v1,old_v0;

初始化變量old_v0——old_v4,在void Test_TimerInt(void)函數中,如下:

    variable0 = 0;variable1 = 0;variable2 = 0;variable3 = 0;variable4 = 0; old_v3=0;old_v4=0;old_v2=0;old_v1=0;old_v0=0;

  • 實驗結果展示

在程式沒有改動之前,編譯程式,下載下傳到實驗箱運作,結果如下:

Timer0:1

Timer1:1

Timer2:2

Timer3:4

Timer4:8

編譯程式,下載下傳到實驗箱運作。運作結果為:

Timer0:1

Timer1:1

Timer2:2

Timer3:4

Timer4:8

  • 創新點及存在問題

在實驗過程中,由于考慮問題不夠全面,在修改程式使定時器工作于單次觸發模式并完成本實驗相同的功能。我們隻考慮了定時器控制寄存器中Timer0、Timer1、Timer2、Timer3、Timer4的自動裝載位是否啟動。其中第3位、第11位、15位、19位、22位置0,使其工作于單次觸發模式下。是以我們隻把

rTCON  = rTCON & ~(0xffffff) | 0x1;// | 0x1<<3 ; //Timer 0 Start,

rTCON  = rTCON | 0x1<<8 ;//| 0x1<<11 ; //Timer 1 Start,

rTCON  = rTCON | 0x1<<12;// | 0x1<<15 ; //Timer 2 Start, Auto-reload

rTCON  = rTCON | 0x1<<16 ;//| 0x1<<19 ; //Timer 3 Start, Auto-reload

rTCON  = rTCON | 0x1<<20;// | 0x1<<22 ; //Timer 4 Start, Auto-reload   

結果在運作結果後,并沒有出現預想的結果。重新改正了程式,并得到了相同的結果。因為還需要在單次觸發模式下重新啟動定時器。

 定時長度=計時常數/(pclk/(預分頻值+1))/分割器值)可以計算出T0:T1:T2:T3:T4=8:8:4:2:1,而中斷次數反比于定時長度(相同時間内)Tn0:Tn1:Tn2:Tn3:Tn4=1:1:2:4:8.進而得到了即Timer0——Timer4的中斷次數分别是1、1、2、4、8。

  • 實驗總結

定時器控制寄存器(TCON)可進行定時器自動重載、手動更新、啟動/停止、輸入、輸入反轉及死區使能的設定功能。

嵌入式軟體開發技術實驗報告-定時器