git教程 代碼托管平臺:git.acwing.com 1 git基本概念 工作區:倉庫的目錄。工作區是獨立於各個分支的。 暫存區:數據暫時存放的區域,類似於工作區寫入版本庫前的緩存區。暫存區是獨立於各個分支的。切換分支不會新創建暫存區。 版本庫:存放所有已經提交到本地倉庫的代碼版本 版本結構:樹結 ...
51 單片機【外部中斷、定時器中斷、回調函數】
這裡的外部中斷類似監聽器,時時刻刻監視某引腳的電平變化;這裡的定時器中斷類似於定時任務,可以定時執行某函數;這裡將回調函數和中斷結合起來,案例里有點設計模式的味道(忘了哪個了,也可能就是感覺,關於高層不能調用低層的解決),也有點函數式編程的味道。
1、中斷(包括 外部中斷 和 定時器中斷,串口todo)
中斷可以狹義地看作是監聽。它可監聽 如 按鈕按下、定時器溢出、CPU內部某值的改變等。
以下都是以89C52的某個(大概不是所有)單片機為例,(我也不知道這個是哪個,用哪個就查看哪個的手冊) 它共有8個中斷,這8個中斷包含 4個外部中斷、3個計時器中斷、1個串口中斷。中斷有四個優先順序可供我們設置。
- 關於這8個中斷。
- 串口中斷 todo
- 外部中斷。 太長了,放下麵了,和 “中斷” 同級了
- 定時器中斷。 太長了,放下麵了,和 “中斷” 同級了
- 關於優先順序。
- 優先順序需要我們自己設置,沒設置的話每個中斷沒有優先順序,所以看作它們是同一個優先順序,這時需要通過查詢順序區分先後。
- 優先順序可以管控的情況分為兩種,第一種——A中斷正在執行,B中斷觸發了; 第二種——A和B中斷同時觸發了。這兩種情況都會比較A和B的優先順序進行區分誰去執行。
- 每一個當下沒執行但已經觸發了的中斷到後來都會被執行的。
- 如果兩個中斷平級,則按查詢順序決定哪個中斷先執行。
- 按 查詢順序(不是優先順序)給中斷排一下順序: 外部中斷0(INT0')、 定時器中斷0(Timer0)、外部中斷1(INT1')、定時器1(Timer1)、串口中斷(UART)、定時器中斷2(Timer2)、外部中斷2(INT2')、外部中斷3(INT3')。
- 通過查手冊設置優先順序。
2、外部中斷
外部中斷有4個,分別監視四個引腳(P32、P33、P42、P43)。
-
我們需要先配置外部中斷,進行一系列的參數開啟,才可以讓它監視起來。 這裡只記錄一丟丟,具體操作需要查詢數據手冊。看下圖,當我們想使用 INT0' 中斷時,我們 要做的是 把 總開關 EA、管控 INT0' 的 EX0打開,然後通過 IT0控制是下降沿觸發還是低電平觸發即可。
外部中斷配置起來簡單,但要註意的是,有些寄存器的位在頭文件里沒有定義,可通過數據手冊或下麵的第三個圖找到它的寄存器然後操作即可。
中斷請求標誌位寫代碼時用不到。
/** * 以0號中斷為例 */ #include <STC89C5xRC.H> #define LED_0 P00 /** * @brief 初始化0號中斷,這個函數需要被調用一次以開啟中斷 */ void Init_Int0(){ // 打開中斷總開關 EA = 1; // 打開外部中斷1開關 EX0 = 1; // 配置中斷為下降沿觸發 IT0 = 1; } /** * 0號中斷觸發後要執行的代碼 */ void Func_Int0() interrupt 0 { // interrupt後面的數是啥看手冊 LED_0 = ~LED_0; }
3、定時器中斷。
關於配置定時器中斷用到的寄存器位看下圖 或者 從數據手冊找。
定時器的觸發條件是計數寄存器溢出時觸發。
計數寄存器有兩個,可通過模式決定如何使用這兩個寄存器。修改M0和M1的值,如下第三張圖片,或者查手冊。
C/T、GATE、M1、M0 這四個位都在TMOD寄存器里,這個寄存器8bit,另外4bit操控另一個定時器的這四個位,這四個位如何配置看圖或手冊。
看代碼吧
void Timer0_Init() {
// 打開中斷開關
EA = 1;
// 打開定時器中斷開關
ET0 = 1;
// 開啟TR0,允許 第一個定時器 中斷計數
TR0 = 1;
// 設置TMOD,TMOD是一個寄存器,它高四位和低四位分別控制兩個不同的定時器
// 我們需要操作低四位的那個寄存器,高四位保持原態
TMOD &= 0xF0;
TMOD |= 0x01;
// timer0 設置為 1ms 中斷
TL0 = T1MS;
TH0 = T1MS >> 8;
counter = 0;
}
總的來說一下,外部中斷的配置需要 總開關EA,單個開關,下降沿/低電平的觸發方式; 定時器中斷配置需要 總開關EA,單個開關,TR0/1/2、控制電路的TMOD(也就是裡面的位)、兩個寄存器的值(通過它倆控制時間)
回調函數 todo
使用回調函數有個有點,就是可以在高一層定義回調,高一層不用調用低一層的代碼,低一層直接調用高一層的回調來掉自己這一層的函數。