当前位置:文档之家› 串口通信协议程序

串口通信协议程序

主机程序:/*主机主要处理:主—>从 1.给从机发送命令2.给从机发送数据3.命令从机向主机发送数据从—>主由中断程序处理根据从机发送过来的请求类型0.请求主机发送命令(包括主到从的1,2命令)1.请求主机接收数据2,3保留*/#include<reg51.h>#include <string.h>#define uchar unsigned char#define uint unsigned int#define slav1_addr 0x01#define slav2_addr 0x02#define COMEND 0#define REC_DATE 1//主机向从机发送多数据命令高四位为1111,所以其他命令高四位不能为1111#define cmd_X 0x12#define cmd_rec_data 0x11sbit signal=P3^2;uchar temp_addr,num,rec,style,re_addr;uchar buf[20];uchar rec_data[10];void delay(unsigned int i){while(i--);}void init_uart(void){TMOD=0x20; //定时器方式2--8位reload模式TH1=0xfd;TL1=0xfd;PCON=0; //波特率不加倍SCON=0xf0; //方式三TB8=1; //发送地址时第九位为1SM2=1; //接收到第九位为1时才能接收数据TR1=1; //要在设置scon后开定时ES=1; //开中断EA=1;}//发送命令void uart_send_cmd(uchar addr,uchar cmd)//uchar *date){while(signal==0); //检查总线是否被占signal=0; //占用总线EA=0;//关中断do{do{SBUF=addr; //发送从机地址while(TI!=1);TI=0;}while(RI!=1); //一直等待从机响应//while循环里可加入出错处理temp_addr=SBUF;RI=0;}while(temp_addr!=addr); //一直等到从机回应的地址相同//while循环里可加入出错处理TB8=0; //发送数据第9位为0// SM2=0; // 接收到第九位为1时才置位RI//每次一个数据SBUF=cmd;while(TI!=1);TI=0;TB8=1;// SM2=1;RI=0;TI=0; //不处理期间发生的中断EA=1;signal=1; //释放总线}//主机向从机发送多数据//自动计算发送数据长度void uart_send_data(uchar addr,uchar *date){uchar n;while(signal==0); //检查总线是否被占signal=0; //占用总线EA=0; //关中断do{do{SBUF=addr; //发送从机地址while(TI!=1);TI=0;}while(RI!=1); //一直等待从机响应//while循环里可加入出错处理temp_addr=SBUF;RI=0;}while(temp_addr!=addr); //一直等到从机回应的地址相同//while循环里可加入出错处理TB8=0; //发送数据第9位为1SM2=0; // 接收到第九位为1时才置位RInum=strlen(date);SBUF=(0xf0|num); //向从机发送接收多数据命令//高四位为标志位低四位为数据长度while(TI!=1);TI=0;delay(200) ; //等待从机能稳定(从机产生接收中断需要时间) for(n=0;n<num;n++) //发送多个数据{SBUF=date[n];while(TI!=1);TI=0;delay(2) ; //放慢发送速度使从机能稳定接收}TB8=1;SM2=1;RI=0;TI=0; //不处理期间发生的中断EA=1;signal=1;}//主机请求从机发送数据过来void cmd_rec(uchar addr ){uchar numb,n;while(signal==0); //检查总线是否被占signal=0; //占用总线EA=0;//关中断do{do{SBUF=addr; //发送从机地址while(TI!=1);TI=0;}while(RI!=1); //一直等待从机响应//while循环里可加入出错处理temp_addr=SBUF;RI=0;}while(temp_addr!=addr); //一直等到从机回应的地址相同//while循环里可加入出错处理TB8=0; //发送数据第9位为1SM2=0; // 接收到第九位为1时才置位RI//每次一个数据SBUF=cmd_rec_data; //发送命令while(TI!=1);TI=0;while(RI!=1); //接收要受到数据的个数RI=0;numb=SBUF;for(n=0;n<numb;n++) //接收数据{while(RI!=1);RI=0;rec_data[n]=SBUF;}TB8=1;SM2=1;RI=0;TI=0; //不处理期间发生的中断EA=1;signal=1;}void main(void){init_uart();signal=1; //初始化总线状态buf[0]=1; buf[1]=1; b uf[2]=1; buf[3]=5;uart_send_cmd(slav1_addr,0x55);uart_send_cmd(slav2_addr,0x77);uart_send_data(slav1_addr,buf);cmd_rec(slav1_addr);P1=rec_data[3];while(1);}/*处理从机的数据请求0 请求主机发送命令1 请求主机接收数据*/void series() interrupt 4{if(RI==1){RI=0;rec=SBUF; //从机发送数据时SM2=0 从机发送的数据不能与其他从机地址相同//接收到的数据低6位为从机地址高2位为向主机请求的命令类型style=(rec>>6); //取出数据类型位命令请求or 数据请求re_addr= (rec&0x3f); //取出地址位if(style==COMEND) //从机向主机发送命令请求{uart_send_cmd(re_addr,cmd_X); //or uart_send_data(re_addr,buf);}else if(style==REC_DA TE) //从机向主机发送数据请求{cmd_rec(re_addr ) ;}}}从机程序#include<reg51.h>#include <string.h>#define uchar unsigned char#define uint unsigned int#define slav1_addr 0x01#define cmd_rec_data 0x11sbit signal=P3^2;uchar date[10];uchar send_buf[10];uchar n,cmd_res_mul_data_flag,temp;uchar temp_addr=0,data_flag=0,sbuf_code=0;void delay(unsigned int i){while(--i);}void cmd_to_mast(uchar cmd_mast){while(signal==0); //检查总线是否被占signal=0; //占用总线}void init_uart(void){TMOD=0x20; //定时器方式2--8位reload模式TH1=0xfd;TL1=0xfd;PCON=0; //波特率不加倍SCON=0xf0;SM2=1;TB8=1;TR1=1;ES=1;EA=1;}void dill_cmd_rec_data(uchar *date){uchar n,num;SM2=0;TB8=0;EA=0;num=strlen(date);SBUF=num;while(TI!=1);TI=0; //发送数据的个数delay(20); //等待主机接收到for(n=0;n<num;n++) //发送多个数据{SBUF=date[n];while(TI!=1);TI=0;delay(2) ; //放慢发送速度使主机能稳定接收}SM2=1;TB8=1;EA=1;}void main(void){init_uart();signal=1;send_buf[0]=1;send_buf[1]=4;send_buf[2]=2;send_buf[3]=5;{P1=sbuf_code;P2=date[3];if(sbuf_code==cmd_rec_data)//向主机发送数据{dill_cmd_rec_data(send_buf);sbuf_code=0; //记得命令清零}}}void uart_isr() interrupt 4{if(RI==1){RI=0;temp_addr=SBUF;if(data_flag==1) //必须在前面判断,发送的数据可能与地址相同{ //// sbuf_code=temp_addr;if((temp_addr&0xf0)==0xf0) //收到接收多数据命令{ //高四位为标志位低四位为数据长度temp=(sbuf_code&0x0f);for(n=0;n<temp;n++){while(RI!=1);RI=0;date[n]=SBUF;}data_flag=0; //多数据通信时可通过判断通信结束位来置零data_flagSM2=1;TB8=1;}else //接收到的是普通命令{sbuf_code=temp_addr;data_flag=0; //多数据通信时可通过判断通信结束位来置零data_flagSM2=1;}else if(temp_addr==slav1_addr){EA=0; //关中断REN=0; //停止接收防止主机的多次从发造成的多次中断SBUF=slav1_addr;while(TI!=1);TI=0;EA=1;SM2=0; //无论第九位0或者1都能接收// TB8=0; //准备接收REN=1;data_flag=1; //接收数据标志位置位RI=0; //再次清零中断标志防止主机的多次从发造成的多次中断} //虽然多次发过来的地址不会对主机发过来的数据产生影响(SM2已置位),但会产生中断}}。

相关主题