用51單片機設計了一拖二的控制系統一套。主機定時發送數據給從機,并要求從機回傳數據給主機。主機發送的數據為2個字節,第一個字節為地址,第二個為數據,從機回復的數據也一樣。主機將數據發送出去后,進行計時,在計時范圍內接收到數據,即完成收發通信,計時完成后,仍然無法收到數據,認為數據接收失敗。現在主機和從機之間通信正常.主,從機通信正常.從機設計了一個當無按鍵操作達到一定時間后,程序將進入一循環程序,一直執行循環程序,除非按下“喚醒”按鍵,程序跳出循環。現在程序好像無法進入循環,疑為通信程序影響所致。用STC-ISP的串口助手調試,將從機與電腦連接,點擊"發送緩沖區---自動發送,可以定時休眠,點擊"多字符串發送,勾選第1,2字符,此時就無法正常進入休眠狀態.目前無法分析出原因,更不要提如何修改。求哪位敬愛的大師給予指導。貼程序:
主機程序
- # include "config.h"
- void UartDriver(); //串口驅動函數
- void DelayX50ms(uchar8 t); //延時函數
- void ConfigTimer0(); //定時器配置函數,定時3ms.模式1
- void ConfigUART(); //串口配置函數
- void OCProtect(); //過流檢測函數
- void PowCheck(uchar8 t,uchar8 addr); // 供電檢測函數, 主機要發送給從機的數據
- void UartSend(uchar8 addr); //串口發送函數
- void DelayX10us(uchar8 t); //延時函數
- void UartReceive(); //串口接收函數
- void UartAction(uchar8 addr); //串口數據解析函數
- void LedDisp(uchar8 temp); //LED顯示函數
- void ReturnPos(uchar8 addr); //復位函數
- void UartRxMonitor(uchar8 ms); //總線監控函數
- uchar8 OCBuf[2];
- uchar8 RxdBuf[4];
- uchar8 TxdBuf[4];
- uchar8 buf[4];
- uchar8 cntRxd=0; //字節接收計數
- uchar8 PowCNTR=0; //供電檢測計數
- uchar8 PowSta=0xFF; //供電狀態存儲變量
- bit OCflag=0; //過流標志
- bit Txdflag=0; //字節發送完成標志
- bit TxFr_Succ=0; //幀發送完成標志
- 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; //數碼管全亮,檢測數碼管是否能正常亮起,并提示系統啟動
- DIR485=0;
- EA=1;
- ConfigTimer0();
- ConfigUART();
- while(1)
- {
- OCProtect();
- UartDriver();
- }
- }
- //串口驅動函數
- void UartDriver()
- {
- static uchar8 sl_select=1; //從機選擇索引
- switch(sl_select)
- {
- case 1:PowCheck(4,0x01); //檢測供電狀態,并發送
- if(RxFr_Succ) //從機數據接收成功標志
- {
- RxFr_Succ=0;
- UartReceive(); //串口讀取函數
- UartAction(0x01); //數據解析函數
- if((buf[1]<0x03)||(buf[1]>0x11)) //有按鍵按下,有數據
- {
- sl_select++;
- }
- }
- else if(RxFr_Fail) //從機數據接收失敗標志
- {
- 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)) //有按鍵按下,有數據
- {
- 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;
- }
- }
- //延時函數,延時時間為t*50ms
- void DelayX50ms(uchar8 t)
- {
- ........
- }
- //T0配置函數,模式1,3ms.
- void ConfigTimer0()
- {
- ...........
- }
- //串口配置函數, 方式1, 9600
- void ConfigUART()
- {
- ........................
- }
- //過流保護函數,
- void OCProtect()
- {
- ....................
- }
- //供電狀態檢測,并發送給從機,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); //將供電數據發送出去
- }
- }
- //串口發送函數
- void UartSend(uchar8 addr)
- {
- uchar8 len=0;
- DIR485=1;
- DelayX10us(2);
- TxdBuf[0]=addr; //將即要發送的地址裝入緩沖數組中
- for(;len<2;len++)
- {
- Txdflag=0;
- SBUF=TxdBuf[len];
- while(!Txdflag);
- DelayX10us(5);
- }
- DelayX10us(5);
- DIR485=0;
- //DelayX10us(5);
- TxFr_Succ=1; //幀發送完成標志
- }
- //延時10us函數
- void DelayX10us(uchar8 t)
- {
- ....................
- }
- //串口接收函數
- void UartReceive()
- {
- uchar8 len=0;
- while(len<2)
- {
- buf[len]=RxdBuf[len];
- len++;
- }
- cntRxd=0;
- }
- //串口接收數據解析函數,addr為發送地址
- void UartAction(uchar8 addr)
- {
- if(buf[0]!=addr) //地址解析,接收到的地址字節與發送地址不相同,
- { return; } //返回
- switch(buf[1]) //數據解析,解析接收到的數據字節
- {
- 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;
- }
- }
- //數碼管顯示函數
- void LedDisp(uchar8 temp)
- {
- .................
- }
- //復位函數
- void ReturnPos(uchar8 addr)
- {
- .......................
- }
- //串口接收監控函數,從發送完成后開始監控,監控的結果:1.接收成功,2.接收失敗
- void UartRxMonitor(uchar8 ms)
- {
- static uchar8 cntbkp=0;
- static uchar8 idletmr=0; //總線空閑時間
- if(TxFr_Succ) //幀發送成功后,才開始進行計時接收
- {
- if(cntRxd>0) //接收計數大于0,接收到字節,監控總線空閑時間
- {
- if(cntbkp!=cntRxd) //接收計數器改變,有新字節數據,清零總線空閑計數器
- {
- cntbkp=cntRxd;
- idletmr=0;
- }
- else //接收計數器不改變,沒有新字節數據,空閑計數器開始計數
- {
- if(idletmr<10) //小于20ms.
- {
- idletmr+=ms;
- if(idletmr>=10) //大于等于20ms
- {
- RxFr_Succ=1; //接收成功
- TxFr_Succ=0; //幀發送成功標志歸0,不再進行總線空閑監控
- idletmr=0;
- }
- }
- }
- }
- else //從機不在線,未接收到從機數據
- {
- cntbkp=0;
- if(idletmr<20)
- {
- idletmr+=ms;
- if(idletmr>=20)
- {
- RxFr_Fail=1; //接收失敗
- TxFr_Succ=0;
- idletmr=0;
- }
- }
- }
- }
- }
- //T0中斷函數
- void InterruptTimer0() interrupt 1
- {
- static uchar8 j=0;
- static uchar8 i=0;
- TH0=0xF5;
- TL0=0x33;
- OCBuf[0]=(OCBuf[0]<<1)|GL1; //第1路過流數據采集
- OCBuf[1]=(OCBuf[1]<<1)|GL2; //第2路過流數據采集
- 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讀取供電狀態一次
- j++;
- if(j>=8)
- {
- j=0;
- PowCNTR++;
- }
- UartRxMonitor(3); //UART空閑監控,
- }
- //串口中斷函數
- 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]; //讀取數組
- uchar8 TxdBuf[4]; //發送緩沖
- bit ScanKeyCNTR=0; //按鍵掃描索引
- uchar8 PowCNTR=0; //供電狀態采集計數
- uchar8 PowSta;
- uchar8 RxdBuf[4]; //接收緩沖
- uchar8 cntRxd=0; //接收計數
- uchar8 Cobuf=0xFF; //按鍵編碼緩沖
- bit flagFrame=0; //幀接收完成標志
- bit flagTxd=0; //字節接收完成標志
- void UartDriver(); //串口驅動函數
- void ConfigTimer0(); //T0配置函數,3ms,模式1
- void ConfigUART(); //UART配置函數,方式1
- void Delay60us(); //延時函數
- void ScanKey(); //按鍵掃描函數
- void KeyCode(); //按鍵編碼函數
- void SlpMode(); //休眠函數
- void UartReceive(); //串口接收函數
- void UartSend(uchar8 addr,uchar8 Txdata); //串口發送函數
- void UartRxMonitor(uchar8 ms); //總線監控函數
- void PowStaDisp(); //供電狀態監控函數
- 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();
- }
- }
- //串口驅動函數
- 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);
- }
- }
- //定時器配置函數
- void ConfigTimer0()
- {
- ................
- }
- //UART配置函數
- void ConfigUART()
- {
- ....................
- }
- //軟件延時函數
- void Delay60us() //?ó2? -0.049913194444us
- {
- ...........................
- }
- //讀取按鍵狀態函數
- void ScanKey()
- {
- ...................
- }
- //按鍵編碼函數,定時調用,執行
- void KeyCode()
- {
- ....................
- }
- //休眠函數
- 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;
- }
- }
- //串口接收函數
- void UartReceive()
- {
- uchar8 len=0;
- while(len<2)
- {
- buf[len]=RxdBuf[len];
- len++;
- }
- cntRxd=0;
- }
- //串口發送函數
- 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;
- }
- //串口接收監控函數,由空閑時間判斷幀接收是否完成,在T0中斷中調用,ms為定時間隔
- void UartRxMonitor(uchar8 ms)
- {
- static uchar8 cntbkp=0;
- static uchar8 idletmr=0;
- if(cntRxd>0) //接收計數大于0,監控總線空閑時間
- {
- if(cntbkp!=cntRxd) //接收計數器改變,有新字節數據,清零總線空閑計數器
- {
- cntbkp=cntRxd;
- idletmr=0;
- }
- else //接收計數器不改變,沒有新字節數據,空閑計數器開始計數
- {
- if(idletmr<10)
- {
- idletmr+=ms;
- if(idletmr>=10)
- {
- flagFrame=1;
- }
- }
- }
- }
- else
- {
- cntbkp=0;
- }
- }
- //供電狀態顯示函數,通過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中斷函數
- 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;
- }
- //串口中斷函數
- void InterruptUART() interrupt 4
- {
- if(RI)
- {
- RI=0;
- RxdBuf[cntRxd]=SBUF;
- cntRxd++;
- }
- if(TI)
- {
- TI=0;
- flagTxd=1;
- }
- }
復制代碼
|