180 likes | 329 Views
Timer & KEYPAD. 11/24. 實習基礎. S3C4510B 提供了兩個 32 位元計時器 (timer0 、 timer1) ,固定 以下數方式進行計數 。而其操作的方式可分為兩種,其分別為 間隔 (interval) 模式 與 雙態 (toggle) 模式 ,這兩種模式的差別在於輸出波形的不同。. 下數計數器. 波形產生器. Time out. 脈波訊號. System Clock. 計時器模式. 間隔 Interval Mode: 計時器計數結束即會產生一個脈波,
E N D
Timer & KEYPAD 11/24
實習基礎 • S3C4510B 提供了兩個32位元計時器(timer0、timer1),固定以下數方式進行計數。而其操作的方式可分為兩種,其分別為間隔(interval)模式與雙態(toggle)模式,這兩種模式的差別在於輸出波形的不同。 下數計數器 波形產生器 Time out 脈波訊號 System Clock
計時器模式 間隔 Interval Mode:計時器計數結束即會產生一個脈波, 輸出頻率 fTOUT = fMCLK / 計時器資料值 雙態 Toggle Mode:計時器計數結束進行波形轉態動作, 輸出頻率 fTOUT = fMCLK / (計時器資料值 x 2) CPU工作頻率 fMCLK = 50MHz
32位元計時器方塊圖 TDATA 暫存器 給予下數數值 產生中斷訊號 system clock time out TCNT 暫存器 TMOD 計時器 模式設定
計時器模式暫存器 • 計時器模式暫存器(TMOD),使用於控制2個32位元計時器的操作 31 5 4 3 2 1 0 TE0: Timer0 致能控制 0 = disable timer0 1 = enable timer0 TMD0: Timer0 模式選擇 0 = 間隔模式(interval) 1 = 雙態模式(toggle) TCLR0: Timer0 脈波輸出腳位(TOUT0) 初始化 0 = 在toggle模式下,初始化為0 1 = 在toggle模式下,初始化為1 TE1: Timer1 致能控制 0 = disable timer0 1 = enable timer0 TMD1: Timer1 模式選擇 0 = 間隔模式(interval) 1 = 雙態模式(toggle) TCLR1: Timer1 脈波輸出腳位(TOUT0) 初始化 0 = 在toggle模式下,初始化為0 1 = 在toggle模式下,初始化為1
計時器資料暫存器(TDATA0、TDATA1) 指明計時器 count value 計數總量(time-out的時間間隔) 計時器計數暫存器(TCNT0、TCNT1) 存放一般操作期間的timer0和timer1的目前計數值 31 0 31 0
Example • 在間隔 Interval Mode 產生週期 1ms 的 clock 輸出 (time out = 1ms) (1) 產生 1ms 的 clock : fTOUT = 1000 Hz Interval Mode 輸出頻率公式: fTOUT = fMCLK / 計時器資料值 CPU工作頻率 fMCLK = 50MHz 故計時器資料值 = 50000 fTOUT = 50MHz / 50000 = 1000 Hz time out = 1/ (1000 Hz) = 1ms (2) fMCLK = 50MHz => 週期 = 20ns =計時器每 20ns 計數一次 若計時器資料值(count value) = 50000 50000 x 20ns = 1ms 的 clock輸出
相關暫存器位址 • creator_ram.pcm 之系統記憶體映射 Ox3FFFFFF TCNT1: 0x3FF6010TCNT0: 0x3FF600C TDATA1: 0x3FF6008 TDATA0: 0x3FF6004 TMOD: 0x3FF6000 . . . INTMSK: 0x3FF4008 INTPND: 0x3FF4004 INTMOD: 0x3FF4000 Special Register Bank Ox3FF0000 Ox3F0FFFF 64K I/O Ox3F00000 Ox19FFFFF 2MB Flash ROM Ox1800000 Ox1000000 16MB SDRAM Ox0000000
暫存器變數宣告 • timer/4510addr.h /*============================================================ ;Timers control registers ;============================================================*/ #define TMOD ( *(volatile unsigned *) 0x03FF6000) #define TDATA0 ( *(volatile unsigned *) 0x03FF6004) #define TCNT0 ( *(volatile unsigned *) 0x03FF600C) #define TDATA1 ( *(volatile unsigned *) 0x03FF6008) #define TCNT1 ( *(volatile unsigned *) 0x03FF6010)
範例程式(timer) • /************************************************************************* • System Initialize • *************************************************************************/ • void Initial_Creator(void) • { • InitialHandler_ISR(); // 初始化中斷向量表格 • init_TIMER0(); //初始化TIMER0函式 • } • /************************************************************************* • MAIN Program • *************************************************************************/ • int main(void){ • __enable_interrupt(); // 致能系統中斷服務Initial_Creator(); // 此函式做Creator的初始化EnableInterrupt(BIT_GMASK); // 致能中斷服務遮罩 • while (1){ • } • DisableInterrupt(BIT_GMASK); // 禁能中斷服務遮罩 • return(0); • }
Init_timer0()(drive.c) void init_TIMER0(void) { TMOD = 0x00000001; TDATA0 = 50000000; //=50000000*20ns = 1s // install interrupt source and its service function InstallHandler_ISR(TIMER0, Timer_ISR_function); ClearPending(BIT_TIMER0); // 清除中斷Pending EnableInterrupt(BIT_TIMER0); // 致能中斷服務 } 使用Timer0, 間隔模式(interval) Timer 中斷服務副程式
中斷副程式 Timer_ISR_function (drive.c) intLED_light=0; void Timer_ISR_function(void){switch(LED_light) {case0:IO_REG2 = 0xf000;LED_light=1;break;case1:IO_REG2 = 0x0f00;LED_light=0;break;default:break; } ClearPending(BIT_TIMER0);} 左半邊4個LED燈號亮 右半邊4個LED燈號亮
4X4 KEYPAD 藉由程式對SCAN_Ox設定”0”進行掃描,而由SCAN_Ix讀取資料可以判斷該列那一個KEY被按下。
範例程式 while (1) { //執行掃描 for (i=0;i<4;i++){ //掃描第i行keypad IO_REG2 =keyOutvalue[i] ; Delay (ms); //設定buff=掃描結果 buff = (0x0F00 & IO_REG1); //如果結果有掃描到 if(buff != 0x0f00 ) { keypad(i,buff, 1); Delay(2000); } } }
範例程式 void keypad(UI i,UI buff,UI k) { UI j, ms=100; //判別哪一列被按下 for (j=0;j<4;j++){ //如果第i列被按下 if( buff == keyInvalue[j] ){ //如果是第i行掃描到 if( i==0) SHOW7SEG(seg_com[k], j ); if (i==1) SHOW7SEG(seg_com[k], j+4 ); if (i==2) SHOW7SEG(seg_com[k], j+8 ); if (i==3) SHOW7SEG(seg_com[k], j+12); } } }
實習 • 實習一: 修改範例程式(timer),設定 Timer0 的 time-out 時間為 5 秒(S)。 • 實習二: 修改範例程式(timer),使用附錄A的副程式(TEST_ISR)替換掉Timer_ISR_function ,作為 timer0 產生中斷時的中斷服務呼叫。 • 實習三: 修改範例程式(keypad),將按鍵輸出在不同的七階顯示器上面。 (keypad 第1次按下的鍵輸出在COM0) (keypad 第2次按下的鍵輸出在COM1) (keypad 第3次按下的鍵輸出在COM2) (keypad 第4次按下的鍵輸出在COM3) (keypad 第5次按下的鍵輸出在COM0) 一次輸出一個數字即可
附錄A int i; void TEST_ISR(void){switch(i) {case 0: IO_REG0 = 0x0ec0;break;case 1: IO_REG0 = 0x0ef9;break;case 2: IO_REG0 = 0x0ea4;break;case 3: IO_REG0 = 0x0eb0;break;default: i=0; IO_REG0 = 0x0ec0;break; } i++; ClearPending(BIT_TIMER0);}