- #include <reg52.h>
- signed long beats = 0; //電機轉動節拍總數
- void KeyDriver();
- void main()
- {
- EA = 1; //使能總中斷
- TMOD = 0x01; //設置T0為模式1
- TH0 = 0xFC; //為T0賦初值0xFC67,定時1ms
- TL0 = 0x67;
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動T0
-
- while (1)
- {
- KeyDriver(); //調用按鍵驅動函數
- }
- }
- /* 步進電機啟動函數,angle-需轉過的角度 */
- void StartMotor(signed long angle)
- {
- //在計算前關閉中斷,完成后再打開,以避免中斷打斷計算過程而造成錯誤
- EA = 0;
- beats = (angle * 4076) / 360; //實測為4076拍轉動一圈
- EA = 1;
- }
- /* 步進電機停止函數 */
- void StopMotor()
- {
- EA = 0;
- beats = 0;
- EA = 1;
- }
- /* 按鍵動作函數,根據鍵碼執行相應的操作,keycode-按鍵鍵碼 */
- void KeyAction(unsigned char keycode)
- {
- static bit dirMotor = 0; //電機轉動方向
-
- if ((keycode>=0x30) && (keycode<=0x39)) //控制電機轉動1-9圈
- {
- if (dirMotor == 0)
- StartMotor(360*(keycode-0x30));
- else
- StartMotor(-360*(keycode-0x30));
- }
- else if (keycode == 0x26) //向上鍵,控制轉動方向為正轉
- {
- dirMotor = 0;
- }
- else if (keycode == 0x28) //向下鍵,控制轉動方向為反轉
- {
- dirMotor = 1;
- }
- else if (keycode == 0x25) //向左鍵,固定正轉90度
- {
- StartMotor(90);
- }
- else if (keycode == 0x27) //向右鍵,固定反轉90度
- {
- StartMotor(-90);
- }
- else if (keycode == 0x1B) //Esc鍵,停止轉動
- {
- StopMotor();
- }
- }
- /* 按鍵驅動函數,檢測按鍵動作,調度相應動作函數,需在主循環中調用 */
- void KeyDriver()
- {
- unsigned char i, j;
- static unsigned char backup[4][4] = { //按鍵值備份,保存前一次的值
- {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}
- };
-
- for (i=0; i<4; i++) //循環檢測4*4的矩陣按鍵
- {
- for (j=0; j<4; j++)
- {
- if (backup[i][j] != KeySta[i][j]) //檢測按鍵動作
- {
- if (backup[i][j] != 0) //按鍵按下時執行動作
- {
- KeyAction(KeyCodeMap[i][j]); //調用按鍵動作函數
- }
- backup[i][j] = KeySta[i][j]; //刷新前一次的備份值
- }
- }
- }
- }
- /* 電機轉動控制函數 */
- void TurnMotor()
- {
- unsigned char tmp; //臨時變量
- static unsigned char index = 0; //節拍輸出索引
- unsigned char code BeatCode[8] = { //步進電機節拍對應的IO控制代碼
- 0xE, 0xC, 0xD, 0x9, 0xB, 0x3, 0x7, 0x6
- };
-
- if (beats != 0) //節拍數不為0則產生一個驅動節拍
- {
- if (beats > 0) //節拍數大于0時正轉
- {
- index++; //正轉時節拍輸出索引遞增
- index = index & 0x07; //用&操作實現到8歸零
- beats--; //正轉時節拍計數遞減
- }
- else //節拍數小于0時反轉
- {
- index--; //反轉時節拍輸出索引遞減
- index = index & 0x07; //用&操作同樣可以實現到-1時歸7
- beats++; //反轉時節拍計數遞增
- }
- tmp = P1; //用tmp把P1口當前值暫存
- tmp = tmp & 0xF0; //用&操作清零低4位
- tmp = tmp | BeatCode[index]; //用|操作把節拍代碼寫到低4位
- P1 = tmp; //把低4位的節拍代碼和高4位的原值送回P1
- }
- else //節拍數為0則關閉電機所有的相
- {
- P1 = P1 | 0x0F;
- }
- }
- /* T0中斷服務函數,用于按鍵掃描與電機轉動控制 */
- void InterruptTimer0() interrupt 1
- {
- static bit div = 0;
-
- TH0 = 0xFC; //重新加載初值
- TL0 = 0x67;
- KeyScan(); //執行按鍵掃描
- //用一個靜態bit變量實現二分頻,即2ms定時,用于控制電機
- div = ~div;
- if (div == 1)
- {
- TurnMotor();
- }
- }
復制代碼 |