第一百三十四節(jié):“應(yīng)用層半雙工”雙機(jī)串口通訊的程序框架。
【134.1 應(yīng)用層的“半雙工”和“全雙工”?!?/span>
應(yīng)用層的“半雙工”。主機(jī)與從機(jī)在程序應(yīng)用層采用“一問(wèn)一答”的查詢模式,主機(jī)是主動(dòng)方,從機(jī)是被動(dòng)方,主機(jī)問(wèn)一句從機(jī)答一句,“聊天對(duì)話“的氛圍很無(wú)趣很呆板。從機(jī)沒(méi)有發(fā)言權(quán),當(dāng)從機(jī)想主動(dòng)給主機(jī)發(fā)送一些數(shù)據(jù)時(shí)就“憋得慌”。半雙工適用于大多數(shù)單向通訊的場(chǎng)合。
應(yīng)用層的“全雙工”。主機(jī)與從機(jī)在程序應(yīng)用層可以實(shí)現(xiàn)任意雙向的通訊,這時(shí)從機(jī)也可變?yōu)橹鳈C(jī),主機(jī)也可變?yōu)閺臋C(jī),就像兩個(gè)人平時(shí)聊天,無(wú)所謂誰(shuí)是從機(jī)誰(shuí)是主機(jī),也無(wú)所謂非要對(duì)方對(duì)我每句話都要應(yīng)答附和(只要對(duì)方能聽(tīng)得清我講什么就可以),“聊天對(duì)話”的氛圍很生動(dòng)很活潑。全雙工適用于通訊更復(fù)雜的場(chǎng)合。
本節(jié)從“半雙工“開(kāi)始講,讓初學(xué)者先熟悉雙機(jī)通訊的基本程序框架,下一節(jié)再講“全雙工“。
【134.2 雙機(jī)通訊的三類核心函數(shù)?!?/span>
雙機(jī)通訊在程序框架層面有三類核心的涵數(shù),它們分別是:通訊過(guò)程的控制涵數(shù),發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù),接收數(shù)據(jù)后的處理涵數(shù)。
“通訊過(guò)程的控制涵數(shù)”的數(shù)量可以不止1個(gè),每一個(gè)通訊事件都對(duì)應(yīng)一個(gè)獨(dú)立的“通訊過(guò)程的控制涵數(shù)”,根據(jù)通訊事件的數(shù)量,一個(gè)系統(tǒng)往往有N個(gè)“通訊過(guò)程的控制涵數(shù)”。顧名思義,它負(fù)責(zé)過(guò)程的控制,無(wú)論什么項(xiàng)目,凡是過(guò)程控制我都首選switch語(yǔ)句。此函數(shù)是屬于上層應(yīng)用的函數(shù),它的基礎(chǔ)底層是“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”和“接收數(shù)據(jù)后的處理涵數(shù)”這兩個(gè)函數(shù)。
“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”在系統(tǒng)中只有1個(gè)“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”,負(fù)責(zé)“通訊管道的占用”的分配,負(fù)責(zé)數(shù)據(jù)的具體發(fā)送。當(dāng)同時(shí)存在很多“待發(fā)送”的請(qǐng)求指令時(shí),此函數(shù)會(huì)根據(jù)“if ,else if...”的優(yōu)先級(jí),像隊(duì)列一樣安排各指令發(fā)送的先后順序,確保各指令不會(huì)發(fā)生沖突。此函數(shù)屬于底層的驅(qū)動(dòng)函數(shù)。
“接收數(shù)據(jù)后的處理涵數(shù)”在系統(tǒng)中只有1個(gè),負(fù)責(zé)處理當(dāng)前接收到的數(shù)據(jù),它既屬于“底層函數(shù)”也屬于“應(yīng)用層函數(shù)”,二者成分皆有。
我們一旦深刻地領(lǐng)悟了這三類函數(shù)各自的分工與關(guān)聯(lián)方式,將來(lái)應(yīng)付再?gòu)?fù)雜的通訊系統(tǒng)都會(huì)脈絡(luò)清析,游刃有余。
【134.3 例程的功能需求。】
上位機(jī)與下位機(jī)都有一個(gè)一模一樣的57個(gè)字節(jié)的大數(shù)組。在上位機(jī)端按下獨(dú)立按鍵K1后,上位機(jī)開(kāi)始與下位機(jī)建立通訊,上位機(jī)的目的是讀取下位機(jī)的那57個(gè)字節(jié)的大數(shù)組,分批讀取,每批讀取10個(gè)字節(jié),最后一批讀取的是余下的7個(gè)字節(jié)。讀取完畢后,上位機(jī)把讀取到的大數(shù)組與自己的大數(shù)組進(jìn)行對(duì)比:如果相等,表示通訊正確,蜂鳴器“長(zhǎng)鳴”一聲;如果不相等,表示通訊錯(cuò)誤,蜂鳴器“短鳴”一聲。在通訊過(guò)程中,如果出現(xiàn)通信異常(比如因?yàn)榻邮粘瑫r(shí)或者接收某批次數(shù)據(jù)錯(cuò)誤而導(dǎo)致重發(fā)的次數(shù)超過(guò)最大限制的次數(shù))也表示通訊錯(cuò)誤,蜂鳴器也會(huì)發(fā)出“短鳴”一聲的提示。
【134.4 例程的電路圖?!?/span>
兩個(gè)單片機(jī)進(jìn)行232串口通訊,一共需要3根線:1根作為共地線,其它2根是交叉的收發(fā)數(shù)據(jù)線(上位機(jī)的“接收線”連接下位機(jī)的“發(fā)送線”,上位機(jī)的“發(fā)送線”連接下位機(jī)的“接收線”),如下圖所示:
上圖134.4.1 雙機(jī)通訊的232串口接線圖
【134.5 例程的通訊協(xié)議?!?/span>
(一)通訊參數(shù)。波特率9600,校驗(yàn)位NONE(無(wú)),數(shù)據(jù)位8,停止位1。
(二)上位機(jī)讀取下位機(jī)的數(shù)組容量的大小的指令。
(1)上位機(jī)發(fā)送十六進(jìn)制的數(shù)據(jù):EB 01 00 00 00 07 ED。
EB是數(shù)據(jù)頭。
01是指令類型,01代表請(qǐng)求下位機(jī)返回大數(shù)組的容量大小。
00 00 00 07代表整個(gè)指令的數(shù)據(jù)長(zhǎng)度。
ED是前面所有字節(jié)數(shù)據(jù)的異或結(jié)果,用來(lái)作為校驗(yàn)數(shù)據(jù)。
(2)下位機(jī)返回十六進(jìn)制的數(shù)據(jù):EB 01 00 00 00 0C XX XX XX XX ZZ。
EB是數(shù)據(jù)頭。
01是指令類型,01代表返回大數(shù)組的容量大小。
00 00 00 0B代表整個(gè)指令的數(shù)據(jù)長(zhǎng)度
XX XX XX XX代表大數(shù)組的容量大小
ZZ是前面所有字節(jié)數(shù)據(jù)的異或結(jié)果,用來(lái)作為校驗(yàn)數(shù)據(jù)。
(三)上位機(jī)讀取下位機(jī)的大數(shù)組的分段數(shù)據(jù)的指令。
(1)上位機(jī)發(fā)送十六進(jìn)制的數(shù)據(jù):EB 02 00 00 00 0F RR RR RR RR YY YY YY YY ZZ
EB是數(shù)據(jù)頭
02是指令類型,02代表請(qǐng)求下位機(jī)返回當(dāng)前分段的數(shù)據(jù)。
00 00 00 0F代表整個(gè)指令的數(shù)據(jù)長(zhǎng)度
RR RR RR RR代表請(qǐng)求下位機(jī)返回的數(shù)據(jù)的“請(qǐng)求起始地址”
YY YY YY YY代表請(qǐng)求下位機(jī)從“請(qǐng)求起始地址”一次返回的數(shù)據(jù)長(zhǎng)度
ZZ是前面所有字節(jié)數(shù)據(jù)的異或結(jié)果,用來(lái)作為校驗(yàn)數(shù)據(jù)。
(2)下位機(jī)返回十六進(jìn)制的數(shù)據(jù):EB 02 TT TT TT TT RR RR RR RR YY YY YY YY HH ...HH ZZ
EB是數(shù)據(jù)頭
02是指令類型,02代表返回大數(shù)組當(dāng)前分段的數(shù)據(jù)
TT TT TT TT 代表整個(gè)指令的數(shù)據(jù)長(zhǎng)度
RR RR RR RR代表下位機(jī)返回?cái)?shù)據(jù)時(shí)的“請(qǐng)求起始地址”
YY YY YY YY代表下位機(jī)從“請(qǐng)求起始地址”一次返回的數(shù)據(jù)長(zhǎng)度
HH ...HH代表中間有效的數(shù)據(jù)內(nèi)容
ZZ是前面所有字節(jié)數(shù)據(jù)的異或結(jié)果,用來(lái)作為校驗(yàn)數(shù)據(jù)。
【134.6 解決本節(jié)例程編譯不過(guò)去的方法?!?/span>
因?yàn)楸竟?jié)用到的全局變量比較多,如果有初學(xué)者在編譯的時(shí)候出現(xiàn)“error C249: 'DATA': SEGMENT TOO LARGE”的提示,請(qǐng)按下圖的窗口提示來(lái)設(shè)置一下編譯的環(huán)境。
【134.7 例程的上位機(jī)程序?!?/span>
void usart(void); //串口接收的中斷函數(shù)void T0_time(); //定時(shí)器的中斷函數(shù)void BigBufferUsart(void); //讀取下位機(jī)大數(shù)組的“通訊過(guò)程的控制涵數(shù)”。三大核心函數(shù)之一void QueueSend(void); //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)。三大核心函數(shù)之一void ReceDataHandle(void); //接收數(shù)據(jù)后的處理涵數(shù)。三大核心函數(shù)之一void UsartTask(void); //串口收發(fā)的任務(wù)函數(shù),放在主函數(shù)內(nèi)unsigned char CalculateXor(const unsigned char *pCu8Buffer, //異或的算法函數(shù)unsigned long u32BufferSize);//比較兩個(gè)數(shù)組的是否相等。返回1代表相等,返回0代表不相等//u32BufferSize是參與對(duì)比的數(shù)組的大小unsigned char CmpTwoBufferIsSame(const unsigned char *pCu8Buffer_1,const unsigned char *pCu8Buffer_2,unsigned long u32BufferSize);void UsartSendByteData(unsigned char u8SendData); //發(fā)送一個(gè)字節(jié)的底層驅(qū)動(dòng)函數(shù)//發(fā)送帶協(xié)議的函數(shù)void UsartSendMessage(const unsigned char *pCu8SendMessage, unsigned long u32SendMaxSize);void SystemInitial(void) ;void Delay(unsigned long u32DelayTime) ;void PeripheralInitial(void) ;void BeepOpen(void);void BeepClose(void);void VoiceScan(void);void KeyScan(void);void KeyTask(void);sbit P3_4 = P3 ^ 4; //蜂鳴器的驅(qū)動(dòng)輸出口sbit KEY_INPUT1 = P2 ^ 2; //K1按鍵識(shí)別的輸入口。//下面表格數(shù)組的數(shù)據(jù)與下位機(jī)的表格數(shù)據(jù)一模一樣,目的用來(lái)檢測(cè)接收到的數(shù)據(jù)是否正確code unsigned char Cu8TestTable[] ={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57};unsigned char Gu8ReceTable[57]; //從下位機(jī)接收到的表格數(shù)據(jù)的數(shù)組//把一些針對(duì)某個(gè)特定事件的全局變量放在一個(gè)結(jié)構(gòu)體內(nèi),可以讓全局變量的分類更加清晰struct StructBigBufferUsart //控制讀取大數(shù)組的通訊過(guò)程的結(jié)構(gòu)體{unsigned char u8Status; //通訊過(guò)程的狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗unsigned char u8ReSendCnt; //重發(fā)計(jì)數(shù)器unsigned char u8Step; //通訊過(guò)程的步驟unsigned char u8Start; //通訊過(guò)程的啟動(dòng)unsigned long u32NeedSendSize; //一共需要發(fā)送的全部數(shù)據(jù)量unsigned long u32AlreadySendSize; //實(shí)際已經(jīng)發(fā)送的數(shù)據(jù)量unsigned long u32CurrentAddr; //當(dāng)前批次需要發(fā)送的起始地址unsigned long u32CurrentSize; //當(dāng)前批次從起始地址開(kāi)始發(fā)送的數(shù)據(jù)量unsigned char u8QueueSendTrig;//隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)unsigned char u8QueueSendBuffer[30]; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送指令的數(shù)組unsigned char u8QueueStatus; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗};unsigned char Gu8QueueReceUpdate = 0; //1代表“隊(duì)列發(fā)送數(shù)據(jù)后,收到了新的數(shù)據(jù)”struct StructBigBufferUsart GtBigBufferUsart;//此結(jié)構(gòu)體變量專門用來(lái)控制讀取大數(shù)組的通訊事件volatile unsigned char vGu8BigBufferUsartTimerFlag = 0; //過(guò)程控制的超時(shí)定時(shí)器volatile unsigned int vGu16BigBufferUsartTimerCnt = 0;volatile unsigned char vGu8QueueSendTimerFlag = 0; //隊(duì)列發(fā)送的超時(shí)定時(shí)器volatile unsigned int vGu16QueueSendTimerCnt = 0;volatile unsigned char vGu8BeepTimerFlag = 0;volatile unsigned int vGu16BeepTimerCnt = 0;volatile unsigned char vGu8KeySec = 0;unsigned char Gu8SendByteFinish = 0; //發(fā)送一個(gè)字節(jié)完成的標(biāo)志unsigned char Gu8ReceBuffer[REC_BUFFER_SIZE]; //常規(guī)控制類的小內(nèi)存unsigned char *pGu8ReceBuffer; //用來(lái)切換接收內(nèi)存的“中轉(zhuǎn)指針”unsigned long Gu32ReceCntMax = REC_BUFFER_SIZE; //最大緩存unsigned long Gu32ReceCnt = 0; //接收緩存數(shù)組的下標(biāo)unsigned char Gu8ReceStep = 0; //接收中斷函數(shù)里的步驟變量unsigned char Gu8ReceFeedDog = 1; //“喂狗”的操作變量。unsigned char Gu8ReceType = 0; //接收的數(shù)據(jù)類型unsigned char Gu8Rece_Xor = 0; //接收的異或unsigned long Gu32ReceDataLength = 0; //接收的數(shù)據(jù)長(zhǎng)度unsigned char Gu8FinishFlag = 0; //是否已接收完成一串?dāng)?shù)據(jù)的標(biāo)志unsigned long *pu32Data; //用于數(shù)據(jù)轉(zhuǎn)換的指針volatile unsigned char vGu8ReceTimeOutFlag = 0; //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器的開(kāi)關(guān)volatile unsigned int vGu16ReceTimeOutCnt = 0; //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器,“喂狗”的對(duì)象void main(){SystemInitial();Delay(10000);PeripheralInitial();while(1){UsartTask(); //串口收發(fā)的任務(wù)函數(shù)KeyTask();}}void KeyTask(void) //按鍵任務(wù)函數(shù),放在主函數(shù)內(nèi){if(0 == vGu8KeySec){return; //按鍵的觸發(fā)序號(hào)是0意味著無(wú)按鍵觸發(fā),直接退出當(dāng)前函數(shù),不執(zhí)行此函數(shù)下面的代碼}switch(vGu8KeySec) //根據(jù)不同的按鍵觸發(fā)序號(hào)執(zhí)行對(duì)應(yīng)的代碼{case 1: //1號(hào)按鍵。K1的獨(dú)立按鍵//GtBigBufferUsart.u8Start在開(kāi)機(jī)初始化函數(shù)里必須初始化為0!這一步很關(guān)鍵!if(0 == GtBigBufferUsart.u8Start) //只有在還沒(méi)有啟動(dòng)的情況下,才能啟動(dòng){GtBigBufferUsart.u8Status = 0; //通訊過(guò)程的狀態(tài) 0為初始狀態(tài)GtBigBufferUsart.u8Step = 0; //通訊過(guò)程的步驟 0為從當(dāng)前開(kāi)始的步驟GtBigBufferUsart.u8Start = 1; //通訊過(guò)程的啟動(dòng)}vGu8KeySec = 0; //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號(hào)必須清零,避免一致觸發(fā)break;}}/* 注釋一:* 每一個(gè)通訊事件都對(duì)應(yīng)的一個(gè)獨(dú)立的“通訊過(guò)程的控制涵數(shù)”,一個(gè)系統(tǒng)中有多少個(gè)通訊事件,就存在* 多少個(gè)“通訊過(guò)程的控制涵數(shù)”。該函數(shù)負(fù)責(zé)某個(gè)通訊事件從開(kāi)始到結(jié)束的整個(gè)過(guò)程。比如本節(jié)項(xiàng)目,* 在通訊過(guò)程中,如果發(fā)現(xiàn)接收到的數(shù)據(jù)錯(cuò)誤,則繼續(xù)啟動(dòng)重發(fā)的機(jī)制。當(dāng)發(fā)現(xiàn)接收到的累加字節(jié)數(shù)等于* 預(yù)期想要接收的數(shù)量時(shí),則結(jié)束這個(gè)通訊的事件。*/void BigBufferUsart(void) //讀取下位機(jī)大數(shù)組的“通訊過(guò)程的控制涵數(shù)”{static const unsigned char SCu8ReSendCntMax = 3; //重發(fā)的次數(shù)static unsigned long *pSu32Data; //用于數(shù)據(jù)與數(shù)組轉(zhuǎn)換的指針switch(GtBigBufferUsart.u8Step) //過(guò)程控制,我首選switch語(yǔ)句!{case 0:if(1 == GtBigBufferUsart.u8Start) //通訊過(guò)程的啟動(dòng){//根據(jù)實(shí)際項(xiàng)目需要,在此第0步驟里可以添加一些初始化相關(guān)的數(shù)據(jù)GtBigBufferUsart.u8ReSendCnt = 0; //重發(fā)計(jì)數(shù)器清零GtBigBufferUsart.u8Step = 1; //切換到下一步}break;//-----------先發(fā)送“讀取下位機(jī)的數(shù)組容量的大小的指令”---------------------//-----------EB 01 00 00 00 07 ED ---------------------case 1:GtBigBufferUsart.u8QueueSendBuffer[0] = 0xeb; //數(shù)據(jù)頭GtBigBufferUsart.u8QueueSendBuffer[1] = 0x01; //數(shù)據(jù)類型 讀取數(shù)組容量大小pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2];*pSu32Data = 7; //數(shù)據(jù)長(zhǎng)度 本條指令的數(shù)據(jù)總長(zhǎng)是7個(gè)字節(jié)//異或算法的函數(shù)GtBigBufferUsart.u8QueueSendBuffer[6] = CalculateXor(GtBigBufferUsart.u8QueueSendBuffer,6); //最后一個(gè)字節(jié)不納入計(jì)算//隊(duì)列驅(qū)動(dòng)函數(shù)的狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗GtBigBufferUsart.u8QueueStatus = 0; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài)GtBigBufferUsart.u8QueueSendTrig = 1; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)vGu8BigBufferUsartTimerFlag = 0;vGu16BigBufferUsartTimerCnt = 2000;vGu8BigBufferUsartTimerFlag = 1; //過(guò)程控制的超時(shí)定時(shí)器的啟動(dòng)GtBigBufferUsart.u8Step = 2; //切換到下一步break;case 2: //發(fā)送之后,等待下位機(jī)返回的數(shù)據(jù)的狀態(tài)if(1 == GtBigBufferUsart.u8QueueStatus) //當(dāng)前批次的接收到的數(shù)據(jù)成功{GtBigBufferUsart.u8ReSendCnt = 0; //重發(fā)計(jì)數(shù)器清零GtBigBufferUsart.u32AlreadySendSize = 0; //實(shí)際已經(jīng)發(fā)送的數(shù)據(jù)量清零GtBigBufferUsart.u32CurrentAddr = 0; //當(dāng)前批次需要發(fā)送的起始地址GtBigBufferUsart.u32CurrentSize = 10; //從當(dāng)前批次起始地址開(kāi)始發(fā)送的數(shù)據(jù)量GtBigBufferUsart.u8Step = 3; //切換到下一步}else if(2 == GtBigBufferUsart.u8QueueStatus) //當(dāng)前批次的接收到的數(shù)據(jù)失敗{GtBigBufferUsart.u8ReSendCnt++;if(GtBigBufferUsart.u8ReSendCnt >= SCu8ReSendCntMax) //大于最大的重發(fā)次數(shù){GtBigBufferUsart.u8Step = 0;GtBigBufferUsart.u8Start = 0; //結(jié)束當(dāng)前的過(guò)程通訊GtBigBufferUsart.u8Status = 2; //對(duì)外宣布“通訊失敗”vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 30; //讓蜂鳴器“短鳴”一聲vGu8BeepTimerFlag = 1;}else{GtBigBufferUsart.u8Step = 1; //返回上一步,重發(fā)當(dāng)前段的數(shù)據(jù)}}else if(0 == vGu16BigBufferUsartTimerCnt) //當(dāng)前批次在等待接收返回?cái)?shù)據(jù)時(shí),超時(shí){GtBigBufferUsart.u8ReSendCnt++;if(GtBigBufferUsart.u8ReSendCnt >= SCu8ReSendCntMax) //大于最大的重發(fā)次數(shù){GtBigBufferUsart.u8Step = 0;GtBigBufferUsart.u8Start = 0; //結(jié)束當(dāng)前的過(guò)程通訊GtBigBufferUsart.u8Status = 2; //對(duì)外宣布“通訊失敗”vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 30; //讓蜂鳴器“短鳴”一聲vGu8BeepTimerFlag = 1;}else{GtBigBufferUsart.u8Step = 1; //返回上一步,重發(fā)當(dāng)前段的數(shù)據(jù)}}break;//-----------接著發(fā)送“讀取下位機(jī)的大數(shù)組的分段數(shù)據(jù)的指令”---------------------//-----------EB 02 00 00 00 0F RR RR RR RR YY YY YY YY ZZ ---------------------case 3:GtBigBufferUsart.u8QueueSendBuffer[0] = 0xeb; //數(shù)據(jù)頭GtBigBufferUsart.u8QueueSendBuffer[1] = 0x02; //數(shù)據(jù)類型 讀取分段數(shù)據(jù)pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2];*pSu32Data = 15; //數(shù)據(jù)長(zhǎng)度 本條指令的數(shù)據(jù)總長(zhǎng)是15個(gè)字節(jié)pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2 + 4];*pSu32Data = GtBigBufferUsart.u32CurrentAddr; //當(dāng)前批次需要發(fā)送的起始地址pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2 + 4 + 4];*pSu32Data = GtBigBufferUsart.u32CurrentSize; //從當(dāng)前批次起始地址發(fā)送的數(shù)據(jù)量//異或算法的函數(shù)GtBigBufferUsart.u8QueueSendBuffer[14] = CalculateXor(GtBigBufferUsart.u8QueueSendBuffer,14); //最后一個(gè)字節(jié)不納入計(jì)算//隊(duì)列驅(qū)動(dòng)函數(shù)的狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗GtBigBufferUsart.u8QueueStatus = 0; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài)GtBigBufferUsart.u8QueueSendTrig = 1; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)vGu8BigBufferUsartTimerFlag = 0;vGu16BigBufferUsartTimerCnt = 2000;vGu8BigBufferUsartTimerFlag = 1; //過(guò)程控制的超時(shí)定時(shí)器的啟動(dòng)GtBigBufferUsart.u8Step = 4; //切換到下一步break;case 4: //發(fā)送之后,等待下位機(jī)返回的數(shù)據(jù)的狀態(tài)if(1 == GtBigBufferUsart.u8QueueStatus) //當(dāng)前批次的接收到的數(shù)據(jù)成功{//更新累加當(dāng)前實(shí)際已經(jīng)發(fā)送的字節(jié)數(shù)GtBigBufferUsart.u32AlreadySendSize = GtBigBufferUsart.u32AlreadySendSize +GtBigBufferUsart.u32CurrentSize;//更新下一步起始的發(fā)送地址GtBigBufferUsart.u32CurrentAddr = GtBigBufferUsart.u32CurrentAddr +GtBigBufferUsart.u32CurrentSize;//更新下一步從起始地址開(kāi)始發(fā)送的字節(jié)數(shù)if((GtBigBufferUsart.u32CurrentAddr + GtBigBufferUsart.u32CurrentSize) >GtBigBufferUsart.u32NeedSendSize) //最后一段數(shù)據(jù)的臨界點(diǎn)的判斷{GtBigBufferUsart.u32CurrentSize = GtBigBufferUsart.u32NeedSendSize -GtBigBufferUsart.u32CurrentAddr;}else{GtBigBufferUsart.u32CurrentSize = 10;}//判斷是否已經(jīng)把整個(gè)大數(shù)組的57個(gè)字節(jié)都已經(jīng)接收完畢。如果已經(jīng)接收完畢,則//結(jié)束當(dāng)前通信;如果還沒(méi)結(jié)束,則繼續(xù)請(qǐng)求下位機(jī)發(fā)送下一段新數(shù)據(jù)。if(GtBigBufferUsart.u32AlreadySendSize >= GtBigBufferUsart.u32NeedSendSize){GtBigBufferUsart.u8Step = 0;GtBigBufferUsart.u8Start = 0; //結(jié)束當(dāng)前的過(guò)程通訊if(1 == CmpTwoBufferIsSame(Cu8TestTable, //如果接收的數(shù)據(jù)與存儲(chǔ)的相等Gu8ReceTable,57)){vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 1000; //讓蜂鳴器“長(zhǎng)鳴”一聲vGu8BeepTimerFlag = 1;GtBigBufferUsart.u8Status = 1; //對(duì)外宣布“通訊成功”}else{vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 30; //讓蜂鳴器“短鳴”一聲vGu8BeepTimerFlag = 1;GtBigBufferUsart.u8Status = 2; //對(duì)外宣布“通訊失敗”}}else{GtBigBufferUsart.u8ReSendCnt = 0; //重發(fā)計(jì)數(shù)器清零GtBigBufferUsart.u8Step = 3; //返回上一步,繼續(xù)發(fā)下一段的新數(shù)據(jù)}}else if(2 == GtBigBufferUsart.u8QueueStatus) //當(dāng)前批次的接收到的數(shù)據(jù)失敗{GtBigBufferUsart.u8ReSendCnt++;if(GtBigBufferUsart.u8ReSendCnt >= SCu8ReSendCntMax) //大于最大的重發(fā)次數(shù){GtBigBufferUsart.u8Step = 0;GtBigBufferUsart.u8Start = 0; //結(jié)束當(dāng)前的過(guò)程通訊GtBigBufferUsart.u8Status = 2; //對(duì)外宣布“通訊失敗”vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 30; //讓蜂鳴器“短鳴”一聲vGu8BeepTimerFlag = 1;}else{GtBigBufferUsart.u8Step = 3; //返回上一步,重發(fā)當(dāng)前段的數(shù)據(jù)}}else if(0 == vGu16BigBufferUsartTimerCnt) //當(dāng)前批次在等待接收返回?cái)?shù)據(jù)時(shí),超時(shí){GtBigBufferUsart.u8ReSendCnt++;if(GtBigBufferUsart.u8ReSendCnt >= SCu8ReSendCntMax) //大于最大的重發(fā)次數(shù){GtBigBufferUsart.u8Step = 0;GtBigBufferUsart.u8Start = 0; //結(jié)束當(dāng)前的過(guò)程通訊GtBigBufferUsart.u8Status = 2; //對(duì)外宣布“通訊失敗”vGu8BeepTimerFlag = 0;vGu16BeepTimerCnt = 30; //讓蜂鳴器“短鳴”一聲vGu8BeepTimerFlag = 1;}else{GtBigBufferUsart.u8Step = 3; //返回上一步,重發(fā)當(dāng)前段的數(shù)據(jù)}}break;}}/* 注釋二:* 整個(gè)項(xiàng)目中只有一個(gè)“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”,負(fù)責(zé)“通訊管道的占用”的分配,負(fù)責(zé)數(shù)據(jù)的具體發(fā)* 送。當(dāng)同時(shí)存在很多“待發(fā)送”的請(qǐng)求指令時(shí),此函數(shù)會(huì)根據(jù)“if ,else if...”的優(yōu)先級(jí),像隊(duì)列一* 樣安排各指令發(fā)送的先后順序,確保各指令不會(huì)發(fā)生沖突。*/void QueueSend(void) //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù){static unsigned char Su8Step = 0;switch(Su8Step){case 0: //分派即將要發(fā)送的任務(wù)if(1 == GtBigBufferUsart.u8QueueSendTrig){GtBigBufferUsart.u8QueueSendTrig = 0; //及時(shí)清零。驅(qū)動(dòng)層,不管結(jié)果,只發(fā)一次。Gu8QueueReceUpdate = 0; //接收應(yīng)答數(shù)據(jù)的狀態(tài)恢復(fù)初始值//發(fā)送帶指令的數(shù)據(jù)UsartSendMessage((const unsigned char *)&GtBigBufferUsart.u8QueueSendBuffer[0],30);vGu8QueueSendTimerFlag = 0;vGu16QueueSendTimerCnt = 2000;vGu8QueueSendTimerFlag = 1; //隊(duì)列發(fā)送的超時(shí)定時(shí)器Su8Step = 1;}// else if(...) //當(dāng)有其它發(fā)送的指令時(shí),可以在此處繼續(xù)添加判斷,越往下優(yōu)先級(jí)越低// else if(...) //當(dāng)有其它發(fā)送的指令時(shí),可以在此處繼續(xù)添加判斷,越往下優(yōu)先級(jí)越低break;case 1: //發(fā)送之后,等待下位機(jī)的應(yīng)答。驅(qū)動(dòng)層,只管有沒(méi)有應(yīng)答,不管應(yīng)答對(duì)不對(duì)。if(1 == Gu8QueueReceUpdate) //如果“接收數(shù)據(jù)后的處理涵數(shù)”接收到應(yīng)答數(shù)據(jù){Su8Step = 0; //返回上一步繼續(xù)處理其它“待發(fā)送的指令”}if(0 == vGu16QueueSendTimerCnt) //發(fā)送指令之后,等待應(yīng)答超時(shí){Su8Step = 0; //返回上一步繼續(xù)處理其它“待發(fā)送的指令”}break;}}/* 注釋三:* 整個(gè)項(xiàng)目中只有一個(gè)“接收數(shù)據(jù)后的處理涵數(shù)”,負(fù)責(zé)即時(shí)處理當(dāng)前接收到的數(shù)據(jù)。*/void ReceDataHandle(void) //接收數(shù)據(jù)后的處理涵數(shù){static unsigned long *pSu32Data; //數(shù)據(jù)轉(zhuǎn)換的指針static unsigned long i;static unsigned char Su8Rece_Xor = 0; //計(jì)算的“異或”static unsigned long Su32CurrentAddr; //讀取的起始地址static unsigned long Su32CurrentSize; //讀取的發(fā)送的數(shù)據(jù)量if(1 == Gu8ReceFeedDog) //每被“喂一次狗”,就及時(shí)更新一次“超時(shí)檢測(cè)的定時(shí)器”的初值{Gu8ReceFeedDog = 0;vGu8ReceTimeOutFlag = 0;vGu16ReceTimeOutCnt = RECE_TIME_OUT; //更新一次“超時(shí)檢測(cè)的定時(shí)器”的初值vGu8ReceTimeOutFlag = 1;}else if(Gu8ReceStep > 0 && 0 == vGu16ReceTimeOutCnt) //超時(shí),并且步驟不在接頭暗號(hào)的步驟{Gu8ReceStep = 0; //串口接收數(shù)據(jù)的中斷函數(shù)及時(shí)切換回接頭暗號(hào)的步驟}if(1 == Gu8FinishFlag) //1代表已經(jīng)接收完畢一串新的數(shù)據(jù),需要馬上去處理{switch(Gu8ReceType) //接收到的數(shù)據(jù)類型{case 0x01: //讀取下位機(jī)的數(shù)組容量的大小Gu8QueueReceUpdate = 1; //告訴“隊(duì)列驅(qū)動(dòng)函數(shù)”收到了新的應(yīng)答數(shù)據(jù)Gu8Rece_Xor = Gu8ReceBuffer[Gu32ReceDataLength - 1]; //提取接收到的“異或”Su8Rece_Xor = CalculateXor(Gu8ReceBuffer, Gu32ReceDataLength - 1); //計(jì)算“異或”if(Gu32ReceDataLength >= 11 && //接收到的數(shù)據(jù)長(zhǎng)度必須大于或者等于11個(gè)字節(jié)Su8Rece_Xor == Gu8Rece_Xor) //驗(yàn)證“異或”,“計(jì)算的”與“接收的”是否一致{pSu32Data = (unsigned long *)&Gu8ReceBuffer[6]; //數(shù)據(jù)轉(zhuǎn)換。GtBigBufferUsart.u32NeedSendSize = *pSu32Data; //提取將要接收數(shù)組的大小GtBigBufferUsart.u8QueueStatus = 1; //告訴“過(guò)程控制函數(shù)”,當(dāng)前通訊成功}else{GtBigBufferUsart.u8QueueStatus = 2; //告訴“過(guò)程控制函數(shù)”,當(dāng)前通訊失敗}break;case 0x02: //讀取下位機(jī)的分段數(shù)據(jù)Gu8QueueReceUpdate = 1; //告訴“隊(duì)列驅(qū)動(dòng)函數(shù)”收到了新的應(yīng)答數(shù)據(jù)Gu8Rece_Xor = Gu8ReceBuffer[Gu32ReceDataLength - 1]; //提取接收到的“異或”Su8Rece_Xor = CalculateXor(Gu8ReceBuffer, Gu32ReceDataLength - 1); //計(jì)算“異或”pSu32Data = (unsigned long *)&Gu8ReceBuffer[6]; //數(shù)據(jù)轉(zhuǎn)換。Su32CurrentAddr = *pSu32Data; //讀取的起始地址pSu32Data = (unsigned long *)&Gu8ReceBuffer[6 + 4]; //數(shù)據(jù)轉(zhuǎn)換。Su32CurrentSize = *pSu32Data; //讀取的發(fā)送的數(shù)據(jù)量if(Gu32ReceDataLength >= 11 && //接收到的數(shù)據(jù)長(zhǎng)度必須大于或者等于11個(gè)字節(jié)Su8Rece_Xor == Gu8Rece_Xor && //驗(yàn)證“異或”,“計(jì)算的”與“接收的”是否一致Su32CurrentAddr == GtBigBufferUsart.u32CurrentAddr && //驗(yàn)證“地址”,相當(dāng)于驗(yàn)證“動(dòng)態(tài)密匙”Su32CurrentSize == GtBigBufferUsart.u32CurrentSize) //驗(yàn)證“地址”,相當(dāng)于驗(yàn)證“動(dòng)態(tài)密匙”{for(i = 0; i < Su32CurrentSize; i++){//及時(shí)把接收到的數(shù)據(jù)存儲(chǔ)到Gu8ReceTable數(shù)組Gu8ReceTable[Su32CurrentAddr + i] = Gu8ReceBuffer[6 + 4 + 4 + i];}GtBigBufferUsart.u8QueueStatus = 1; //告訴“過(guò)程控制函數(shù)”,當(dāng)前通訊成功}else{GtBigBufferUsart.u8QueueStatus = 2; //告訴“過(guò)程控制函數(shù)”,當(dāng)前通訊失敗}break;}Gu8FinishFlag = 0; //上面處理完數(shù)據(jù)再清零標(biāo)志,為下一次接收新的數(shù)據(jù)做準(zhǔn)備}}void UsartTask(void) //串口收發(fā)的任務(wù)函數(shù),放在主函數(shù)內(nèi){BigBufferUsart(); //讀取下位機(jī)大數(shù)組的“通訊過(guò)程的控制涵數(shù)”QueueSend(); //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)ReceDataHandle(); //接收數(shù)據(jù)后的處理涵數(shù)}void usart(void) interrupt 4 //串口接發(fā)的中斷函數(shù),中斷號(hào)為4{if(1 == RI) //接收完一個(gè)字節(jié)后引起的中斷{RI = 0; //及時(shí)清零,避免一直無(wú)緣無(wú)故的進(jìn)入中斷。if(0 == Gu8FinishFlag) //1代表已經(jīng)完成接收了一串新數(shù)據(jù),并且禁止接收其它新的數(shù)據(jù){Gu8ReceFeedDog = 1; //每接收到一個(gè)字節(jié)的數(shù)據(jù),此標(biāo)志就置1及時(shí)更新定時(shí)器的值。switch(Gu8ReceStep){case 0: //“前部分的”數(shù)據(jù)頭。接頭暗號(hào)的步驟。Gu8ReceBuffer[0] = SBUF; //直接讀取剛接收完的一個(gè)字節(jié)的數(shù)據(jù)。if(0xeb == Gu8ReceBuffer[0]) //等于數(shù)據(jù)頭0xeb,接頭暗號(hào)吻合。{Gu32ReceCnt = 1; //接收緩存的下標(biāo)Gu8ReceStep = 1; //切換到下一個(gè)步驟,接收其它有效的數(shù)據(jù)}break;case 1: //“前部分的”數(shù)據(jù)類型和長(zhǎng)度Gu8ReceBuffer[Gu32ReceCnt] = SBUF; //直接讀取剛接收完的一個(gè)字節(jié)的數(shù)據(jù)。Gu32ReceCnt++; //每接收一個(gè)字節(jié),數(shù)組下標(biāo)都自加1,為接收下一個(gè)數(shù)據(jù)做準(zhǔn)備if(Gu32ReceCnt >= 6) //前6個(gè)數(shù)據(jù)。接收完了“數(shù)據(jù)類型”和“數(shù)據(jù)長(zhǎng)度”。{Gu8ReceType = Gu8ReceBuffer[1]; //提取“數(shù)據(jù)類型”//以下的數(shù)據(jù)轉(zhuǎn)換,在第62節(jié)講解過(guò)的指針?lè)?/span>pu32Data = (unsigned long *)&Gu8ReceBuffer[2]; //數(shù)據(jù)轉(zhuǎn)換Gu32ReceDataLength = *pu32Data; //提取“數(shù)據(jù)長(zhǎng)度”if(Gu32ReceCnt >= Gu32ReceDataLength) //靠“數(shù)據(jù)長(zhǎng)度”來(lái)判斷是否完成{Gu8FinishFlag = 1; //接收完成標(biāo)志“置1”,通知主函數(shù)處理。Gu8ReceStep = 0; //及時(shí)切換回接頭暗號(hào)的步驟}else //如果還沒(méi)結(jié)束,繼續(xù)切換到下一個(gè)步驟,接收“有效數(shù)據(jù)”{//本節(jié)只用到一個(gè)接收數(shù)組,把指針關(guān)聯(lián)到Gu8ReceBuffer本身的數(shù)組pGu8ReceBuffer = (unsigned char *)&Gu8ReceBuffer[6];Gu32ReceCntMax = REC_BUFFER_SIZE; //最大緩存Gu8ReceStep = 2; //切換到下一個(gè)步驟}}break;case 2: //“后部分的”數(shù)據(jù)pGu8ReceBuffer[Gu32ReceCnt - 6] = SBUF; //這里的指針就是各種不同內(nèi)存的化身!!!Gu32ReceCnt++; //每接收一個(gè)字節(jié),數(shù)組下標(biāo)都自加1,為接收下一個(gè)數(shù)據(jù)做準(zhǔn)備//靠“數(shù)據(jù)長(zhǎng)度”來(lái)判斷是否完成。也不允許超過(guò)數(shù)組的最大緩存的長(zhǎng)度if(Gu32ReceCnt >= Gu32ReceDataLength || Gu32ReceCnt >= Gu32ReceCntMax){Gu8FinishFlag = 1; //接收完成標(biāo)志“置1”,通知主函數(shù)處理。Gu8ReceStep = 0; //及時(shí)切換回接頭暗號(hào)的步驟}break;}}}else //發(fā)送數(shù)據(jù)引起的中斷{TI = 0; //及時(shí)清除發(fā)送中斷的標(biāo)志,避免一直無(wú)緣無(wú)故的進(jìn)入中斷。Gu8SendByteFinish = 1; //從0變成1通知主函數(shù)已經(jīng)發(fā)送完一個(gè)字節(jié)的數(shù)據(jù)了。}}void UsartSendByteData(unsigned char u8SendData) //發(fā)送一個(gè)字節(jié)的底層驅(qū)動(dòng)函數(shù){static unsigned int Su16TimeOutDelay; //超時(shí)處理的延時(shí)計(jì)時(shí)器Gu8SendByteFinish = 0; //在發(fā)送以字節(jié)之前,必須先把此全局變量的標(biāo)志清零。SBUF = u8SendData; //依靠寄存器SBUF作為載體發(fā)送一個(gè)字節(jié)的數(shù)據(jù)Su16TimeOutDelay = 0xffff; //超時(shí)處理的延時(shí)計(jì)時(shí)器裝載一個(gè)相對(duì)合理的計(jì)時(shí)初始值while(Su16TimeOutDelay > 0) //超時(shí)處理{if(1 == Gu8SendByteFinish){break; //如果Gu8SendByteFinish為1,則發(fā)送一個(gè)字節(jié)完成,退出當(dāng)前循環(huán)等待。}Su16TimeOutDelay--; //超時(shí)計(jì)時(shí)器不斷遞減}//Delay();//在實(shí)際應(yīng)用中,當(dāng)連續(xù)發(fā)送一堆數(shù)據(jù)時(shí)如果發(fā)現(xiàn)丟失數(shù)據(jù),可以嘗試在此增加延時(shí)}//發(fā)送帶協(xié)議的函數(shù)void UsartSendMessage(const unsigned char *pCu8SendMessage, unsigned long u32SendMaxSize){static unsigned long i;static unsigned long *pSu32;static unsigned long u32SendSize;pSu32 = (const unsigned long *)&pCu8SendMessage[2];u32SendSize = *pSu32; //從帶協(xié)議的數(shù)組中提取整包數(shù)組的有效發(fā)送長(zhǎng)度if(u32SendSize > u32SendMaxSize) //如果“有效發(fā)送長(zhǎng)度”大于“最大限制的長(zhǎng)度”,數(shù)據(jù)異常{return; //數(shù)據(jù)異常,直接退出當(dāng)前函數(shù),預(yù)防數(shù)組越界}for(i = 0; i < u32SendSize; i++) //u32SendSize為發(fā)送的數(shù)據(jù)長(zhǎng)度{UsartSendByteData(pCu8SendMessage[i]); //基于“發(fā)送單字節(jié)的最小接口函數(shù)”來(lái)實(shí)現(xiàn)的}}unsigned char CalculateXor(const unsigned char *pCu8Buffer, //此處加const代表數(shù)組“只讀”unsigned long u32BufferSize) //參與計(jì)算的數(shù)組的大小{unsigned long i;unsigned char Su8Rece_Xor;Su8Rece_Xor = pCu8Buffer[0]; //提取數(shù)據(jù)串第“i=0”個(gè)數(shù)據(jù)作為異或的原始數(shù)據(jù)for(i = 1; i < u32BufferSize; i++) //注意,這里是從第“i=1”個(gè)數(shù)據(jù)開(kāi)始{Su8Rece_Xor = Su8Rece_Xor ^ pCu8Buffer[i]; //計(jì)算“異或”}return Su8Rece_Xor; //返回運(yùn)算后的異或的計(jì)算結(jié)果}//比較兩個(gè)數(shù)組的是否相等。返回1代表相等,返回0代表不相等unsigned char CmpTwoBufferIsSame(const unsigned char *pCu8Buffer_1,const unsigned char *pCu8Buffer_2,unsigned long u32BufferSize) //參與對(duì)比的數(shù)組的大小{unsigned long i;for(i = 0; i < u32BufferSize; i++){if(pCu8Buffer_1[i] != pCu8Buffer_2[i]){return 0; //只要有一個(gè)不相等,則返回0并且退出當(dāng)前函數(shù)}}return 1; //相等}void KeyScan(void) //此函數(shù)放在定時(shí)中斷里每1ms掃描一次{static unsigned char Su8KeyLock1; //1號(hào)按鍵的自鎖static unsigned int Su16KeyCnt1; //1號(hào)按鍵的計(jì)時(shí)器//1號(hào)按鍵if(0 != KEY_INPUT1) //IO是高電平,說(shuō)明按鍵沒(méi)有被按下,這時(shí)要及時(shí)清零一些標(biāo)志位{Su8KeyLock1 = 0; //按鍵解鎖Su16KeyCnt1 = 0; //按鍵去抖動(dòng)延時(shí)計(jì)數(shù)器清零,此行非常巧妙,是全場(chǎng)的亮點(diǎn)。}else if(0 == Su8KeyLock1) //有按鍵按下,且是第一次被按下。{Su16KeyCnt1++; //累加定時(shí)中斷次數(shù)if(Su16KeyCnt1 >= KEY_FILTER_TIME) //濾波的“穩(wěn)定時(shí)間”KEY_FILTER_TIME,長(zhǎng)度是25ms。{Su8KeyLock1 = 1; //按鍵的自鎖,避免一直觸發(fā)vGu8KeySec = 1; //觸發(fā)1號(hào)鍵}}}void T0_time() interrupt 1{VoiceScan();KeyScan();if(1 == vGu8BigBufferUsartTimerFlag && vGu16BigBufferUsartTimerCnt > 0) //過(guò)程控制的超時(shí)定時(shí)器{vGu16BigBufferUsartTimerCnt--;}if(1 == vGu8QueueSendTimerFlag && vGu16QueueSendTimerCnt > 0) //隊(duì)列發(fā)送的超時(shí)定時(shí)器{vGu16QueueSendTimerCnt--;}if(1 == vGu8ReceTimeOutFlag && vGu16ReceTimeOutCnt > 0) //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器{vGu16ReceTimeOutCnt--;}TH0 = 0xfc;TL0 = 0x66;}void SystemInitial(void){unsigned char u8_TMOD_Temp = 0;//以下是定時(shí)器0的中斷的配置TMOD = 0x01;TH0 = 0xfc;TL0 = 0x66;EA = 1;ET0 = 1;TR0 = 1;//以下是串口接收中斷的配置//串口的波特率與內(nèi)置的定時(shí)器1直接相關(guān),因此配置此定時(shí)器1就等效于配置波特率。u8_TMOD_Temp = 0x20; //即將把定時(shí)器1設(shè)置為:工作方式2,初值自動(dòng)重裝的8位定時(shí)器。TMOD = TMOD & 0x0f; //此寄存器低4位是跟定時(shí)器0相關(guān),高4位是跟定時(shí)器1相關(guān)。先清零定時(shí)器1。TMOD = TMOD | u8_TMOD_Temp; //把高4位的定時(shí)器1填入0x2,低4位的定時(shí)器0保持不變。TH1 = 256 - (11059200L / 12 / 32 / 9600); //波特率為9600。11059200代表晶振11.0592MHz,TL1 = 256 - (11059200L / 12 / 32 / 9600); //L代表long的長(zhǎng)類型數(shù)據(jù)。根據(jù)芯片手冊(cè)提供的計(jì)算公式。TR1 = 1; //開(kāi)啟定時(shí)器1SM0 = 0;SM1 = 1; //SM0與SM1的設(shè)置:選擇10位異步通訊,波特率根據(jù)定時(shí)器1可變REN = 1; //允許串口接收數(shù)據(jù)//為了保證串口中斷接收的數(shù)據(jù)不丟失,必須設(shè)置IP = 0x10,相當(dāng)于把串口中斷設(shè)置為最高優(yōu)先級(jí),//這個(gè)時(shí)候,串口中斷可以打斷任何其他的中斷服務(wù)函數(shù)實(shí)現(xiàn)嵌套,IP = 0x10; //把串口中斷設(shè)置為最高優(yōu)先級(jí),必須的。ES = 1; //允許串口中斷EA = 1; //允許總中斷}void Delay(unsigned long u32DelayTime){for(; u32DelayTime > 0; u32DelayTime--);}void PeripheralInitial(void){GtBigBufferUsart.u8Start = 0; //通訊過(guò)程的啟動(dòng)變量必須初始化為0!這一步很關(guān)鍵!}void BeepOpen(void){P3_4 = 0;}void BeepClose(void){P3_4 = 1;}void VoiceScan(void){static unsigned char Su8Lock = 0;if(1 == vGu8BeepTimerFlag && vGu16BeepTimerCnt > 0){if(0 == Su8Lock){Su8Lock = 1;BeepOpen();}else{vGu16BeepTimerCnt--;if(0 == vGu16BeepTimerCnt){Su8Lock = 0;BeepClose();}}}}
【134.8 例程的下位機(jī)程序?!?/span>
下位機(jī)作為從機(jī)應(yīng)答上位機(jī)的指令,程序相對(duì)簡(jiǎn)化了很多。不需要“通訊過(guò)程的控制涵數(shù)”,直接在“接收數(shù)據(jù)后的處理涵數(shù)”里啟動(dòng)“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”來(lái)發(fā)送應(yīng)答的數(shù)據(jù)即可。發(fā)送應(yīng)答數(shù)據(jù)后,也不用等待上位機(jī)的應(yīng)答數(shù)據(jù)。
void usart(void); //串口接收的中斷函數(shù)void T0_time(); //定時(shí)器的中斷函數(shù)void QueueSend(void); //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)void ReceDataHandle(void); //接收數(shù)據(jù)后的處理涵數(shù)void UsartTask(void); //串口收發(fā)的任務(wù)函數(shù),放在主函數(shù)內(nèi)unsigned char CalculateXor(const unsigned char *pCu8Buffer, //異或的算法的函數(shù)unsigned long u32BufferSize);void UsartSendByteData(unsigned char u8SendData); //發(fā)送一個(gè)字節(jié)的底層驅(qū)動(dòng)函數(shù)//發(fā)送帶協(xié)議的函數(shù)void UsartSendMessage(const unsigned char *pCu8SendMessage, unsigned long u32SendMaxSize);void SystemInitial(void) ;void Delay(unsigned long u32DelayTime) ;void PeripheralInitial(void) ;//下面表格數(shù)組的數(shù)據(jù)與上位機(jī)的表格數(shù)據(jù)一模一樣,目的用來(lái)讓上位機(jī)檢測(cè)接收到的數(shù)據(jù)是否正確code unsigned char Cu8TestTable[] ={0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57};//把一些針對(duì)某個(gè)特定事件的全局變量放在一個(gè)結(jié)構(gòu)體內(nèi),可以讓全局變量的分類更加清晰struct StructBigBufferUsart //應(yīng)答讀取大數(shù)組的通訊過(guò)程的結(jié)構(gòu)體{unsigned char u8QueueSendTrig;//隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)unsigned char u8QueueSendBuffer[30]; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送指令的數(shù)組unsigned char u8QueueStatus; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗};unsigned char Gu8QueueReceUpdate = 0; //1代表“隊(duì)列發(fā)送數(shù)據(jù)后,收到了新的數(shù)據(jù)”struct StructBigBufferUsart GtBigBufferUsart;//此結(jié)構(gòu)體變量專門用來(lái)應(yīng)答讀取大數(shù)組的通訊事件volatile unsigned char vGu8QueueSendTimerFlag = 0; //隊(duì)列發(fā)送的超時(shí)定時(shí)器volatile unsigned int vGu16QueueSendTimerCnt = 0;unsigned char Gu8SendByteFinish = 0; //發(fā)送一個(gè)字節(jié)完成的標(biāo)志unsigned char Gu8ReceBuffer[REC_BUFFER_SIZE]; //常規(guī)控制類的小內(nèi)存unsigned char *pGu8ReceBuffer; //用來(lái)切換接收內(nèi)存的“中轉(zhuǎn)指針”unsigned long Gu32ReceCntMax = REC_BUFFER_SIZE; //最大緩存unsigned long Gu32ReceCnt = 0; //接收緩存數(shù)組的下標(biāo)unsigned char Gu8ReceStep = 0; //接收中斷函數(shù)里的步驟變量unsigned char Gu8ReceFeedDog = 1; //“喂狗”的操作變量。unsigned char Gu8ReceType = 0; //接收的數(shù)據(jù)類型unsigned char Gu8Rece_Xor = 0; //接收的異或unsigned long Gu32ReceDataLength = 0; //接收的數(shù)據(jù)長(zhǎng)度unsigned char Gu8FinishFlag = 0; //是否已接收完成一串?dāng)?shù)據(jù)的標(biāo)志unsigned long *pu32Data; //用于數(shù)據(jù)轉(zhuǎn)換的指針volatile unsigned char vGu8ReceTimeOutFlag = 0; //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器的開(kāi)關(guān)volatile unsigned int vGu16ReceTimeOutCnt = 0; //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器,“喂狗”的對(duì)象void main(){SystemInitial();Delay(10000);PeripheralInitial();while(1){UsartTask(); //串口收發(fā)的任務(wù)函數(shù)}}/* 注釋一:* 整個(gè)項(xiàng)目中只有一個(gè)“發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)”,負(fù)責(zé)“通訊管道的占用”的分配,負(fù)責(zé)數(shù)據(jù)的具體發(fā)* 送。當(dāng)同時(shí)存在很多“待發(fā)送”的請(qǐng)求指令時(shí),此函數(shù)會(huì)根據(jù)“if ,else if...”的優(yōu)先級(jí),像隊(duì)列一* 樣安排各指令發(fā)送的先后順序,確保各指令不會(huì)發(fā)生沖突。*/void QueueSend(void) //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù){static unsigned char Su8Step = 0;switch(Su8Step){case 0: //分派即將要發(fā)送的任務(wù)if(1 == GtBigBufferUsart.u8QueueSendTrig){GtBigBufferUsart.u8QueueSendTrig = 0; //及時(shí)清零。驅(qū)動(dòng)層,不管結(jié)果,只發(fā)一次。Gu8QueueReceUpdate = 0; //接收應(yīng)答數(shù)據(jù)的狀態(tài)恢復(fù)初始值//發(fā)送帶指令的數(shù)據(jù)UsartSendMessage((const unsigned char *)&GtBigBufferUsart.u8QueueSendBuffer[0],30);//注意,這里是從機(jī)應(yīng)答主機(jī)的數(shù)據(jù),不需要等待返回的數(shù)據(jù),因此不需要切換Su8Step}// else if(...) //當(dāng)有其它發(fā)送的指令時(shí),可以在此處繼續(xù)添加判斷,越往下優(yōu)先級(jí)越低// else if(...) //當(dāng)有其它發(fā)送的指令時(shí),可以在此處繼續(xù)添加判斷,越往下優(yōu)先級(jí)越低break;case 1: //發(fā)送之后,等待下位機(jī)的應(yīng)答。驅(qū)動(dòng)層,只管有沒(méi)有應(yīng)答,不管應(yīng)答對(duì)不對(duì)。if(1 == Gu8QueueReceUpdate) //如果“接收數(shù)據(jù)后的處理涵數(shù)”接收到應(yīng)答數(shù)據(jù){Su8Step = 0; //返回上一步繼續(xù)處理其它“待發(fā)送的指令”}if(0 == vGu16QueueSendTimerCnt) //發(fā)送指令之后,等待應(yīng)答超時(shí){Su8Step = 0; //返回上一步繼續(xù)處理其它“待發(fā)送的指令”}break;}}/* 注釋二:* 整個(gè)項(xiàng)目中只有一個(gè)“接收數(shù)據(jù)后的處理涵數(shù)”,負(fù)責(zé)即時(shí)處理當(dāng)前接收到的數(shù)據(jù)。*/void ReceDataHandle(void) //接收數(shù)據(jù)后的處理涵數(shù){static unsigned long *pSu32Data; //數(shù)據(jù)轉(zhuǎn)換的指針static unsigned long i;static unsigned char Su8Rece_Xor = 0; //計(jì)算的“異或”static unsigned long Su32CurrentAddr; //讀取的起始地址static unsigned long Su32CurrentSize; //讀取的發(fā)送的數(shù)據(jù)量if(1 == Gu8ReceFeedDog) //每被“喂一次狗”,就及時(shí)更新一次“超時(shí)檢測(cè)的定時(shí)器”的初值{Gu8ReceFeedDog = 0;vGu8ReceTimeOutFlag = 0;vGu16ReceTimeOutCnt = RECE_TIME_OUT; //更新一次“超時(shí)檢測(cè)的定時(shí)器”的初值vGu8ReceTimeOutFlag = 1;}else if(Gu8ReceStep > 0 && 0 == vGu16ReceTimeOutCnt) //超時(shí),并且步驟不在接頭暗號(hào)的步驟{Gu8ReceStep = 0; //串口接收數(shù)據(jù)的中斷函數(shù)及時(shí)切換回接頭暗號(hào)的步驟}if(1 == Gu8FinishFlag) //1代表已經(jīng)接收完畢一串新的數(shù)據(jù),需要馬上去處理{switch(Gu8ReceType) //接收到的數(shù)據(jù)類型{case 0x01: //返回下位機(jī)的數(shù)組容量的大小Gu8Rece_Xor = Gu8ReceBuffer[Gu32ReceDataLength - 1]; //提取接收到的“異或”Su8Rece_Xor = CalculateXor(Gu8ReceBuffer, Gu32ReceDataLength - 1); //計(jì)算“異或”if(Su8Rece_Xor != Gu8Rece_Xor) //驗(yàn)證“異或”,如果不相等,退出當(dāng)前switch{break; //退出當(dāng)前switch}GtBigBufferUsart.u8QueueSendBuffer[0] = 0xeb; //數(shù)據(jù)頭GtBigBufferUsart.u8QueueSendBuffer[1] = 0x01; //數(shù)據(jù)類型 返回?cái)?shù)組容量的大小pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2];*pSu32Data = 11; //數(shù)據(jù)長(zhǎng)度 本條指令的數(shù)據(jù)總長(zhǎng)是11個(gè)字節(jié)//提取數(shù)組容量的大小pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2 + 4];*pSu32Data = sizeof(Cu8TestTable); //相當(dāng)于*pSu32Data=57;sizeof請(qǐng)參考第69節(jié)//異或算法的函數(shù)GtBigBufferUsart.u8QueueSendBuffer[10] = CalculateXor(GtBigBufferUsart.u8QueueSendBuffer,10); //最后一個(gè)字節(jié)不納入計(jì)算//隊(duì)列驅(qū)動(dòng)函數(shù)的狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗GtBigBufferUsart.u8QueueStatus = 0; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài)GtBigBufferUsart.u8QueueSendTrig = 1; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)Gu8QueueReceUpdate = 1; //告訴“隊(duì)列驅(qū)動(dòng)函數(shù)”此發(fā)送指令無(wú)需等待上位機(jī)的應(yīng)答break;case 0x02: //返回下位機(jī)的分段數(shù)據(jù)Gu8Rece_Xor = Gu8ReceBuffer[Gu32ReceDataLength - 1]; //提取接收到的“異或”Su8Rece_Xor = CalculateXor(Gu8ReceBuffer, Gu32ReceDataLength - 1); //計(jì)算“異或”if(Su8Rece_Xor != Gu8Rece_Xor) //驗(yàn)證“異或”,如果不相等,退出當(dāng)前switch{break; //退出當(dāng)前switch}pSu32Data = (unsigned long *)&Gu8ReceBuffer[6]; //數(shù)據(jù)轉(zhuǎn)換。Su32CurrentAddr = *pSu32Data; //讀取的起始地址pSu32Data = (unsigned long *)&Gu8ReceBuffer[6 + 4]; //數(shù)據(jù)轉(zhuǎn)換。Su32CurrentSize = *pSu32Data; //讀取的發(fā)送的數(shù)據(jù)量GtBigBufferUsart.u8QueueSendBuffer[0] = 0xeb; //數(shù)據(jù)頭GtBigBufferUsart.u8QueueSendBuffer[1] = 0x02; //數(shù)據(jù)類型 返回分段數(shù)據(jù)pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2];*pSu32Data = 6 + 4 + 4 + Su32CurrentSize + 1; //數(shù)據(jù)總長(zhǎng)度pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2 + 4];*pSu32Data = Su32CurrentAddr; //返回接收到的起始地址pSu32Data = (unsigned long *)&GtBigBufferUsart.u8QueueSendBuffer[2 + 4 + 4];*pSu32Data = Su32CurrentSize; //返回接收到的當(dāng)前批次的數(shù)據(jù)量for(i = 0; i < Su32CurrentSize; i++){//裝載即將要發(fā)送的分段數(shù)據(jù)GtBigBufferUsart.u8QueueSendBuffer[6 + 4 + 4 + i] = Cu8TestTable[Su32CurrentAddr + i];}//異或算法的函數(shù)GtBigBufferUsart.u8QueueSendBuffer[6 + 4 + 4 + Su32CurrentSize] =CalculateXor(GtBigBufferUsart.u8QueueSendBuffer, 6 + 4 + 4 + Su32CurrentSize);//隊(duì)列驅(qū)動(dòng)函數(shù)的狀態(tài) 0為初始狀態(tài) 1為通訊成功 2為通訊失敗GtBigBufferUsart.u8QueueStatus = 0; //隊(duì)列驅(qū)動(dòng)函數(shù)的通訊狀態(tài)GtBigBufferUsart.u8QueueSendTrig = 1; //隊(duì)列驅(qū)動(dòng)函數(shù)的發(fā)送的啟動(dòng)Gu8QueueReceUpdate = 1; //告訴“隊(duì)列驅(qū)動(dòng)函數(shù)”此發(fā)送指令無(wú)需等待上位機(jī)的應(yīng)答break;}Gu8FinishFlag = 0; //上面處理完數(shù)據(jù)再清零標(biāo)志,為下一次接收新的數(shù)據(jù)做準(zhǔn)備}}void UsartTask(void) //串口收發(fā)的任務(wù)函數(shù),放在主函數(shù)內(nèi){QueueSend(); //發(fā)送的隊(duì)列驅(qū)動(dòng)涵數(shù)ReceDataHandle(); //接收數(shù)據(jù)后的處理涵數(shù)}void usart(void) interrupt 4 //串口接發(fā)的中斷函數(shù),中斷號(hào)為4{if(1 == RI) //接收完一個(gè)字節(jié)后引起的中斷{RI = 0; //及時(shí)清零,避免一直無(wú)緣無(wú)故的進(jìn)入中斷。if(0 == Gu8FinishFlag) //1代表已經(jīng)完成接收了一串新數(shù)據(jù),并且禁止接收其它新的數(shù)據(jù){Gu8ReceFeedDog = 1; //每接收到一個(gè)字節(jié)的數(shù)據(jù),此標(biāo)志就置1及時(shí)更新定時(shí)器的值。switch(Gu8ReceStep){case 0: //“前部分的”數(shù)據(jù)頭。接頭暗號(hào)的步驟。Gu8ReceBuffer[0] = SBUF; //直接讀取剛接收完的一個(gè)字節(jié)的數(shù)據(jù)。if(0xeb == Gu8ReceBuffer[0]) //等于數(shù)據(jù)頭0xeb,接頭暗號(hào)吻合。{Gu32ReceCnt = 1; //接收緩存的下標(biāo)Gu8ReceStep = 1; //切換到下一個(gè)步驟,接收其它有效的數(shù)據(jù)}break;case 1: //“前部分的”數(shù)據(jù)類型和長(zhǎng)度Gu8ReceBuffer[Gu32ReceCnt] = SBUF; //直接讀取剛接收完的一個(gè)字節(jié)的數(shù)據(jù)。Gu32ReceCnt++; //每接收一個(gè)字節(jié),數(shù)組下標(biāo)都自加1,為接收下一個(gè)數(shù)據(jù)做準(zhǔn)備if(Gu32ReceCnt >= 6) //前6個(gè)數(shù)據(jù)。接收完了“數(shù)據(jù)類型”和“數(shù)據(jù)長(zhǎng)度”。{Gu8ReceType = Gu8ReceBuffer[1]; //提取“數(shù)據(jù)類型”//以下的數(shù)據(jù)轉(zhuǎn)換,在第62節(jié)講解過(guò)的指針?lè)?/span>pu32Data = (unsigned long *)&Gu8ReceBuffer[2]; //數(shù)據(jù)轉(zhuǎn)換Gu32ReceDataLength = *pu32Data; //提取“數(shù)據(jù)長(zhǎng)度”if(Gu32ReceCnt >= Gu32ReceDataLength) //靠“數(shù)據(jù)長(zhǎng)度”來(lái)判斷是否完成{Gu8FinishFlag = 1; //接收完成標(biāo)志“置1”,通知主函數(shù)處理。Gu8ReceStep = 0; //及時(shí)切換回接頭暗號(hào)的步驟}else //如果還沒(méi)結(jié)束,繼續(xù)切換到下一個(gè)步驟,接收“有效數(shù)據(jù)”{//本節(jié)只用到一個(gè)接收數(shù)組,把指針關(guān)聯(lián)到Gu8ReceBuffer本身的數(shù)組pGu8ReceBuffer = (unsigned char *)&Gu8ReceBuffer[6];Gu32ReceCntMax = REC_BUFFER_SIZE; //最大緩存Gu8ReceStep = 2; //切換到下一個(gè)步驟}}break;case 2: //“后部分的”數(shù)據(jù)pGu8ReceBuffer[Gu32ReceCnt - 6] = SBUF; //這里的指針就是各種不同內(nèi)存的化身!!!Gu32ReceCnt++; //每接收一個(gè)字節(jié),數(shù)組下標(biāo)都自加1,為接收下一個(gè)數(shù)據(jù)做準(zhǔn)備//靠“數(shù)據(jù)長(zhǎng)度”來(lái)判斷是否完成。也不允許超過(guò)數(shù)組的最大緩存的長(zhǎng)度if(Gu32ReceCnt >= Gu32ReceDataLength || Gu32ReceCnt >= Gu32ReceCntMax){Gu8FinishFlag = 1; //接收完成標(biāo)志“置1”,通知主函數(shù)處理。Gu8ReceStep = 0; //及時(shí)切換回接頭暗號(hào)的步驟}break;}}}else //發(fā)送數(shù)據(jù)引起的中斷{TI = 0; //及時(shí)清除發(fā)送中斷的標(biāo)志,避免一直無(wú)緣無(wú)故的進(jìn)入中斷。Gu8SendByteFinish = 1; //從0變成1通知主函數(shù)已經(jīng)發(fā)送完一個(gè)字節(jié)的數(shù)據(jù)了。}}void UsartSendByteData(unsigned char u8SendData) //發(fā)送一個(gè)字節(jié)的底層驅(qū)動(dòng)函數(shù){static unsigned int Su16TimeOutDelay; //超時(shí)處理的延時(shí)計(jì)時(shí)器Gu8SendByteFinish = 0; //在發(fā)送以字節(jié)之前,必須先把此全局變量的標(biāo)志清零。SBUF = u8SendData; //依靠寄存器SBUF作為載體發(fā)送一個(gè)字節(jié)的數(shù)據(jù)Su16TimeOutDelay = 0xffff; //超時(shí)處理的延時(shí)計(jì)時(shí)器裝載一個(gè)相對(duì)合理的計(jì)時(shí)初始值while(Su16TimeOutDelay > 0) //超時(shí)處理{if(1 == Gu8SendByteFinish){break; //如果Gu8SendByteFinish為1,則發(fā)送一個(gè)字節(jié)完成,退出當(dāng)前循環(huán)等待。}Su16TimeOutDelay--; //超時(shí)計(jì)時(shí)器不斷遞減}//Delay();//在實(shí)際應(yīng)用中,當(dāng)連續(xù)發(fā)送一堆數(shù)據(jù)時(shí)如果發(fā)現(xiàn)丟失數(shù)據(jù),可以嘗試在此增加延時(shí)}//發(fā)送帶協(xié)議的函數(shù)void UsartSendMessage(const unsigned char *pCu8SendMessage, unsigned long u32SendMaxSize){static unsigned long i;static unsigned long *pSu32;static unsigned long u32SendSize;pSu32 = (const unsigned long *)&pCu8SendMessage[2];u32SendSize = *pSu32; //從帶協(xié)議的數(shù)組中提取整包數(shù)組的有效發(fā)送長(zhǎng)度if(u32SendSize > u32SendMaxSize) //如果“有效發(fā)送長(zhǎng)度”大于“最大限制的長(zhǎng)度”,數(shù)據(jù)異常{return; //數(shù)據(jù)異常,直接退出當(dāng)前函數(shù),預(yù)防數(shù)組越界}for(i = 0; i < u32SendSize; i++) //u32SendSize為發(fā)送的數(shù)據(jù)長(zhǎng)度{UsartSendByteData(pCu8SendMessage[i]); //基于“發(fā)送單字節(jié)的最小接口函數(shù)”來(lái)實(shí)現(xiàn)的}}unsigned char CalculateXor(const unsigned char *pCu8Buffer, //此處加const代表數(shù)組“只讀”unsigned long u32BufferSize) //參與計(jì)算的數(shù)組的大小{unsigned long i;unsigned char Su8Rece_Xor;Su8Rece_Xor = pCu8Buffer[0]; //提取數(shù)據(jù)串第“i=0”個(gè)數(shù)據(jù)作為異或的原始數(shù)據(jù)for(i = 1; i < u32BufferSize; i++) //注意,這里是從第“i=1”個(gè)數(shù)據(jù)開(kāi)始{Su8Rece_Xor = Su8Rece_Xor ^ pCu8Buffer[i]; //計(jì)算“異或”}return Su8Rece_Xor; //返回運(yùn)算后的異或的計(jì)算結(jié)果}void T0_time() interrupt 1{if(1 == vGu8QueueSendTimerFlag && vGu16QueueSendTimerCnt > 0) //隊(duì)列發(fā)送的超時(shí)定時(shí)器{vGu16QueueSendTimerCnt--;}if(1 == vGu8ReceTimeOutFlag && vGu16ReceTimeOutCnt > 0) //通訊過(guò)程中字節(jié)之間的超時(shí)定時(shí)器{vGu16ReceTimeOutCnt--;}TH0 = 0xfc;TL0 = 0x66;}void SystemInitial(void){unsigned char u8_TMOD_Temp = 0;//以下是定時(shí)器0的中斷的配置TMOD = 0x01;TH0 = 0xfc;TL0 = 0x66;EA = 1;ET0 = 1;TR0 = 1;//以下是串口接收中斷的配置//串口的波特率與內(nèi)置的定時(shí)器1直接相關(guān),因此配置此定時(shí)器1就等效于配置波特率。u8_TMOD_Temp = 0x20; //即將把定時(shí)器1設(shè)置為:工作方式2,初值自動(dòng)重裝的8位定時(shí)器。TMOD = TMOD & 0x0f; //此寄存器低4位是跟定時(shí)器0相關(guān),高4位是跟定時(shí)器1相關(guān)。先清零定時(shí)器1。TMOD = TMOD | u8_TMOD_Temp; //把高4位的定時(shí)器1填入0x2,低4位的定時(shí)器0保持不變。TH1 = 256 - (11059200L / 12 / 32 / 9600); //波特率為9600。11059200代表晶振11.0592MHz,TL1 = 256 - (11059200L / 12 / 32 / 9600); //L代表long的長(zhǎng)類型數(shù)據(jù)。根據(jù)芯片手冊(cè)提供的計(jì)算公式。TR1 = 1; //開(kāi)啟定時(shí)器1SM0 = 0;SM1 = 1; //SM0與SM1的設(shè)置:選擇10位異步通訊,波特率根據(jù)定時(shí)器1可變REN = 1; //允許串口接收數(shù)據(jù)//為了保證串口中斷接收的數(shù)據(jù)不丟失,必須設(shè)置IP = 0x10,相當(dāng)于把串口中斷設(shè)置為最高優(yōu)先級(jí),//這個(gè)時(shí)候,串口中斷可以打斷任何其他的中斷服務(wù)函數(shù)實(shí)現(xiàn)嵌套,IP = 0x10; //把串口中斷設(shè)置為最高優(yōu)先級(jí),必須的。ES = 1; //允許串口中斷EA = 1; //允許總中斷}void Delay(unsigned long u32DelayTime){for(; u32DelayTime > 0; u32DelayTime--);}void PeripheralInitial(void){}
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!





