用51單片機設計了一拖二的控制系統(tǒng)一套。主機定時發(fā)送數(shù)據(jù)給從機,并要求從機回傳數(shù)據(jù)給主機。主機發(fā)送的數(shù)據(jù)為2個字節(jié),第一個字節(jié)為地址,第二個為數(shù)據(jù),從機回復的數(shù)據(jù)也一樣。主機將數(shù)據(jù)發(fā)送出去后,進行計時,在計時范圍內(nèi)接收到數(shù)據(jù),即完成收發(fā)通信,計時完成后,仍然無法收到數(shù)據(jù),認為數(shù)據(jù)接收失敗。現(xiàn)在主機和從機之間通信正常.主,從機通信正常.從機設計了一個當無按鍵操作達到一定時間后,程序?qū)⑦M入一循環(huán)程序,一直執(zhí)行循環(huán)程序,除非按下“喚醒”按鍵,程序跳出循環(huán),F(xiàn)在程序好像無法進入循環(huán),疑為通信程序影響所致。用STC-ISP的串口助手調(diào)試,將從機與電腦連接,點擊"發(fā)送緩沖區(qū)---自動發(fā)送,可以定時休眠,點擊"多字符串發(fā)送,勾選第1,2字符,此時就無法正常進入休眠狀態(tài).目前無法分析出原因,更不要提如何修改。求哪位敬愛的大師給予指導。貼程序:
主機程序
- # include "config.h"
- void UartDriver(); //串口驅(qū)動函數(shù)
- void DelayX50ms(uchar8 t); //延時函數(shù)
- void ConfigTimer0(); //定時器配置函數(shù),定時3ms.模式1
- void ConfigUART(); //串口配置函數(shù)
- void OCProtect(); //過流檢測函數(shù)
- void PowCheck(uchar8 t,uchar8 addr); // 供電檢測函數(shù), 主機要發(fā)送給從機的數(shù)據(jù)
- void UartSend(uchar8 addr); //串口發(fā)送函數(shù)
- void DelayX10us(uchar8 t); //延時函數(shù)
- void UartReceive(); //串口接收函數(shù)
- void UartAction(uchar8 addr); //串口數(shù)據(jù)解析函數(shù)
- void LedDisp(uchar8 temp); //LED顯示函數(shù)
- void ReturnPos(uchar8 addr); //復位函數(shù)
- void UartRxMonitor(uchar8 ms); //總線監(jiān)控函數(shù)
- uchar8 OCBuf[2];
- uchar8 RxdBuf[4];
- uchar8 TxdBuf[4];
- uchar8 buf[4];
- uchar8 cntRxd=0; //字節(jié)接收計數(shù)
- uchar8 PowCNTR=0; //供電檢測計數(shù)
- uchar8 PowSta=0xFF; //供電狀態(tài)存儲變量
- bit OCflag=0; //過流標志
- bit Txdflag=0; //字節(jié)發(fā)送完成標志
- bit TxFr_Succ=0; //幀發(fā)送完成標志
- bit RxFr_Succ=0; //幀接收完成標志
- bit RxFr_Fail=0; //幀接收失敗標志
- main()
- {
- ROE=1;RA3=1;RA2=1;RA1=1; //釋放所有繼電器
- Buz=0;
- DelayX50ms(5);
- Buz=1; //蜂鳴器響
- P1=0x00;
- DelayX50ms(5);
- P1=0xFF; //數(shù)碼管全亮,檢測數(shù)碼管是否能正常亮起,并提示系統(tǒng)啟動
- DIR485=0;
- EA=1;
- ConfigTimer0();
- ConfigUART();
- while(1)
- {
- OCProtect();
- UartDriver();
- }
- }
- //串口驅(qū)動函數(shù)
- void UartDriver()
- {
- static uchar8 sl_select=1; //從機選擇索引
- switch(sl_select)
- {
- case 1:PowCheck(4,0x01); //檢測供電狀態(tài),并發(fā)送
- if(RxFr_Succ) //從機數(shù)據(jù)接收成功標志
- {
- RxFr_Succ=0;
- UartReceive(); //串口讀取函數(shù)
- UartAction(0x01); //數(shù)據(jù)解析函數(shù)
- if((buf[1]<0x03)||(buf[1]>0x11)) //有按鍵按下,有數(shù)據(jù)
- {
- sl_select++;
- }
- }
- else if(RxFr_Fail) //從機數(shù)據(jù)接收失敗標志
- {
- RxFr_Fail=0;
- buf[1]=0xFF;
- UartAction(0x01);
- //ROE=1;RA3=1;RA2=1;RA1=1; Dis_Pin=0xFF;
- sl_select++;
- }
- break;
- case 2:PowCheck(4,0x02);
- if(RxFr_Succ)
- {
- RxFr_Succ=0;
- UartReceive();
- UartAction(0x02);
- if((buf[1]<0x03)||(buf[1]>0x11)) //有按鍵按下,有數(shù)據(jù)
- {
- sl_select--;
- }
- }
- else if(RxFr_Fail)
- {
- RxFr_Fail=0;
- buf[1]=0xFF;
- UartAction(0x02);
- //ROE=1;RA3=1;RA2=1;RA1=1; Dis_Pin=0xE2;
- sl_select--;
- }
- break;
- default:sl_select=1;break;
- }
- }
- //延時函數(shù),延時時間為t*50ms
- void DelayX50ms(uchar8 t)
- {
- ........
- }
- //T0配置函數(shù),模式1,3ms.
- void ConfigTimer0()
- {
- ...........
- }
- //串口配置函數(shù), 方式1, 9600
- void ConfigUART()
- {
- ........................
- }
- //過流保護函數(shù),
- void OCProtect()
- {
- ....................
- }
- //供電狀態(tài)檢測,并發(fā)送給從機,t為檢測時間控制變量,addr為從機地址
- void PowCheck(uchar8 t,uchar8 addr)
- {
- if(PowCNTR>=t)
- {
- PowCNTR=0;
- if(PowSta==0xFF)
- {
- TxdBuf[1]=0x12; //DC供電
- }
- else if(PowSta==0x00)
- {
- TxdBuf[1]=0x13; //BAT供電
- }
- else;
- UartSend(addr); //將供電數(shù)據(jù)發(fā)送出去
- }
- }
- //串口發(fā)送函數(shù)
- void UartSend(uchar8 addr)
- {
- uchar8 len=0;
- DIR485=1;
- DelayX10us(2);
- TxdBuf[0]=addr; //將即要發(fā)送的地址裝入緩沖數(shù)組中
- for(;len<2;len++)
- {
- Txdflag=0;
- SBUF=TxdBuf[len];
- while(!Txdflag);
- DelayX10us(5);
- }
- DelayX10us(5);
- DIR485=0;
- //DelayX10us(5);
- TxFr_Succ=1; //幀發(fā)送完成標志
- }
- //延時10us函數(shù)
- void DelayX10us(uchar8 t)
- {
- ....................
- }
- //串口接收函數(shù)
- void UartReceive()
- {
- uchar8 len=0;
- while(len<2)
- {
- buf[len]=RxdBuf[len];
- len++;
- }
- cntRxd=0;
- }
- //串口接收數(shù)據(jù)解析函數(shù),addr為發(fā)送地址
- void UartAction(uchar8 addr)
- {
- if(buf[0]!=addr) //地址解析,接收到的地址字節(jié)與發(fā)送地址不相同,
- { return; } //返回
- switch(buf[1]) //數(shù)據(jù)解析,解析接收到的數(shù)據(jù)字節(jié)
- {
- case 0x03:ReturnPos(addr);break;
- case 0x04:ROE=0;RA3=0;RA2=0;RA1=0; LedDisp(1); break; //C1P為低電平
- case 0x05:ROE=0;RA3=0;RA2=1;RA1=0; LedDisp(2); break; //C2P向頭平移
- case 0x06:ROE=1;RA3=0;RA2=1;RA1=0; LedDisp(5); break; //C5P背板上升
- case 0x07:ROE=0;RA3=1;RA2=1;RA1=0; LedDisp(11);break; //1#Y6 剎車
- case 0x08:ROE=0;RA3=0;RA2=1;RA1=1; LedDisp(7); break; //C2N向腳平移
- case 0x09:ROE=1;RA3=0;RA2=1;RA1=1; LedDisp(10);break; //C5N背板下降
- case 0x0A:ROE=0;RA3=0;RA2=0;RA1=1; LedDisp(6); break; //C1N下降
- case 0x0B:ROE=1;RA3=1;RA2=0;RA1=0; LedDisp(13);break; //2#Y4 腰升
- case 0x0C:ROE=1;RA3=0;RA2=0;RA1=0; LedDisp(4); break; //C4P左傾
- case 0x0D:ROE=0;RA3=1;RA2=1;RA1=1; LedDisp(12);break; //1#Y7 松剎車
- case 0x0E:ROE=0;RA3=1;RA2=0;RA1=1; LedDisp(8); break; //C3N頭降腳升
- case 0x0F:ROE=1;RA3=1;RA2=0;RA1=1; LedDisp(14);break; //2#Y5 腰降
- case 0x10:ROE=0;RA3=1;RA2=0;RA1=0; LedDisp(3); break; //C3P頭升腳降
- case 0x11:ROE=1;RA3=0;RA2=0;RA1=1; LedDisp(9); break; //C4N右傾
- case 0xFF:ROE=1;RA3=1;RA2=1;RA1=1; Dis_Pin=0xFF;break; //釋放所有繼電器
- default:ROE=1;RA3=1;RA2=1;RA1=1;Dis_Pin=0xFF;break;
- }
- }
- //數(shù)碼管顯示函數(shù)
- void LedDisp(uchar8 temp)
- {
- .................
- }
- //復位函數(shù)
- void ReturnPos(uchar8 addr)
- {
- .......................
- }
- //串口接收監(jiān)控函數(shù),從發(fā)送完成后開始監(jiān)控,監(jiān)控的結果:1.接收成功,2.接收失敗
- void UartRxMonitor(uchar8 ms)
- {
- static uchar8 cntbkp=0;
- static uchar8 idletmr=0; //總線空閑時間
- if(TxFr_Succ) //幀發(fā)送成功后,才開始進行計時接收
- {
- if(cntRxd>0) //接收計數(shù)大于0,接收到字節(jié),監(jiān)控總線空閑時間
- {
- if(cntbkp!=cntRxd) //接收計數(shù)器改變,有新字節(jié)數(shù)據(jù),清零總線空閑計數(shù)器
- {
- cntbkp=cntRxd;
- idletmr=0;
- }
- else //接收計數(shù)器不改變,沒有新字節(jié)數(shù)據(jù),空閑計數(shù)器開始計數(shù)
- {
- if(idletmr<10) //小于20ms.
- {
- idletmr+=ms;
- if(idletmr>=10) //大于等于20ms
- {
- RxFr_Succ=1; //接收成功
- TxFr_Succ=0; //幀發(fā)送成功標志歸0,不再進行總線空閑監(jiān)控
- idletmr=0;
- }
- }
- }
- }
- else //從機不在線,未接收到從機數(shù)據(jù)
- {
- cntbkp=0;
- if(idletmr<20)
- {
- idletmr+=ms;
- if(idletmr>=20)
- {
- RxFr_Fail=1; //接收失敗
- TxFr_Succ=0;
- idletmr=0;
- }
- }
- }
- }
- }
- //T0中斷函數(shù)
- void InterruptTimer0() interrupt 1
- {
- static uchar8 j=0;
- static uchar8 i=0;
- TH0=0xF5;
- TL0=0x33;
- OCBuf[0]=(OCBuf[0]<<1)|GL1; //第1路過流數(shù)據(jù)采集
- OCBuf[1]=(OCBuf[1]<<1)|GL2; //第2路過流數(shù)據(jù)采集
- if((OCBuf[0]==0x00)||(OCBuf[1]==0x00)) //有過流
- {
- i++;
- OCBuf[0]=0xFF;
- OCBuf[1]=0xFF;
- if(i>=2)
- {
- i=0;
- OCflag=1; //過流標志
- }
- }
- PowSta=(PowSta<<1)|DcBat; //每隔2ms讀取供電狀態(tài)一次
- j++;
- if(j>=8)
- {
- j=0;
- PowCNTR++;
- }
- UartRxMonitor(3); //UART空閑監(jiān)控,
- }
- //串口中斷函數(shù)
- void InterruptUART() interrupt 4
- {
- if(RI)
- {
- RI=0;
- RxdBuf[cntRxd]=SBUF;
- cntRxd++;
- }
- if(TI)
- {
- TI=0;
- Txdflag=1;
- }
- }
復制代碼
從機程序
- # include "config.h"
- uint16 KeyBuf=0x0000; //按鍵緩沖
- uint16 SlpCNTR=0x0000; //休眠索引
- //uchar8 Slpbuf=0xFF; //休眠喚醒緩沖
- uchar8 buf[4]; //讀取數(shù)組
- uchar8 TxdBuf[4]; //發(fā)送緩沖
- bit ScanKeyCNTR=0; //按鍵掃描索引
- uchar8 PowCNTR=0; //供電狀態(tài)采集計數(shù)
- uchar8 PowSta;
- uchar8 RxdBuf[4]; //接收緩沖
- uchar8 cntRxd=0; //接收計數(shù)
- uchar8 Cobuf=0xFF; //按鍵編碼緩沖
- bit flagFrame=0; //幀接收完成標志
- bit flagTxd=0; //字節(jié)接收完成標志
- void UartDriver(); //串口驅(qū)動函數(shù)
- void ConfigTimer0(); //T0配置函數(shù),3ms,模式1
- void ConfigUART(); //UART配置函數(shù),方式1
- void Delay60us(); //延時函數(shù)
- void ScanKey(); //按鍵掃描函數(shù)
- void KeyCode(); //按鍵編碼函數(shù)
- void SlpMode(); //休眠函數(shù)
- void UartReceive(); //串口接收函數(shù)
- void UartSend(uchar8 addr,uchar8 Txdata); //串口發(fā)送函數(shù)
- void UartRxMonitor(uchar8 ms); //總線監(jiān)控函數(shù)
- void PowStaDisp(); //供電狀態(tài)監(jiān)控函數(shù)
- void main()
- {
- P3M1=0x00;
- P3M0=0x40;
- P1M1=0x00;
- P1M0=0x03;
- _nop_();_nop_();
- SleepDisp=1;
- _nop_();_nop_();
- PowDisp=0;
- DIR_485=0;
- ConfigTimer0();
- ConfigUART();
- while(1)
- {
- if(ScanKeyCNTR)
- {
- ScanKeyCNTR=0;
- ScanKey();
- KeyCode();
- }
- SlpMode();
- PowStaDisp();
- UartDriver();
- }
- }
- //串口驅(qū)動函數(shù)
- void UartDriver()
- {
- if(flagFrame)
- {
- flagFrame=0;
- UartReceive();
- if(buf[0]!=0x01)
- {
- return;
- }
- switch(buf[1])
- {
- case 0x12:PowSta=buf[1];break;
- case 0x13:PowSta=buf[1];break;
- default:break;
- }
- UartSend(buf[0],Cobuf);
- }
- }
- //定時器配置函數(shù)
- void ConfigTimer0()
- {
- ................
- }
- //UART配置函數(shù)
- void ConfigUART()
- {
- ....................
- }
- //軟件延時函數(shù)
- void Delay60us() //?ó2? -0.049913194444us
- {
- ...........................
- }
- //讀取按鍵狀態(tài)函數(shù)
- void ScanKey()
- {
- ...................
- }
- //按鍵編碼函數(shù),定時調(diào)用,執(zhí)行
- void KeyCode()
- {
- ....................
- }
- //休眠函數(shù)
- void SlpMode()
- {
- if(SlpCNTR>=SleepTime)
- {
- while(Wake_up!=0)
- {
- SlpCNTR=0; //休眠燈亮
- SleepDisp=0;
- PowStaDisp();
- if(flagFrame)
- {
- flagFrame=0;
- UartReceive();
- if(buf[0]!=0x01)
- {
- return;
- }
- switch(buf[1])
- {
- case 0x12:PowSta=buf[1];break;
- case 0x13:PowSta=buf[1];break;
- default:break;
- }
- UartSend(buf[0],0xFF);
- }
- }
- SleepDisp=1;
- }
- }
- //串口接收函數(shù)
- void UartReceive()
- {
- uchar8 len=0;
- while(len<2)
- {
- buf[len]=RxdBuf[len];
- len++;
- }
- cntRxd=0;
- }
- //串口發(fā)送函數(shù)
- void UartSend(uchar8 addr,uchar8 Txdata)
- {
- uchar8 len=0;
- DIR_485=1;
- TxdBuf[0]=addr;
- TxdBuf[1]=Txdata;
- for(;len<2;len++)
- {
- flagTxd=0;
- SBUF=TxdBuf[len];
- while(!flagTxd);
- Delay60us();
- }
- Delay60us();
- DIR_485=0;
- }
- //串口接收監(jiān)控函數(shù),由空閑時間判斷幀接收是否完成,在T0中斷中調(diào)用,ms為定時間隔
- void UartRxMonitor(uchar8 ms)
- {
- static uchar8 cntbkp=0;
- static uchar8 idletmr=0;
- if(cntRxd>0) //接收計數(shù)大于0,監(jiān)控總線空閑時間
- {
- if(cntbkp!=cntRxd) //接收計數(shù)器改變,有新字節(jié)數(shù)據(jù),清零總線空閑計數(shù)器
- {
- cntbkp=cntRxd;
- idletmr=0;
- }
- else //接收計數(shù)器不改變,沒有新字節(jié)數(shù)據(jù),空閑計數(shù)器開始計數(shù)
- {
- if(idletmr<10)
- {
- idletmr+=ms;
- if(idletmr>=10)
- {
- flagFrame=1;
- }
- }
- }
- }
- else
- {
- cntbkp=0;
- }
- }
- //供電狀態(tài)顯示函數(shù),通過PowSta的值進行判斷,PowSta的值來自串口接收
- void PowStaDisp()
- {
- if(PowSta==0x12)
- {
- if(PowCNTR>=5)
- {
- PowCNTR=0;
- PowDisp=(!PowDisp);
- }
- }
- else if(PowSta==0x13)
- {
- if(PowCNTR>=160)
- {
- PowCNTR=0;
- PowDisp=(!PowDisp); //LED燈每400ms亮滅一次
- }
- }
- }
- //T0中斷函數(shù)
- void InterruptTimer0() interrupt 1
- {
- TH0=0xF5;
- TL0=0x33;
- ScanKeyCNTR=(!ScanKeyCNTR); //按鍵掃描索引+1
- if(KeyBuf==0xFFFF)
- {
- SlpCNTR++;
- }
- else
- {
- SlpCNTR=0;
- }
- PowCNTR++;
- UartRxMonitor(3);
- //Slpbuf=(Slpbuf<<1)|Wake_up;
- }
- //串口中斷函數(shù)
- void InterruptUART() interrupt 4
- {
- if(RI)
- {
- RI=0;
- RxdBuf[cntRxd]=SBUF;
- cntRxd++;
- }
- if(TI)
- {
- TI=0;
- flagTxd=1;
- }
- }
復制代碼
|