1.定時器結構分析
- 1.每來一個CLK,TCNTn減1
- 2.當
時,(可以把對應的PWM引腳翻轉)TCNTn == TCMPn
-
與TCNTn
的值來自寄存器TCMPn
與TCNPBn
TCMTBn
-
- 3.TCNTn繼續減1,當
時,可以産生中斷(PWM引腳再次翻轉)TCNTn == 0
- 4.
時,可自動加載初值TCNTn == 0
2.初始化
- 1.設定時鐘源
- 2.設定初值
- 3.加載初值,啟動Timer
- 4.設定為自動加載
- 5.中斷相關
- 需要設定:1.Prescaler,2.MUX(Divider),3.TCMPB0(不是PWM測試,是以該不需要設定),4.TCNTB0,5.TCON0
2.1 設定時鐘源
- 由上公式:
- 設定Prescaler
- 設定MUX
/* 1.設定timer0的時鐘
* Timer CLK = PCLK / {prescaler value+1} / {divider value}
* 50000000/(99+1)/(16) = 31250
*/
TCFG0 = 99; //Prescaler = 99,用于timer0,timer1
TCFG1 &= ~0xFF;
TCFG1 |= 3; //MUX0=1/16(即是 divider value)
2.2 設定初值
//2.設定timer0的初值
TCNTB0 = 15625; //0.5s中斷一次(15625/31250=0.5s)
2.3 手動加載初值
- 手動加載初值至TCNT0與TCMT0,啟動timer0
- 置1
2.4 清除手動加載
- 清零
2.5 設定自動重裝載并啟動
3. 構造函數指針
- 把每一個中斷的處理函數放置在指針數組中,當發生中斷時,通過判斷中斷号,調用對應的函數即可
3.1 定義
- 定義函數指針,指針的變量名為
irq_func
typedef void (*irq_func)(int);
irq_func irq_array[32];//定義存放函數指針數組(即:數組中存放的是函數指針)
-
的用途,先來看下其基本用法typedef void(*Func)(void)
typedef void (*func)(void);
void myfunc(void);
func pfun = myfunc;/*指派*/
pfun();/*調用*/
3.2 由來
-
的由來typedef void(*Func)(void);
- 其實這樣的形式聲明函數指針是有"問題"的。如果仿照變量類型聲明,聲明函數指針似乎應該這樣:
但是c标準的建立者沒有這樣做,不知道為什麼,而選擇了這樣的聲明:
C編譯器非常清楚,這就是在聲明一個void(*)() 類型的函數指針variable。
3.4 注冊函數
/* 注冊中斷
* param:1.中斷号,2.中斷服務函數
*/
void register_irq(int irq,irq_func fp)
{
irq_array[irq] = fp;//将fp指向的函數位址 存放在arr中
INTMSK &= (1<<irq);
}
- eg:
3.5 調用函數
/* 中斷處理函數
*
*/
void handle_irq_c(void)
{
/* 1.分辨中斷源 */
int bit = INTOFFSET;//判斷誰在請求中斷
/* 2.調用對應的處理函數 */
irq_array[bit](bit); //irq_array存放的是函數指針,加一個()即表示調用該函數
/* 3.清中斷 :從源頭開始清 */
SRCPND = (1<<bit);
INTPND = (1<<bit);
}