| 應(yīng)用舉例 現(xiàn)在來舉例說明上述幾個(gè)模塊的使用方法。 硬件環(huán)境描述: 為了控制一盞燈,需要單片機(jī)提供一個(gè)做控制功能的開關(guān)量,這里不描述外部接口電路,只說明當(dāng)單片機(jī)的P10腳為高電平時(shí),燈滅,當(dāng)P10腳為低電平時(shí),燈亮。 可以通過計(jì)算機(jī)由串口發(fā)送命令來控制,或通過一個(gè)按鍵(push button不是自鎖式的按鍵)來手動(dòng)控制(按鍵接在P11腳上,當(dāng)鍵沒有按下時(shí),P11電平為高,鍵按下時(shí),引腳電平被接低),當(dāng)使用按鍵手動(dòng)控制的時(shí)候,需要給計(jì)算機(jī)發(fā)送通知。 設(shè)定串口通訊指令如下: 數(shù)據(jù)包由0xff做包頭,4個(gè)字節(jié)長,第二個(gè)字節(jié)為命令代碼,第三個(gè)字節(jié)為數(shù)據(jù),最后一個(gè)字節(jié)為校驗(yàn)位。 命令和數(shù)據(jù)代碼有如下組合: (計(jì)算機(jī)發(fā)給單片機(jī)) 0x10 0x01: 計(jì)算機(jī)控制燈亮。(數(shù)據(jù)位是非零值即可) 0x10 0x00: 計(jì)算機(jī)控制燈滅。 (單片機(jī)發(fā)給計(jì)算機(jī)) 0x11 0x01:單片機(jī)正常執(zhí)行控制指令,返回。(數(shù)據(jù)位是非零值即可) 0x11 0x00: 單片機(jī)不能夠正常執(zhí)行控制指令,或控制指令錯(cuò)(不明含義的數(shù)據(jù)包或校驗(yàn)錯(cuò)等)。 0x12 0x01:手動(dòng)控制燈亮。(數(shù)據(jù)位是非零值即可) 0x12 0x00: 手動(dòng)控制燈滅。 建立工程: 在硬盤上建立文件夾Projects,在Projects下建立Common文件夾及Example文件夾。將各模塊的頭文件及實(shí)現(xiàn)文件拷貝到Common 文件夾下(推薦使用這樣的文件組織結(jié)構(gòu),其它工程也可以建立在Projects下,各工程共享Common文件夾中的代碼)。 啟動(dòng)KeilC的IDE,在Example下建立新工程,將各模塊的實(shí)現(xiàn)文件包含進(jìn)工程。 在Example文件夾下建立Output文件夾,更改工程設(shè)置,將Output作為輸出文件和List文件的輸出文件夾(推薦使用這樣的結(jié)構(gòu),當(dāng)保存工程文件時(shí),可以簡單的刪除Output文件夾中的內(nèi)容而不會(huì)誤刪有用的工程文件)。 建立工程配置頭文件Config.h及工程主文件Example.c,并將Exmaple.c文件加入工程。 輸入代碼: 代碼的具體編寫過程略。下面是最后的Config.h文件及Example.c文件。 // // file: Config.h // #ifndef _CONFIG_H_ #define _CONFIG_H_ #include <Atmel/At89x52.h> // 使用AT89C52做控制 #include “../Common/Common.h” // 使用自定義的數(shù)據(jù)類型 #define TIMER_RELOAD 922 // 11.0592MHz晶振,1ms中斷周期 #define TIMER_KBSCANDELAY 40 // 40ms重檢測按鍵狀態(tài),即40ms消抖 #define SCOMM_AsyncInterface // 使用異步通訊服務(wù) #define IsPackageHeader(x) ((x) == 0xff) // 判斷包頭是不是0xff #define IsPackageTailer(x, y, z) ((y) <= (z)) // 判斷包的長度是不是足夠 #endif // _CONFIG_H_ // // file: Example.c // #include <Atmail/At89x52.h> #include “../Common/Common.h” #include “../Common/Timer.h” #include “../Common/Scomm.h” #include “../Common/KBScan.h” BIT gbitLampState = 1; // 燈的狀態(tài),缺省為off static void Initialize() { InitTimerModule(); // 初始化時(shí)鐘模塊 InitSCommModule(0xfd, TRUE); // 初始化通訊模塊,11.0592MHz晶振, // 波特率為19200 EA = 1; // 開中斷 } void main() { Initialize(); // 初始化 while(TRUE) // 主循環(huán) { ImpTimerService(); // 實(shí)現(xiàn)時(shí)鐘中斷服務(wù),如鍵盤掃描 AsyncRecePackage(4); // 接收4個(gè)字節(jié)長的數(shù)據(jù)包 } } // 在中斷外部響應(yīng)時(shí)鐘中斷事件 void OnTimerEvent() { // do nothing } // 控制外部燈 static void TriggerLamp(BIT bEnable) { P10 = ~bEnable; // 需要反相控制 } // 鍵掃描回調(diào)函數(shù) BYTE KBScan() { BIT b; P11 = 1; // 讀之前拉高引腳電平 b = P11; // 讀入引腳狀態(tài) return ~b; // 數(shù)據(jù)反相做掃描碼 } // 計(jì)算校驗(yàn)和 static BYTE CalcCheckSum(BYTE* pbyBuf, BYTE byLen) { BYTE by, bySum = 0; for(by = 0; by < byLen; by++) bySum += pbyBuf[by]; return 0 – bySum; } // 接收到鍵盤消息回調(diào)函數(shù) void onKeyPressed(BYTE byvalue, BYTE byState) { BYTE by[4]; if(byState == 0) { switch(byvalue) { case 0x01: gbitLampState = ~g bitLampState; // 燈狀態(tài)取反 TriggerLamp(gbitLampState); // 執(zhí)行控制 by[0] = 0xff; // 構(gòu)造數(shù)據(jù)包 by[1] = 0x12; by[2] = (BYTE)gbitLampState; by[3] = CalcCheckSum(by, 3); // 求校驗(yàn)和 SendPackage(by, 4); // 發(fā)送數(shù)據(jù)包 break; // 處理其它掃描碼 default: break; } } // 接收到數(shù)據(jù)包回調(diào)函數(shù) void OnRecePackage(BYTE* pbyBuf, BYTE byBufLen) { BYTE by[4]; by[0] = 0xff; by[1] = 0x11; if(byBufLen != 4  pbyBuf[3] != CalcCheckSum(pbyBuf, 3)) { by[2] = 0; by[3] = CalcCheckSum(by, 3); SendPackage(by, 4); // 處理長度或校驗(yàn)和不正確 } switch(pbyBuf[1]) { case 0x10: gbitLampState = (BIT)pbyBuf[2]; TriggerLamp(gbitLampState); by[2] = 1; by[3] = CalcCheckSum(by, 3); SendPackage(by, 4); // 發(fā)送成功執(zhí)行通知 break; default: // 不知道的命令 by[2] = 0; by[3] = CalcCheckSum(by, 3); SendPackage(by, 4); // 發(fā)送沒有成功執(zhí)行通知 break; } } |





