日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]點(diǎn)擊上方嵌入式開(kāi)發(fā)圈?記得關(guān)注我們哦! 【134.1 ??應(yīng)用層的“半雙工”和“全雙工”?!?? ?? ? 應(yīng)用層的“半雙工”。主機(jī)與從機(jī)在程序應(yīng)用層采用“一問(wèn)一答”的查詢模式,主機(jī)是主動(dòng)方,從機(jī)是被動(dòng)方,主機(jī)問(wèn)一句從機(jī)答一句,“聊天對(duì)話“的氛圍很無(wú)趣很呆板

點(diǎn)擊上方嵌入式開(kāi)發(fā)圈 記得關(guān)注我們哦!

【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>

#include "REG52.H"
#define RECE_TIME_OUT 2000 //通訊過(guò)程中字節(jié)之間的超時(shí)時(shí)間2000ms#define REC_BUFFER_SIZE 30 //常規(guī)控制類數(shù)組的長(zhǎng)度#define KEY_FILTER_TIME 25 //按鍵濾波的“穩(wěn)定時(shí)間”
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í)器1
SM0 = 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ù)。

#include "REG52.H"
#define RECE_TIME_OUT 2000 //通訊過(guò)程中字節(jié)之間的超時(shí)時(shí)間2000ms#define REC_BUFFER_SIZE 30 //常規(guī)控制類數(shù)組的長(zhǎng)度
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í)器1
SM0 = 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){
}

韋東山嵌入式視頻






商務(wù)合作


支持我請(qǐng)給我在看!


免責(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)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關(guān)閉