一、多機通信原理
在多機通信中,主機必須要能對各個從機進行識別,在51系列單片機中可以通過SCON寄存器的SM2位來實現。當串口以方式2或方式3發送數據時,每一幀信息都是11位,第9位是數據可編程位,通過給TB8置1或置0來區別地址幀和數據幀,當該位為1時,發送地址幀;該位為0時,發送數據幀。
在多機通信過程中,主機先發送某一從機的地址,等待從機的應答,所有的從機接收到地址幀后與本機地址進行比較,若相同,則將SM2置0準備接收數據;若不同,則丟棄當前數據,SM2位不變。
二、多機通信電路圖
此處,U1作為主機,U2為從機1,U3為從機2。
三、C語言程序
(1)主機程序
#include#include
#define _SUCC_0x0f//數據傳送成功#define _ERR_0xf0//數據傳送失敗unsigned char Table[9]={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};unsigned char Buff[20];//數據緩沖區unsigned char temp=0xff;sbit KEY1=P1^6;sbit KEY2=P1^7;//unsigned char addr;
//延時1ms函數void delay_1ms(unsigned int t){unsigned int x,y;for(x=t;x>0;x--)for(y=110;y>0;y--);}//緩沖區初始化void Buff_init(){unsigned char i;//將Table里的數據放到緩沖區里for(i=0;i<9;i++)???{??Buff[i]= Table[i];??delay_1ms(100);?}?}//串口初始化函數void serial_init(){?TMOD=0x20;?//定時器1工作于方式2?TH1=0xfd;???TL1=0xfd;?//波特率為9600?PCON=0;?SCON=0xd0;??//串口工作于方式3?TR1=1;??//開啟定時器?TI=0;?RI=0;}//發送數據函數void SEND_data(unsigned char *Buff){?unsigned char i;?unsigned char lenth;?unsigned char check;?lenth=strlen(Buff);??????//計算數據長度?check=lenth;
TI=0;//發送數據長度TB8=0;//發送數據幀SBUF=lenth;while(!TI);TI=0;for(i=0;i;i++)>
TB8=0;//發送校驗字節SBUF=check;while(!TI);TI=0;}//向指定從機地址發送數據void ADDR_data(unsigned addr){while(temp!=addr)//主機等待從機返回其地址作為應答信號{TI=0;//發送從機地址TB8=1;//發送地址幀SBUF=addr;while(!TI);TI=0;RI=0;while(!RI);temp=SBUF;RI=0;}
temp=_ERR_;//主機等待從機數據接收成功信號while(temp!=_SUCC_){SEND_data(Buff);RI=0;while(!RI);temp=SBUF;RI=0;}}
void main(){Buff_init();serial_init();while(1){if(KEY1==0){delay_1ms(5);if(KEY1==0){while(!KEY1);ADDR_data(0x01);}}if(KEY2==0){delay_1ms(5);if(KEY2==0){while(!KEY2);ADDR_data(0x02);}}
}}
(2)從機1程序
#include#include
#define addr0x01//從機1的地址#define _SUCC_0x0f//數據傳送成功#define _ERR_0xf0//數據傳送失敗unsigned char aa=0xff;//主機與從機之間通信標志unsigned char Buff[20];//數據緩沖區
//串口初始化函數void serial_init(){TMOD=0x20;//定時器1工作于方式2TH1=0xfd;TL1=0xfd;//波特率為9600PCON=0;SCON=0xd0;//串口工作于方式3TR1=1;//開啟定時器TI=0;RI=0;}//接收數據函數unsigned char RECE_data(unsigned char *Buff){unsigned char i,temp;unsigned char lenth;unsigned char check;
RI=0;//接收數據長度while(!RI);if(RB8==1)//若接收到地址幀,則返回0xfereturn 0xfe;lenth=SBUF;RI=0;check=lenth;for(i=0;i;i++)>
while(!RI);//接收校驗字節if(RB8==1)//若接收到地址幀,則返回0xfereturn 0xfe;temp=SBUF;RI=0;check=temp^check;//將從主機接收到的校驗碼與自己計算的校驗碼比對if(check!=0)//校驗碼不一致,表明數據接收錯誤,向主機發送錯誤信號,函數返回0xff{TI=0;TB8=0;SBUF=_ERR_;while(!TI);TI=0;return 0xff;}TI=0;//校驗碼一致,表明數據接收正確,向主機發送成功信號,函數返回0x00TB8=0;SBUF=_SUCC_;while(!TI);TI=0;return 0;}
void main(){serial_init();while(1){SM2=1;//接收地址幀while(aa!=addr)//從機等待主機請求自己的地址{RI=0;while(!RI);aa=SBUF;RI=0;}
TI=0;//一旦被請求,從機返回自己的地址作為應答,等待接收數據TB8=0;SBUF=addr;while(!TI);TI=0;
SM2=0;//接收數據幀aa=0xff;//從機接收數據,并將數據保存到數據緩沖區while(aa==0xff){aa=RECE_data(Buff);}if(aa==0xfe)continue;P1=Buff[1];//查看接收到的數據}}
(3)從機2程序
#include#include
#define addr0x02//從機2的地址#define _SUCC_0x0f//數據傳送成功#define _ERR_0xf0//數據傳送失敗unsigned char aa=0xff;//主機與從機之間通信標志unsigned char Buff[20];//數據緩沖區
//串口初始化函數void serial_init(){TMOD=0x20;//定時器1工作于方式2TH1=0xfd;TL1=0xfd;//波特率為9600PCON=0;SCON=0xd0;//串口工作于方式3TR1=1;//開啟定時器TI=0;RI=0;}//接收數據函數unsigned char RECE_data(unsigned char *Buff){unsigned char i,temp;unsigned char lenth;unsigned char check;
RI=0;//接收數據長度while(!RI);if(RB8==1)//若接收到地址幀,則返回0xfereturn 0xfe;lenth=SBUF;RI=0;check=lenth;for(i=0;i;i++)>
while(!RI);//接收校驗字節if(RB8==1)//若接收到地址幀,則返回0xfereturn 0xfe;temp=SBUF;RI=0;check=temp^check;//將從主機接收到的校驗碼與自己計算的校驗碼比對if(check!=0)//校驗碼不一致,表明數據接收錯誤,向主機發送錯誤信號,函數返回0xff{TI=0;TB8=0;SBUF=_ERR_;while(!TI);TI=0;return 0xff;}TI=0;//校驗碼一致,表明數據接收正確,向主機發送成功信號,函數返回0x00TB8=0;SBUF=_SUCC_;while(!TI);TI=0;return 0;}
void main(){serial_init();while(1){SM2=1;//接收地址幀while(aa!=addr)//從機等待主機請求自己的地址{RI=0;while(!RI);aa=SBUF;RI=0;}
TI=0;//一旦被請求,從機返回自己地址作為應答,等待接收數據TB8=0;SBUF=addr;while(!TI);TI=0;
SM2=0;//接收數據幀aa=0xff;//從機接收數據,并將數據保存到數據緩沖區while(aa==0xff){aa=RECE_data(Buff);}if(aa==0xfe)continue;P1=Buff[2];//查看接收到的數據}}
-
51單片機
+關注
關注
274文章
5705瀏覽量
124294 -
多機通信
+關注
關注
0文章
16瀏覽量
9240
原文標題:51單片機多機通信
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論