下面是我一个项目里的通讯程序,没有用环形缓冲区,可能会出现没及时处理的命令被覆盖的问题,如果我改用环形缓冲区的话,怎样存取和判断处理比较方便呢,下面是通讯协议: 通讯格式:
帧起始苻 | 帧长度 | 命令字 | 数据项 | | 68H 单字节 | 单字节 | xxH 单字节 | DATA 不定 | |
因为每帧命令的字节数不一样,中断里网环形缓冲区里存的时候没什么问题,但通讯处理函数从缓冲区里取命令的时候就会有一定问题,指针不容易维护,而且一旦某次读出错,那以后的全部都错,我只是说一下我这个程序容易出现的问题,请大家在这里谈论一个通用性强的,结构清晰的通讯程序架构 /*------------------------------------------------------------------------------------------------** **************************************************************************************************** **------------------------------------------------------------------------------------------------** ** com.c 通讯相关程序 **------------------------------------------------------------------------------------------------** **************************************************************************************************** **------------------------------------------------------------------------------------------------*/
//---------------------------- //通讯处理 //---------------------------- void com_cl() { if(recv_end!=1)return; recv_end=0; switch(recv_buf[0]) {
/*------------------------------------------------------------------------------------------------*/ //调试命令区 case 0xD0: if(recv_buf[1]==0x00) { getdatm(); send0(); } else { switch(recv_buf[2]&0xc0) { case 0x00:get7028(recv_buf[2],recv_buf[1]); send0(); break; case 0x80:write7028(recv_buf[2],recv_buf[1],recv_buf+3);break; case 0xc0: break; default: break; } } break; case 0xD1: switch(recv_buf[1]&0x80) { case 0x00:geteeprom(); send0(); break; case 0x80:writeeeprom(recv_buf[2],recv_buf+3,recv_buf[1]&0x7f);break; default : break; } break; case 0xD2: dysdz=bcdtoint(recv_buf+1); break; case 0xD3: tiaoya(); break; case 0xD8: if(recv_buf[1]==0x88) reset485(); else { send1_add(recv_buf[1]); Delay(1000); xxzz(); send1(); } break; /*------------------------------------------------------------------------------------------------*/ //电源控制命令区 case 0xA0: //复位电源 reset_dy(); break; case 0xA1: //设置电压电流输入输出状态 if(recv_buf[1]==0) kg_flag=0x77; else { if(recv_buf[1]==1) kg_flag=1; else if(recv_buf[1]==2) kg_flag=2; else if(recv_buf[1]==3) kg_flag=4; else if(recv_buf[1]==4) kg_flag=16; else if(recv_buf[1]==5) kg_flag=32; else if(recv_buf[1]==6) kg_flag=64; } if(recv_buf[2]==1) { u_out(kg_flag,u_fd); i_out(); } else if(recv_buf[2]==0) { u_shut(); i_shut(); } break; case 0xA2: //设置相位 xw[0]=recv_buf[1]; xw[1]=recv_buf[2]; xw[3]=recv_buf[3]; break; case 0xA3: //设置电压档位和幅度 u_dw=recv_buf[1]; u_fd[0]=recv_buf[2]; u_fd[1]=recv_buf[3]; dydw(); break; case 0xA4: //设置电流档位和幅度 i_dw=recv_buf[1]; i_fd[0]=recv_buf[2]; i_fd[1]=recv_buf[3]; dldw(); break; case 0xA5: //对称度调整 dcd_adjust(); break; case 0xA6: //电压粗调 break; case 0xA7: //电流粗调 break; case 0xA8: //电压细调 break; case 0xA9: //电流细调 break;
/*------------------------------------------------------------------------------------------------*/ //信息索取命令区 case 0xB0: //索取低压信息 getdatm(); send0(); break; case 0xB4: //索取通讯校验状态 break; /*------------------------------------------------------------------------------------------------*/ //返回信息区 case 0xB1: //返回高压信息 switch(recv_buf[2]) { case 1:u_bz[0]=ctof(recv_buf+3); u_bz[1]=ctof(recv_buf+7); u_bz[2]=ctof(recv_buf+11); u_bz_new=1; break; case 2:i_bz[0]=ctof(recv_buf+3); i_bz[1]=ctof(recv_buf+7); i_bz[2]=ctof(recv_buf+11); i_bz_new=1; break; case 3:xw_bz[0]=ctof(recv_buf+3); xw_bz[1]=ctof(recv_buf+7); xw_bz[2]=ctof(recv_buf+11); xw_bz[3]=ctof(recv_buf+15); xw_bz[4]=ctof(recv_buf+19); xw_bz_new=1; break; default: break; }
break; /*------------------------------------------------------------------------------------------------*/ //辅助命令区 case 0xC4: //信息重新发送命令 send0(); break; default : break; } } //---------------------------- //初始化串口及定时器 //---------------------------- void init(void) { TMOD=0x21; TH0=0x00; TL0=0x00; TH1=0xfd; TL1=0xfd; PCON=0x00; TR1=1; SCON0=0x50; SCON1=0xd0; //UART1工作于方式3,用于多机通讯 ES0=1; ES1=1; ET0=1; EA=1; } //---------------------------- //串口0发送 //---------------------------- void send0() { uchar i; EA=0; SBUF0=0x68; while(TI==0);TI=0; for(i=0;i<=send0_buf[0];i++) { SBUF0=send0_buf; while(TI==0);TI=0; } EA=1; } //---------------------------- //串口0中断 //---------------------------- void int232_0(void) interrupt 4 using 0 { uchar a; ES0=0; if(RI==1) { RI=0; a=SBUF0; if(recv_long==0) { if(a==0x68) recv_start=1; else if(recv_start==1)recv_long=a; } else { if(recv_start==1) { recv_buf[recv_zz]=a; recv_zz=recv_zz+1; recv_long=recv_long-1; if(recv_long==0) { recv_end=1; recv_zz=0; recv_start=0; } } else recv_long=recv_long-1; } } ES0=1; } |