【STC8A8K64S4A12开发板】—开始做 定时器/计数器 实验啦
版權聲明:本文為博主原創文章,轉載請附上原文出處鏈接。
文章目錄
- 前言
- 一、硬件設計
- 1.TIMER概念介紹
- 2.STC8A8K64S4A12系列單片機定時器/計數器介紹
- 3.定時器/計數器工作模式
- 4.定時器/計數器溢出時間計算
- 5.定時器/計數器中斷配置步驟
- 二、軟件設計
- 1.定時器/計數器寄存器匯集
- 2.寄存器解析
- 2.1.中斷允許寄存器IE
- 2.2.中斷允許寄存器IE2
- 2.3.定時器/計數器中斷控制寄存器TCON
- 2.4.輔助寄存器AUXR
- 2.5.中斷與時鐘輸出控制寄存器INTCLKO
- 2.6.寄存器T4T3M
- 2.7.中斷優先級控制寄存器IP
- 3.定時器0定時實驗
- 3.1.工程需要用到的c文件
- 3.2.頭文件引用和路徑設置
- 3.3.編寫代碼
- 4.定時器1定時實驗
- 4.1.工程需要用到的c文件
- 4.2.編寫代碼
- 5.定時器2定時實驗
- 5.1.工程需要用到的c文件
- 5.2.編寫代碼
- 6.定時器3定時實驗
- 6.1.工程需要用到的c文件
- 6.2.編寫代碼
- 7.定時器4定時實驗
- 7.1.工程需要用到的c文件
- 7.2.編寫代碼
- 8.多個定時器定時實驗
- 8.1.工程需要用到的c文件
- 8.2.編寫代碼
- 總結
前言
開始做 定時器/計數器 實驗啦!先介紹原理再開始實驗。
一、硬件設計
1.TIMER概念介紹
定時器(timer)幾乎是每個MCU必有的重要外設之一,可用于定時、精確延時、計數等等,在檢測、控制領域有廣泛應用。
定時器運行時不占用CPU時間,配置好之后,可以與CPU并行工作,實現精確的定時和計數,并且可以通過軟件控制其是否產生中斷,使用起來靈活方便。通常MCU在介紹定時器外設時,總是和計數器(counter)一起出現,所以我們有必要先了解一下定時器和計數器的區別。
定時器和計數器實際都是通過計數器來計數,定時器是對周期不變的脈沖計數(一般來自于系統時鐘),由計數的個數和脈沖的周期即可計算出時間,同時,通過一個給定的預期值(即比較值,對應預期的計數值,也就是預期時間),當計數值達到預期值時產生中斷,這樣就實現了定時,應用程序通過設置不同的預期值實現不同時長的定時。
計數器是對某一事件進行計數,這個事件每發生一次,計數值加/減1,而這個事件的產生可能是沒有規律的。也就是計數器的用途是對事件的發生次數進行計數,由計數值來反映事件產生的次數。
☆注:不同MCU定時器外設使用的計數器位數是個重要的參數,STC8A8K64S4A12系列MCU的定時器使用的是16位計數器(由定時器高8位寄存器和定時器低8位寄存器組合起來實現)。
2.STC8A8K64S4A12系列單片機定時器/計數器介紹
STC8A8K64S4A12系列單片機有5個16位的定時器/計數器,即定時器/計數器T0、定時器/計數器T1、定時器/計數器T2、定時器/計數器T3、定時器/計數器T4。
這些定時器/計數器外設有2種工作方式:定時方式(定時器)和計數方式(計數器)。可通過特殊功能寄存器設置相應的C/T控制位,來選擇定時器/計數器工作在哪種方式。
定時器/計數器外設的核心部件是一個加法計數器,其本質是對脈沖信號進行計數。不同的是,定時器的脈沖信號來自于系統時鐘,而計數器的脈沖信號來自于單片機特定外部輸入引腳。STC8A8K64S4A12系列單片機計數器特定外部輸入引腳如下表。
| T1 | P3.4 | P3.2 | 計數器0外部輸入引腳 | 非獨立GPIO | LCD12864/LCD1602屏接口 |
| T2 | P3.5 | P3.3 | 計數器1外部輸入引腳 | 非獨立GPIO | LCD12864/LCD1602屏接口 |
| T3 | P1.2 | P3.6 | 計數器2外部輸入引腳 | 非獨立GPIO | nRF24L01P模塊接口 |
| T4 | P0.4 | P3.7 | 計數器3外部輸入引腳 | 非獨立GPIO | nRF24L01P模塊接口 |
| T5 | P0.6 | P3.0 | 計數器4外部輸入引腳 | 非獨立GPIO | 電位器ADC采樣 |
☆注:獨立GPIO表示開發板沒有其他的電路使用這個GPIO,非獨立GPIO說明開發板有其他電路用到了該GPIO。針對非獨立GPIO使用時需特別注意。
STC8A8K64S4A12系列單片機定時器/計數器通過相關寄存器的C/T位選擇計數器輸入脈沖信號來源,也即選擇了工作方式是定時方式還是計數方式。后配置相關寄存器位控制輸入脈沖信號至計數器,計數器溢出后產生中斷,也可通過特定引腳輸出產生溢出時鐘。定時器/計數器結構原理示意圖如下。
圖1:定時器/計數器結構原理示意圖☆注:12T模式是選擇對系統時鐘12分頻,1T模式是選擇對系統時鐘不分頻。另外,該計數器是遞增計數器,不具有遞減功能。
■ 定時器/計數器工作在定時方式(定時器)時:
| T0CLKO | P3.5 | T0時鐘輸出引腳 | 非獨立GPIO | LCD12864/LCD1602屏接口 |
| T1CLKO | P3.4 | T1時鐘輸出引腳 | 非獨立GPIO | LCD12864/LCD1602屏接口 |
| T2CLKO | P1.3 | T2時鐘輸出引腳 | 非獨立GPIO | nRF24L01P模塊接口 |
| T3CLKO | P0.5 | T3時鐘輸出引腳 | 非獨立GPIO | 用戶按鍵KEY4 |
| T4CLKO | P0.7 | T4時鐘輸出引腳 | 非獨立GPIO | 用戶按鍵KEY3 |
☆注:獨立GPIO表示開發板沒有其他的電路使用這個GPIO,非獨立GPIO說明開發板有其他電路用到了該GPIO。針對非獨立GPIO使用時需特別注意。
■ 定時器/計數器工作在計數方式(計數器)時:
3.定時器/計數器工作模式
STC8A8K64S4A12系列MCU不同的定時器/計數器所具有的可供選擇的工作模式不同,定時器/計數器0和定時器/計數器1有多種模式可供選擇,選擇模式是通過寄存器TMOD對應的M0位和M1位實現。定時器/計數器2、定時器/計數器3和定時器/計數器4只有默認的一種工作模式。具體如下面列表所示。
表3:STC8A8K64S4A12系列定時器/計數器工作模式| 1 | 模式0:16位自動重裝載模式 | 有 | 有 | 有 | 有 | 有 |
| 2 | 模式1:16位不可重裝載模式 | 有 | 有 | |||
| 3 | 模式2:8位自動重裝載模式 | 有 | 有 | |||
| 4 | 模式3:不可屏蔽16位自動重裝載模式 | 有 |
☆注:模式0是STC官方推薦學習的定時器/計數器工作模式,也是我們講解的重點。當T0工作在模式3,T0可作為實時操作系統用節拍定時器。
下面介紹下定時器/計數器0和定時器/計數器1使用時非常重要的一個寄存器TMOD。
圖2:模式寄存器TMOD☆注:定時器/計數器的門控位在一些特殊應用中會有使用,一般情況下是將門控位置0。
■ 定時器/計數器0和定時器/計數器1工作模式0分析。
圖3:定時器/計數器0和定時器/計數器1模式0結構圖1)定時器/計數器0和定時器/計數器1均有GATE門控位為0、為1的情況。
2)當GATE=0時,控制定時器/計數器完全由TRx(定時器運行控制位)決定。
3)當GATE=1時,控制定時器/計數器不僅由TRx(定時器運行控制位)決定,還由外部中斷引腳上的信號決定。此時,可用于脈寬測量。
4)圖中隱藏2個寄存器RL_THx和RL_TLx,RL_THx和THx共用同一個地址,RL_TLx和TLx共用同一個地址。當Tx被禁止工作時,寫入THx和TLx的內容會同時被寫入RL_THx和RL_TLx中。當Tx開啟工作時,準備寫入THx和TLx的內容,其實沒有被寫入到寫入THx和TLx中,而是寫到了RL_THx和RL_TLx中。這樣便巧妙的實現16位重裝載定時。而讀THx和TLx的內容時,讀取的就是THx和TLx的內容,而不是RL_THx和RL_TLx中的值。
■ 定時器/計數器2、定時器/計數器3和定時器/計數器4工作模式0分析。
圖4:定時器/計數器2、定時器/計數器3和定時器/計數器4模式0結構圖1)定時器/計數器2、定時器/計數器3和定時器/計數器4不存在門控位GATE,對定時器/計數器的控制完全由TxR(定時器運行控制位)決定。
2)定時器/計數器2、定時器/計數器3和定時器/計數器4有且只有一種模式,即16位重裝載模式,實現重裝載的原理請參考對定時器/計數器0和定時器/計數器的分析。
4.定時器/計數器溢出時間計算
STC8A8K64S4A12系列單片機作為定時器使用時,由于計數脈沖的周期是固定的,所以溢出前的脈沖數乘以脈沖周期就是定時時間,或者稱定時溢出時間。
下面是定時器溢出時間計算公式:
☆注:公式中的分頻因子PSC在配置定時器/計數器為12T模式時值為12,在配置定時器/計數器為1T模式時值為1。
舉例,配置定時器/計數器為1T模式,系統時鐘頻率為11.0592MHZ,高8位寄存器初始值為0x28,低8位寄存器初始值為0x00,計算下定時器溢出時間。
1)十六進制0x28轉成十進制是40,十六進制0x00轉成十進制是0。這樣初始裝載值為:256*40+0=10240。
2)16位計數器溢出前所計脈沖數為:65536-10240=55296。
3)分頻因子PSC在1T模式下值為1。系統時鐘頻率為11059200HZ。
4)定時器溢出時間:55296/11059200=0.005s=5ms。
5)如果已知定時器溢出時間,計算高8位寄存器初始裝載值和低8位寄存器初始裝載值,則是反推過來即可(建議使用軟件STC-ISP的定時器計算器)。
5.定時器/計數器中斷配置步驟
針對STC8A8K64S4A12系列單片機5個定時器/計數器外設,軟件的配置過程如下:
圖6:定時器/計數器中斷軟件配置步驟☆注:實驗例程即是按照上述配置步驟操作寄存器相關位實現,后有詳述。
二、軟件設計
1.定時器/計數器寄存器匯集
STC8A8K64S4A12系列單片機操作定時器/計數器時會用到18個寄存器,如下表所示:
表4:STC8A8K64S4A12系列定時器/計數器使用寄存器匯總| 1 | TCON | 讀/寫 | 定時器/計數器中斷控制寄存器。 |
| 2 | TMOD | 讀/寫 | 定時器/計數器模式寄存器。 |
| 3 | AUXR | 讀/寫 | 輔助寄存器1。 |
| 4 | INTCLKO | 讀/寫 | 中斷與時鐘輸出控制寄存器。 |
| 5 | IE | 讀/寫 | 中斷允許寄存器1。 |
| 6 | IE2 | 讀/寫 | 中斷允許寄存器2。 |
| 7 | IP | 讀/寫 | 中斷優先級寄存器1。 |
| 8 | T4T3M | 讀/寫 | T3和T4控制寄存器。 |
| 9 | TL0 | 讀/寫 | 定時器/計數器0低8位寄存器。 |
| 10 | TH0 | 讀/寫 | 定時器/計數器0高8位寄存器。 |
| 11 | TL1 | 讀/寫 | 定時器/計數器1低8位寄存器。 |
| 12 | TH1 | 讀/寫 | 定時器/計數器1高8位寄存器。 |
| 13 | T2L | 讀/寫 | 定時器/計數器2低8位寄存器。 |
| 14 | T2H | 讀/寫 | 定時器/計數器2高8位寄存器。 |
| 15 | T3L | 讀/寫 | 定時器/計數器3低8位寄存器。 |
| 16 | T3H | 讀/寫 | 定時器/計數器3高8位寄存器。 |
| 17 | T4L | 讀/寫 | 定時器/計數器4低8位寄存器。 |
| 18 | T4H | 讀/寫 | 定時器/計數器4高8位寄存器。 |
☆注:上述寄存器有部分不單單是用于定時器/計數器外設中的,比如寄存器TCON、IE、IE2等。
2.寄存器解析
2.1.中斷允許寄存器IE
外部中斷允許寄存器IE支持位尋址,該寄存器的B1和B3位是定時器/計數器0和定時器/計數器1的中斷允許位。
圖7:中斷允許寄存器2.2.中斷允許寄存器IE2
中斷允許寄存器IE2不支持位尋址,該寄存器的B2、B5和B6位是定時器/計數器2、定時器/計數器3和定時器/計數器4的中斷允許位。因為IE2寄存器不支持位尋址,所以舉例操作該寄存器B2位時,不可以直接“ET2=0;”進行操作,參考下圖。
圖8:中斷允許寄存器2.3.定時器/計數器中斷控制寄存器TCON
定時器/計數器中斷控制寄存器TCON支持位尋址,該寄存器的B4位和B6位是T0和T1的運行控制位,寄存器B5位和B7位是T0和T1的溢出中斷標志,含義如下圖。
圖9:定時器/計數器中斷控制寄存器☆注:TCON寄存器的低4個位是用于外部中斷的,在操作該寄存器時一定要按位操作,用不到的位不要操作。
2.4.輔助寄存器AUXR
輔助寄存器AUXR不支持位尋址,該寄存器的B6和B7位是定時器/計數器1和定時器/計數器0的速度控制位,寄存器的B1、B2和B3位是定時器/計數器2的速度控制位、工作方式選擇位和允許控制位。
圖10:輔助寄存器☆注:AUXR寄存器的B0和B5位在串口外設配置時可能會用到。
2.5.中斷與時鐘輸出控制寄存器INTCLKO
中斷與時鐘輸出控制寄存器INTCLKO不支持位尋址,該寄存器的B0、B1和B2位是定時器/計數器0、定時器/計數器1和定時器/計數器2的時鐘輸出引腳控制位。
圖11:中斷與時鐘輸出控制寄存器☆注:INTCLKO寄存器的定時器時鐘輸出功能和定時器工作模式及工作方式(定時還是計數)密切相關,用戶暫只需知道有這些關系,待項目應用時再分析頻率關系。
2.6.寄存器T4T3M
寄存器T4T3M不支持位尋址,該寄存器的B0到B3位是定時器/計數器3配置過程中會用到的位,寄存器的B4到B7位是定時器/計數器4配置過程中會用到的位。
圖12:T3T4M寄存器2.7.中斷優先級控制寄存器IP
中斷優先級控制寄存器IP支持位尋址,該寄存器的B1位和B3位是設置T0和T1中斷優先級的,含義如下圖。需要說明的是T2、T3和T4是沒有中斷優先級的。
圖13:中斷優先級控制寄存器3.定時器0定時實驗
☆注:本節的實驗源碼是在“實驗2-4-1:外部中斷0(下降沿中斷方式)”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-1:定時器0定時”。
3.1.工程需要用到的c文件
本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。
表5:實驗需要用到的c文件| 1 | led | .c | 包含與用戶led控制有關的用戶自定義函數 |
| 2 | timer | .c | 外部定時器有關的用戶自定義函數 |
| 3 | delay | .c | 包含用戶自定義延時函數 |
3.2.頭文件引用和路徑設置
■ 需要引用的頭文件
#include "delay.h" #include "led.h" #include "timer.h"■ 需要包含的頭文件路徑
本例需要包含的頭文件路徑如下表:
| 1 | …\ Source | led.h、timer.h和delay.h頭文件在該路徑,所以要包含 |
| 2 | …\User | STC8.h頭文件在該路徑,所以要包含 |
STC8.h頭文件在該路徑,所以要包含
圖14:添加頭文件包含路徑3.3.編寫代碼
首先,在timer.c文件中編寫定時器0的初始化函數Timer0Init,代碼如下。
程序清單:定時器0初始化函數
/*********************************************************** 功能描述:定時器0初始化 入口參數:無 返回值:無 ************************************************************/ void Timer0Init(void) { AUXR |= 0x80; //定時器0為1T模式 TMOD &= 0xF8; //定時器0設置為定時方式,工作模式為16位自動重裝模式 TMOD &= 0xF7; //定時器0門控位GATE設置為0 TL0 = 0x00; //1T模式下初始裝載值 TH0 = 0x28; //1T模式下初始裝載值 TF0 = 0; //清除T0中斷溢出標志位 ET0 = 1; //使能定時器0的溢出中斷允許位 TR0 = 1; //定時器0開始計時 }然后,編寫定時器0中斷服務函數,一旦響應中斷達到一定次數會執行翻轉用戶指示燈D3的任務,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器0中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer0_int (void) interrupt 1 { cnt++; //5ms進入1次中斷 if(cnt == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt = 0; } //進入中斷時會將定時器中斷溢出標志位硬件清零,因此下面一句可以不加的 TF0 = 0; //清除T0中斷溢出標志位 }最后,在主函數中調用T0初始化函數,開啟總中斷,而主循環中沒有任務,說明用戶指示燈D3變化來自于中斷。
代碼清單:主函數
int main(void) { Timer0Init(); //定時器0初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }4.定時器1定時實驗
==☆注:本節的實驗源碼是在“實驗2-5-1:定時器0定時”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-2:定時器1定時”。 ==
4.1.工程需要用到的c文件
本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-5-1:定時器0定時”部分。
4.2.編寫代碼
首先,在timer.c文件中編寫定時器1的初始化函數Timer1Init,代碼如下。
程序清單:定時器1初始化函數
/*********************************************************** 功能描述:定時器1初始化 入口參數:無 返回值:無 ************************************************************/ void Timer1Init(void) { AUXR |= 0x40; //定時器1為1T模式 TMOD &= 0x8F; //定時器1設置為定時方式,工作模式為16位自動重裝模式 TMOD &= 0x7F; //定時器1門控位GATE設置為0 TL1 = 0x00; //1T模式下初始裝載值 TH1 = 0x28; //1T模式下初始裝載值 TF1 = 0; //清除T1中斷溢出標志位 ET1 = 1; //使能定時器1的溢出中斷允許位 TR1 = 1; //定時器1開始計時 }然后,編寫定時器1中斷服務函數,一旦響應中斷達到一定次數會執行翻轉藍色指示燈D3的任務,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器1中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer1_int (void) interrupt TIMER1_VECTOR { cnt++; //5ms進入1次中斷 if(cnt == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt = 0; } //進入中斷時會將定時器中斷溢出標志位硬件清零,因此下面一句可以不加的 TF1 = 0; //清除T1中斷溢出標志位 }最后,在主函數中調用T1初始化函數,開啟總中斷,而主循環中沒有任務,說明用戶指示燈D3變化來自于中斷。
代碼清單:主函數
int main(void) { Timer1Init(); //定時器1初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }5.定時器2定時實驗
==☆注:本節的實驗源碼是在“實驗2-5-1:定時器0定時”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-3:定時器2定時”。 ==
5.1.工程需要用到的c文件
本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-5-1:定時器0定時”部分。
5.2.編寫代碼
首先,在timer.c文件中編寫定時器2的初始化函數Timer2Init,代碼如下。
程序清單:定時器2初始化函數
/*********************************************************** 功能描述:定時器2初始化 入口參數:無 返回值:無 ************************************************************/ void Timer2Init(void) { AUXR &= 0xF7; //定時器2設置為定時方式 AUXR |= 0x04; //設置定時器2為1T模式 T2L = 0x00; //1T模式下初始裝載值 T2H = 0x28; //1T模式下初始裝載值 IE2 |= 0x04; //使能定時器2中斷 AUXR |= 0x10; //打開定時器2 }然后,編寫定時器2中斷服務函數,一旦響應中斷達到一定次數會執行翻轉藍色指示燈D3的任務,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器2中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer2_int (void) interrupt TIMER2_VECTOR { cnt++; //5ms進入1次中斷 if(cnt == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt = 0; } }最后,在主函數中調用T2初始化函數,開啟總中斷,而主循環中沒有任務,說明用戶指示燈D3變化來自于中斷。
代碼清單:主函數
int main(void) { Timer2Init(); //定時器2初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }6.定時器3定時實驗
==☆注:本節的實驗源碼是在“實驗2-5-1:定時器0定時”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-4:定時器3定時”。 ==
6.1.工程需要用到的c文件
本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-5-1:定時器0定時”部分。
6.2.編寫代碼
首先,在timer.c文件中編寫定時器3的初始化函數Timer2Init,代碼如下。
程序清單:定時器3初始化函數
/*********************************************************** 功能描述:定時器3初始化 入口參數:無 返回值:無 ************************************************************/ void Timer3Init(void) { T4T3M &= 0xFB; //定時器3設置為定時方式 T4T3M |= 0x02; //設置定時器3為1T模式 T3L = 0x00; //1T模式下初始裝載值 T3H = 0x28; //1T模式下初始裝載值 IE2 |= (1<<5); //使能定時器3中斷 T4T3M |= 0x08; //打開定時器3 }然后,編寫定時器3中斷服務函數,一旦響應中斷達到一定次數會執行翻轉藍色指示燈D3的任務,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器3中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer3_int (void) interrupt TIMER3_VECTOR { cnt++; //5ms進入1次中斷 if(cnt == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt = 0; } }最后,在主函數中調用T3初始化函數,開啟總中斷,而主循環中沒有任務,說明用戶指示燈D3變化來自于中斷。
代碼清單:主函數
int main(void) { Timer3Init(); //定時器3初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }7.定時器4定時實驗
==☆注:本節的實驗源碼是在“實驗2-5-1:定時器0定時”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-5:定時器4定時”。 ==
7.1.工程需要用到的c文件
本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-5-1:定時器0定時”部分。
7.2.編寫代碼
首先,在timer.c文件中編寫定時器4的初始化函數Timer4Init,代碼如下。
程序清單:定時器4初始化函數
/*********************************************************** 功能描述:定時器4初始化 入口參數:無 返回值:無 ************************************************************/ void Timer4Init(void) { T4T3M &= 0xBF; //定時器4設置為定時方式 T4T3M |= 0x20; //設置定時器4為1T模式 T4L = 0x00; //1T模式下初始裝載值 T4H = 0x28; //1T模式下初始裝載值 IE2 |= (1<<6); //使能定時器4中斷 T4T3M |= 0x80; //打開定時器4 }然后,編寫定時器4中斷服務函數,一旦響應中斷達到一定次數會執行翻轉藍色指示燈D3的任務,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器4中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer4_int (void) interrupt TIMER4_VECTOR { cnt++; //5ms進入1次中斷 if(cnt == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt = 0; } }最后,在主函數中調用T4初始化函數,開啟總中斷,而主循環中沒有任務,說明用戶指示燈D3變化來自于中斷。
代碼清單:主函數
int main(void) { Timer4Init(); //定時器4初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }8.多個定時器定時實驗
==☆注:本節的實驗源碼是在“實驗2-5-1:定時器0定時”的基礎上修改。本節對應的實驗源碼是:“實驗2-5-6:多個定時器定時”。 ==
8.1.工程需要用到的c文件
本實驗需要用到的頭文件以及添加頭文件包含路徑的方法請參考“實驗2-5-1:定時器0定時”部分。
8.2.編寫代碼
首先,在timer.c文件中編寫定時器0和定時器1的初始化函數Timer0Init和Timer1Init,代碼如下。
程序清單:定時器0和定時器1初始化函數
/*********************************************************** 功能描述:定時器0初始化 入口參數:無 返回值:無 ************************************************************/ void Timer0Init(void) { AUXR |= 0x80; //定時器0為1T模式 TMOD &= 0xF8; //定時器0設置為定時方式,工作模式為16位自動重裝模式 TMOD &= 0xF7; //定時器0門控位GATE設置為0 TL0 = 0x00; //1T模式下初始裝載值 TH0 = 0x28; //1T模式下初始裝載值 TF0 = 0; //清除T0中斷溢出標志位 ET0 = 1; //使能定時器0的溢出中斷允許位 TR0 = 1; //定時器0開始計時 } /*********************************************************** 功能描述:定時器1初始化 入口參數:無 返回值:無 ************************************************************/ void Timer1Init(void) { AUXR |= 0x40; //定時器1為1T模式 TMOD &= 0x8F; //定時器1設置為定時方式,工作模式為16位自動重裝模式 TMOD &= 0x7F; //定時器1門控位GATE設置為0 TL1 = 0x00; //1T模式下初始裝載值 TH1 = 0x28; //1T模式下初始裝載值 TF1 = 0; //清除T1中斷溢出標志位 ET1 = 1; //使能定時器1的溢出中斷允許位 TR1 = 1; //定時器1開始計時 }然后,編寫定時器0和定時器1的中斷服務函數,一旦響應中斷達到一定次數會執行翻轉對應用戶指示燈的操作,代碼如下。
程序清單:中斷服務函數
/*********************************************************** 功能描述:定時器0中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer0_int (void) interrupt TIMER0_VECTOR { cnt1++; //5ms進入1次中斷 if(cnt1 == 100) //100次中斷被響應后,正好500ms { led_toggle(LED_3); //翻轉用戶指示燈D3 cnt1 = 0; } //進入中斷時會將定時器中斷溢出標志位硬件清零,因此下面一句可以不加的 TF0 = 0; //清除T0中斷溢出標志位 } /*********************************************************** 功能描述:定時器1中斷服務程序 入口參數:無 返回值:無 ************************************************************/ void timer1_int (void) interrupt TIMER1_VECTOR { cnt2++; //5ms進入1次中斷 if(cnt2 == 200) //200次中斷被響應后,正好1000ms { led_toggle(LED_4); //翻轉用戶指示燈D4 cnt2 = 0; } //進入中斷時會將定時器中斷溢出標志位硬件清零,因此下面一句可以不加的 TF1 = 0; //清除T1中斷溢出標志位 }最后,在主函數中調用T0和T1初始化函數,開啟總中斷,而主循環中沒有任務,藍色指示燈D3和藍色指示燈D4變化來自于中斷。
代碼清單:主函數
int main(void) { Timer0Init(); //定時器0初始化 Timer1Init(); //定時器1初始化 EA = 1; //使能總中斷 while (1) { ; //無任務,說明LED亮滅來自于中斷 } }總結
以上就是今天要講的內容,大家看完可以思考一下:本例可以設置T0和T1的中斷優先級嗎?會有什么樣的實驗現象呢?總結
以上是生活随笔為你收集整理的【STC8A8K64S4A12开发板】—开始做 定时器/计数器 实验啦的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CV算法工程师:工作一年的小反思
- 下一篇: 商业数据挖掘的应用场景,主要分为哪几种?