用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;
- }
- }
复制代码
|