基于51的MODBUS-RTU多机主从通信

基于51的MODBUS-RTU多机通信实验环境:Proteus编程语言:汇编编程环境:KEIL单片机: AT89C51,AT89C52晶振:11.0592MHz功能说明:本实验运用了MODBUS-RTU通信协议的功能码03多寄存器读和功能码10多寄存器写,其中主机首先通过03功能码读取1号从机的时,分和秒的值,并将它们用液晶LCD显示器显示出来。

然后利用10功能将读取的值送入2号从机,2号从机在接收到主机送来的数据后再将它们以与1号从机相同的方式显示出来。

为1号从机设置了按钮,可调节它的时间,同是主机和2号从机也随之显示相同的时间。

图示:部分程序源代码:1、主机ORG 000HLJMP MAINORG 000BHLJMP TMR0ORG 0023HLJMP USARTORG 0040HMAIN: ACALL INITHERE: CLR RS0CLR RS1JB FLAG2.7,TXWORKJB UFLAG.7,RXWORK;AJMP HERETXWORK: AJMP TXWORK1RXWORK: CLR UFLAG.7;**********接收完成,显示操作JB UFLAG.3,RXWMB03RXWMB10: JNB UFLAG.5,HEREAJMP RXMBW101RXWMB03: CLR UFLAG.3MOV R0,#HOUR1MOV A,CND3CLR CRRC AMOV R7,AMOV R1,#CND5 RWORK1: MOV A,@R1MOV @R0,AINC R1INC R1INC R0DJNZ R7,RWORK1MOV DSPC,#8 TIMDIS: MOV A,DSPCMOV DPTR,#DISTBMOVC A,@A+DPTRMOV LCDD,AACALL LCDWPMOV A,#HOUR1ADD A,DSPCMOV R1,AMOV A,@R1MOV B,#10DIV ABACALL DISPMOV A,BACALL DISPDEC DSPCJNB DSPC.7,TIMDIS CLR RENSETB URDMOV CND1,#0A1H MOV CND2,#10H MOV CND3,#0MOV CND4,#50H MOV CND5,#0MOV CND6,#3MOV CND7,#6MOV CND8,#0MOV CND9,HOUR1 MOV CND10,#0 MOV CND11,MIN1 MOV CND12,#0 MOV CND13,SEC1MOV CND15,#0A5HMOV CNDT,#0MOV CNDT1,#15SETB TB8MOV SBUF,CND1AJMP HERE;******************************** RXMBW101: CLR UFLAG.5MOV CNDT,#0MOV CNDT1,#8AJMP HERE;************************************** TXWORK1:CLR FLAG2.7;1S定时CLR RENSETB URD/* MOV CND1,#30HMOV CND2,#31HMOV CND3,#32HMOV CND4,#33HMOV CND5,#34HMOV CND6,#35HMOV CND8,#37HMOV CND9,#38H*/MOV CND1,#0A0H;地址MOV CND2,#03H ;功能码MOV CND3,#0 ;起始地址2字节MOV CND4,#3BHMOV CND5,#0 ;数据长度MOV CND6,#3MOV CND7,#5AHMOV CND8,#0A5HMOV CNDT,#0MOV CNDT1,#8SETB TB8MOV SBUF,CND1AJMP HERE;*******************************DISTB: DB81H,84H,87H,0C1H,0C4H,0C7H,91H,94H,97H,0D1H,0D4H,0D 7H;*************USART: PUSH PSWPUSH ACCSETB RS0SETB RS1JBC RI,RXINT;发送中断,清中断标志位并转中断处理TXINT: CLR TIINC CNDTMOV A,CNDTCJNE A,CNDT1,TXGN;必须在发送前检测,若在后的话,则最后一个字节可能不能正确传输TXSTP: SETB UFLAG.6;发送结束标志MOV CNDT,#0MOV CNDT1,#8CLR URDSETB RENAJMP UOUT;********************TXGN: MOV A,#CND1ADD A,CNDTMOV R0,ACLR TB8MOV SBUF,@R0UOUT: POP ACCPOP PSWRETI;*************************RXINT: MOV RXDT,SBUFMOV A,CNDTCJNE A,#1,RXINT1MOV A,RXDTCJNE A,#03H,RXMD10MOV CNDT1,#5SETB UFLAG.3;MODBUS03功能AJMP RXSTOR;********************** RXMD10: CJNE A,#10H,RXERORMOV CNDT1,#8SETB UFLAG.5;MODBUS10功能AJMP RXSTOR;********************** RXINT1: JNB UFLAG.3,RXSTORCJNE A,#2,RXSTORMOV A,RXDTADD A,CNDT1MOV CNDT1,ARXSTOR: MOV A,#CND1ADD A,CNDTMOV R0,AMOV @R0,RXDT;CLR RIINC CNDTMOV A,CNDTCJNE A,CNDT1,RXOUTCRCCK: MOV A,@R0 ;发送来的数据变形与否的最简单校验SWAP ADEC R0XRL A,@R0JNZ RXERORSETB UFLAG.7MOV CNDT1,#16MOV CNTM_OV,#200RXEROR: MOV CNDT,#0AJMP UOUTRXOUT: MOV CNTM_OV,#200AJMP UOUT;****************************** DELA Y: MOV R2,#250DELA Y1: DJNZ R2,DELA Y1RET;***************************;**************定时器0中断处理程序TMR0: PUSH PSWPUSH ACCCLR RS1SETB RS0/*MOV A,CNTM_OVJZ TMR01DEC CNTM_OVMOV A,CNTM_OVJNZ TMR01CLR URDSETB REN*/TMR01: DJNZ TM0T1,RETIFMOV TM0T1,#10 ;1msDJNZ TM0TB,RETIFMOV TM0TB,#100DJNZ TM0TS,RETIFMOV TM0TS,#10SETB FLAG2.7;***************** ;中断返回RETIF: CLR RS0POP ACCPOP PSWRETI;***********HD44780读写子程序BUSY: MOV P0,#0FFHCLR LCDRSSETB LCDRWSETB LCDEMOV BIT0,P0CLR LCDEJB BIT0.7,BUSYRETLCDWP: ACALL BUSYCLR LCDRSSJMP LCD1LCDWD: ACALL BUSYSETB LCDRSLCD1: CLR LCDRWSETB LCDEMOV P0,LCDDNOPCLR LCDESETB LCDRSRETLCDW: MOV A,@R0ACALL LCDWDINC R0DJNZ R2,LCDWRET;***************DISP: MOV DPTR,#TIMETBMOVC A,@A+DPTRMOV LCDD,AACALL LCDWDRETTIMETB: DB "0123456789:/abcd" ;****************初始化子程序INIT: MOV SP,#0EFHMOV R1,#TM0TCLR0: MOV @R1,#0INC R1CJNE R1,#FRAM_OV,CLR0LCDINT: MOV LCDD,#38H;LCD初始化子程序ACALL LCDWPMOV LCDD,#01HACALL LCDWPMOV LCDD,#06HACALL LCDWPMOV LCDD,#0CHACALL LCDWPMOV LCDD,#83HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#86HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#0C3HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#0C6HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#93HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#96HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#0D3HACALL LCDWPMOV A,#10ACALL DISPMOV LCDD,#0D6HACALL LCDWPMOV A,#10ACALL DISP;***********************MOV TMOD,#22H;定时器0和1均工作于方式2,定时器1用于串口波特率MOV TH0, #0A3H;11.0592M,100usMOV TL0,#0A3HMOV TM0T,#1MOV TM0T1,#1MOV TM0TB,#5MOV TM0TS,#10;USART初始化MOV TH1,#0FDHMOV TL1,#0FDH; SETB P3.0MOV SCON,#0D0H;串行工作方式3,9为数据传输MOV PCON,#00HSETB URDMOV CNDT,#0MOV CNDT1,#8MOV DSPC,#8MOV UFLAG,#0MOV FLAG2,#0SETB TR0SETB ET0SETB TR1;运行定时器1,但不开中断SETB ES;开串行口中断SETB PSSETB EARET;*************************** END2、1号从机ORG 000HAJMP MAINORG 000BHAJMP TMR0ORG 0023HAJMP USARTORG 0040HMAIN: ACALL INITHERE: CLR RS0CLR RS1JNB UFLAG.7,TIMDC HERE2: CLR UFLAG.7CLR RENSETB URDMOV A,CND6MOV R7,ACLR CRLC AMOV CND3,AADD A,#5MOV CNDT1,AMOV R0,CND4MOV R1,#CND4 MDBS03T:MOV @R1,#0INC R1MOV A,@R0MOV @R1,AINC R0INC R1DJNZ R7,MDBS03TMOV @R1,#5AHINC R1MOV @R1,#0A5HMOV CNDT,#0ACALL DELA YCLR TB8MOV SBUF,CND1TIMDC: JB FLAG2.7,KEYSCAN TIMEDC: MOV A,HOURMOV B,#10DIV ABJNZ TIMH1MOV DIS7,#11AJMP TIMH2;************************ TIMH1: MOV DIS7,ATIMH2: MOV DIS6,B TIMEM: MOV A,MINUTEMOV B,#10DIV ABMOV DIS4,AMOV DIS3,BTIMES: MOV A,SECONDMOV B,#10DIV ABMOV DIS1,AMOV DIS0,BAJMP HERE;*************************KEYSCAN:CLR FLAG2.7MOV A,P1ORL A,#0E0HMOV P1,ANOPNOPMOV A,P1ANL A,#0E0HXRL A,#0E0HJZ NKEYMOV KTEMP,AAJMP HERENKEY: JB KTEMP.KEY0,KSET JB KTEMP.KEY1,KADDJNB KTEMP.KEY2,KOUTAJMP KSUBKSET: JB FLAG2.0,KSET1SETB FLAG2.0AJMP KOUTKSET1: INC FLAG2SETB FLAG2.0JNB FLAG2.2,KOUTMOV FLAG2,#0 KOUT: MOV KTEMP,#0AJMP TIMEDCKADD: JNB FLAG2.0,KOUT MOV R0,#MINUTEJNB FLAG2.1,KADD1MOV R0,#HOURKADD1: INC @R0JB FLAG2.1,HOURACJNE @R0,#60,KOUT KADD2: MOV @R0,#0AJMP KOUTHOURA: CJNE @R0,#24,KOUT AJMP KADD2KSUB: JNB FLAG2.0,KOUTMOV R0,#MINUTEJNB FLAG2.1,KSUB1MOV R0,#HOURKSUB1: DEC @R0MOV A,@R0JNB ACC.7,KOUTJB FLAG2.1,KSUBH0MOV @R0,#59AJMP KOUTKSUBH0: MOV @R0,#23AJMP KOUT;****************定时器0中断处理TMR0: PUSH PSWPUSH ACCSETB RS0CLR RS1DJNZ TM0T,TIMEMOV TM0T,#20T0DIS: MOV P0,#0MOV A,P1ANL A,#0F8HORL A,DSPCMOV P1,AMOV A,#DIS0ADD A,DSPCMOV R0,AMOV A,@R0MOV DPTR,#LEDTBMOVC A,@A+DPTRMOV P0,ADEC DSPCJNB DSPC.7,TIMEMOV DSPC,#7;********************************************** TIME: DJNZ TM0T1,RETIFMOV TM0T1,#10 ;1msDJNZ TM0TB,RETIFMOV TM0TB,#100SETB FLAG2.7DJNZ TM0TS,RETIFMOV TM0TS,#10INC SECONDMOV A,SECONDCJNE A,#60,TIMEHMOV SECOND,#00HINC MINUTEMOV A,MINUTECJNE A,#60,TIMEHMOV MINUTE,#00HINC HOURMOV A,HOURCJNE A,#24,TIMEHMOV HOUR,#00HTIMEH:RETIF: POP ACCPOP PSWRETI;*********************;***********七段共阴数码管LEDTB: DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H,00H ;******************************/*TIMEH1: SETB URDSETB UFLAG.4MOV CND1,#0A0HMOV CND2,#10HMOV CND3,#0MOV CND4,#40HMOV CND5,#0MOV CND6,#3MOV CND7,#6MOV CND8,#0MOV CND9,HOURMOV CND11,MINUTEMOV CND12,0MOV CND13,SECONDMOV CND14,#5AHMOV CND15,#0A5HMOV CNDT,#0MOV CNDT1,#15SETB UFLAG.6CLR UFLAG.5AJMP RETIF;******************/;*************USART: PUSH PSWPUSH ACCSETB RS0SETB RS1JBC RI,RXINT;发送中断,清中断标志位并转中断处理TXINT: CLR TIINC CNDTCJNE A,CNDT1,TXGN;必须在发送前检测,若在后的话,则最后一个字节可能不能正确传输TXSTP: MOV CNDT,#0MOV CNDT1,#8CLR URDSETB RENAJMP UOUT;********************TXGN: MOV A,#CND1ADD A,CNDTMOV R0,ACLR TB8MOV SBUF,@R0UOUT: POP ACCPOP PSWRETIRXAD: MOV A,RXDTCJNE A,#0A0H,RXERORCLR SM2AJMP RXSTORRXINT: MOV RXDT,SBUFJZ RXADCJNE A,#1,RXSTORMOV CNDT1,#8RXSTOR: MOV A,#CND1ADD A,CNDTMOV R0,AMOV @R0,RXDTINC CNDTMOV A,CNDTCJNE A,CNDT1,RXOUTCRCCK: MOV A,@R0 ;接收到的数据变形与否的简单校验SWAP ADEC R0XRL A,@R0JNZ RXERORSETB UFLAG.7MOV CNDT1,#16RXEROR: SETB SM2MOV CNDT,#0RXOUT: AJMP UOUT;***********************DELA Y: MOV R2,#250DELA Y1: DJNZ R2,DELA Y1RET;****************初始化子程序INIT: MOV SP,#5FHMOV R1,#DIS0MOV DSPC,#0CLR URDCLR0: MOV @R1,#0INC R1CJNE R1,#HOUR,CLR0MOV DSPC,#7MOV DIS2,#10MOV DIS5,#10MOV TMOD,#22H;定时器0和1均工作于方式2,定时器1用于串口波特率MOV TH0, #0A3H;11.0592M,100usMOV TL0,#0A3HMOV TM0T,#1MOV TM0T1,#1MOV TM0TB,#5MOV TM0TS,#10;USART初始化MOV TH1,#0FDHMOV TL1,#0FDHMOV SCON,#0F0H;串行工作方式2,9为数据传输MOV PCON,#00HCLR URDMOV CNDT,#0MOV CNDT1,#8MOV UFLAG,#0MOV FLAG2,#0SETB TR0SETB ET0SETB TR1;运行定时器1,但不开中断SETB ES;开串行口中断SETB PSSETB EARET;***************************END3、2号从机ORG 000HLJMP MAINORG 000BHLJMP TMR0ORG 0023HLJMP USARTORG 0040HMAIN: ACALL INITHERE: CLR RS0CLR RS1JB UFLAG.7,HERE2 AHERE: AJMP HEREHERE2: CLR RENCLR UFLAG.7;**********接收完成,显示操作MOV R0,CND4MOV R7,CND6MOV R1,#CND9HERE1: MOV A,@R1MOV @R0,AINC R1INC R1INC R0DJNZ R7,HERE1 TIMEDC: MOV A,HOURMOV B,#10DIV ABJNZ TIMH1MOV DIS7,#11AJMP TIMH2TIMH1: MOV DIS7,A TIMH2: MOV DIS6,B TIMEM: MOV A,MINMOV B,#10DIV ABMOV DIS4,AMOV DIS3,B TIMES: MOV A,SECMOV B,#10DIV ABMOV DIS1,AMOV DIS0,BSETB URD;从机接收指令后回复报文SECHO: MOV CND7,#5AHMOV CNDT,#0MOV CNDT1,#8CLR TB8MOV SBUF,CND1AJMP HERE;*******************************DISTB: DB81H,84H,87H,0C1H,0C4H,0C7H,91H,94H,97H,0D1H,0D4H,0D7H;*************USART: PUSH PSWPUSH ACCSETB RS0SETB RS1JBC RI,RXINT;发送中断,清中断标志位并转中断处理TXINT: CLR TIINC CNDTMOV A,CNDTCJNE A,CNDT1,TXGN;必须在发送前检测,若在后的话,则最后一个字节可能不能正确传输MOV CNDT1,#8CLR URDSETB RENAJMP UOUT;******************** TXGN: MOV A,#CND1ADD A,CNDTMOV R0,ACLR TB8MOV SBUF,@R0 UOUT: POP ACCPOP PSWRETIRXAD: MOV A,RXDTCJNE A,#0A1H,RXERORCLR SM2AJMP RXSTOR RXINT: MOV RXDT,SBUFMOV A,CNDTJZ RXADCJNE A,#1,RXINT1AJMP RXSTORRXINT1: CJNE A,#6,RXSTORMOV A,RXDTADD A,CNDT1MOV CNDT1,ARXSTOR: MOV A,#CND1ADD A,CNDTMOV R0,AMOV @R0,RXDTINC CNDTMOV A,CNDTCJNE A,CNDT1,RXOUTCRCCK: MOV A,@R0 ;接收到的数据变形与否的简单校验SWAP ADEC R0XRL A,@R0JNZ RXERORSETB UFLAG.7MOV CNDT1,#16RXEROR: SETB SM2RXOUT: AJMP UOUT;****************************** DELAY: MOV R2,#250DELAY1: DJNZ R2,DELAY1RET;***************************;**************定时器0中断处理程序TMR0: PUSH PSWPUSH ACCSETB RS0CLR RS1DJNZ TM0T,TIMEMOV TM0T,#20T0DIS: MOV P0,#0MOV A,P1ANL A,#0F8HORL A,DSPCMOV P1,AMOV A,#DIS0ADD A,DSPCMOV R0,AMOV DPTR,#LEDTBMOVC A,@A+DPTRMOV P0,ADEC DSPCJNB DSPC.7,TIMEMOV DSPC,#7;********************************************** TIME: DJNZ TM0T1,RETIFMOV TM0T1,#10 ;1msDJNZ TM0TB,RETIFMOV TM0TB,#100SETB FLAG2.7DJNZ TM0TS,RETIFMOV TM0TS,#10;***************** ;中断返回RETIF: CLR RS0POP ACCPOP PSWRETI;***********七段共阴数码管LEDTB: DB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H,00H ;****************初始化子程序INIT: MOV SP,#05FHCLR URDMOV R1,#TM0TCLR0: MOV @R1,#0INC R1CJNE R1,#RXDT,CLR0;***********************MOV TMOD,#22H;定时器0和1均工作于方式2,定时器1用于串口波特率MOV TH0, #0A3H;11.0592M,100usMOV TL0,#0A3HMOV TM0T,#1MOV TM0T1,#1MOV TM0TB,#5MOV TM0TS,#10;USART初始化MOV TH1,#0FDHMOV TL1,#0FDH; SETB P3.0MOV SCON,#0F0H;串行工作方式3,9位数据传输MOV PCON,#00HMOV CNDT,#0MOV CNDT1,#16MOV DSPC,#7MOV DIS2,#10MOV DIS5,#10MOV UFLAG,#0SETB TR0SETB ET0SETB TR1;运行定时器1,但不开中断SETB ES;开串行口中断SETB PSSETB EARET;***************************END。

合集下载

51单片机实现双机通信

51单片机实现双机通信

左侧 1 号机,右侧 2 号机,,功能实现1号机程序#include<reg51.h>#define uint unsigned int#define uchar unsigned charsbit p10=P1^0;uchar a,b,kk;//uchar code d_c[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; void delay_ms(uchar y){uchar i;while(y--)for(i=0;i<120;i++);}void put(uchar x) // 发送函数{SBUF=x;//SBUF:串行口数据缓冲器while(TI==0);// 等候发送结束TI=0;}void main(){uchar j;SCON=0x40;// 串行口工作方式1,8位通用异步发送器TMOD=0x20;// 准时器 1 工作方式2 PCON=0x00;// 波特率不倍增TH1=0xf4;TL1=0xf4; TR1=1;// 波特率 2400// 准时器 1 开始计时P2=0xc0;while(1){if(p10==0&&j==0){delay_ms(15);while(p10==0);kk=1;P2=0xf9;j=1;}if(p10==0&&j==1){delay_ms(15);while(p10==0);kk=2;P2=0xa4;j=2;}if(p10==0&&j==2){delay_ms(15);while(p10==0);kk=3;P2=0xb0;j=0;}if(kk==1)put('A');if(kk==2)put('B');if(kk==3)put('C');delay_ms(10);}}/*********************************************************************** if(p10==0&&j==0){delay_ms(15);while(p10==0);kk=0;P2=~0xf9;j=1;}if(p10==0&&j==1){delay_ms(15);while(p10==0);kk=1;P2=~0xa4;j=2;}if(p10==0&&j==2){delay_ms(15);while(p10==0);kk=2;P2=~0xc0;j=0;}if(kk==0)put('A');if(kk==1)put('B');if(kk==2)put('C');delay_ms(100);*********************************************************** if(p10==0){delay_ms(15);while(p10==0);number=(number+1)%4;}switch(oper){case 0:break;case 1:put('A');P2=~0xf9;break;case 2:put('B');P2=~0xa4;break;case 3:put('C');P2=~0xc0;break;}delay_ms(10);********************************************************************if(p10==0){delay_ms(15);while(p10==0);j=(j+1)%3;}switch(j){case 0:put('A');P2=~0xf9;break;case 1:put('B');P2=~0xa4;break;case 2:put('C');P2=~0xc0;break;}delay_ms(10);*/2号机程序。

51单片机实现Modbus从机程序

51单片机实现Modbus从机程序

51单片机实现M o d b u s从机程序(总11页)本页仅作为文档封面,使用时可以删除This document is for reference only-rar21year.March自己用单片机做的Modbus从机,可以使用STC89C52。

实现了命令码为1、2、3、4、5、6的功能,程序中有些是我们部分其他功能的函数和数据,希望大家参考下编程的思想。

uint Switch=0xbc95;//开关状态uchar bdata Coil1=0xff,Coil2=0xbc;//16位线圈状态sbit Coil1_bit0=Coil1^0;sbit Coil1_bit1=Coil1^1;sbit Coil1_bit2=Coil1^2;sbit Coil1_bit3=Coil1^3;sbit Coil1_bit4=Coil1^4;sbit Coil1_bit5=Coil1^5;sbit Coil1_bit6=Coil1^6;sbit Coil1_bit7=Coil1^7;sbit Coil2_bit8=Coil2^0;sbit Coil2_bit9=Coil2^1;sbit Coil2_bit10=Coil2^2;sbit Coil2_bit11=Coil2^3;sbit Coil2_bit12=Coil2^4;sbit Coil2_bit13=Coil2^5;sbit Coil2_bit14=Coil2^6;sbit Coil2_bit15=Coil2^7;uint idataReOnlybuf[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0 x0c,0x0d,0x0e,0x0f};uint idataReWrbuf[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x 0c,0x0d,0x0e,0x0f};//CRC校验查表码值const uchar code auchCRCHi[] ={0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};const uchar code auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40};/******************************************** Function:CRC校验子函数Input:要校验的数组起始地址长度Output:16位校验码(高位在前)********************************************/uint crccheck(uchar *puchMsg, uchar usDataLen){uchar uchCRCHi = 0xFF ;uchar uchCRCLo = 0xFF ;uchar uIndex ;while (usDataLen--){uIndex = uchCRCHi ^ *puchMsg++ ;uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;uchCRCLo = auchCRCLo[uIndex] ;}return (uchCRCHi << 8 | uchCRCLo) ;}/******************************************** Function:读线圈状态子函数Input:无Output:无********************************************/void ReadCoil(void){uint StartAddress,tempAddress;uchar CoilNum,i,ByteNum,j;uchar CoilVal;bit exit=0;StartAddress=resvbuf[2];StartAddress=StartAddress|resvbuf[3];tempAddress=StartAddress;CoilNum=resvbuf[5];//读取的位数ByteNum=CoilNum/8;if(CoilNum%8!=0)ByteNum++;Sendbuf[2]=ByteNum;//返回的字节数if(resvbuf[1]==0x01){for(i=0;i<ByteNum;i++){Sendbuf[i+3]=0;for(j=0;j<8;j++){CoilVal=GetCoilVal(StartAddress);Sendbuf[i+3]|=CoilVal<<j;StartAddress++;if(StartAddress>=tempAddress+CoilNum){exit=1;break;}}if(exit==1)break;}}else if(resvbuf[1]==0x02){for(i=0;i<ByteNum;i++){Sendbuf[i+3]=0;for(j=0;j<8;j++){CoilVal=GetSWVal(StartAddress);Sendbuf[i+3]|=CoilVal<<j;StartAddress++;if(StartAddress>=tempAddress+CoilNum){exit=1;break;}}if(exit==1)break;}}SendCount=5+ByteNum;SendData();}/******************************************** Function:读寄存器状态子函数Input:无Output:无********************************************/void ReadRegisters(void){uint StartAddress;uchar ByteCount,i;StartAddress=resvbuf[2];StartAddress=StartAddress<<8|resvbuf[3];ByteCount=resvbuf[5]*2;Sendbuf[2]=resvbuf[5];if(resvbuf[1]==0x03)for(i=0;i<ByteCount;i+=2){Sendbuf[i+4]=ReWrbuf[StartAddress]&0xff;Sendbuf[i+3]=ReWrbuf[StartAddress]>>8;StartAddress++;}else if(resvbuf[1]==0x04)for(i=0;i<ByteCount;i+=2){Sendbuf[i+4]=ReOnlybuf[StartAddress];Sendbuf[i+3]=ReOnlybuf[StartAddress];StartAddress++;}SendCount=ByteCount+5;SendData();}/******************************************** Function:强制单线圈子函数Input:无Output:无********************************************/ void ForceSingalCoil(void){uint Address,OnOff;bit temp,CoilVal;Address=resvbuf[2]<<8|resvbuf[3];OnOff=resvbuf[4]<<8|resvbuf[5];if(OnOff==0x0000){CoilVal=0;temp=SetCoilVal(Address,CoilVal);}else if(OnOff==0xFF00){CoilVal=1;temp=SetCoilVal(Address,CoilVal);}if(temp==1){Sendbuf[2]=resvbuf[2];Sendbuf[3]=resvbuf[3];Sendbuf[4]=resvbuf[4];Sendbuf[5]=resvbuf[5];SendCount=8;SendData();}elseError=1;}/******************************************** Function:强制单寄存器子函数Input:无Output:无********************************************/ void SetOneRegisterVal(){uint R_Address,RegisterVal;bit temp1;R_Address=resvbuf[2];R_Address=R_Address<<8|resvbuf[3];RegisterVal=resvbuf[4];RegisterVal=RegisterVal<<8|resvbuf[5];temp1=SetRegisterVal(R_Address,RegisterVal);if(temp1==1){Sendbuf[2]=resvbuf[2];Sendbuf[3]=resvbuf[3];Sendbuf[4]=resvbuf[4];Sendbuf[5]=resvbuf[5];SendCount=8;SendData();}elseError=1;}/******************************************** Function:读线圈值子函数Input:线圈地址Output:线圈的值********************************************/ uchar GetCoilVal(uint Address){uint CoilAddress;uchar CoilVal=0;CoilAddress=Address;switch(CoilAddress&0x0f){case 0: CoilVal=Coil1_bit0;break;case 1: CoilVal=Coil1_bit1;break;case 2: CoilVal=Coil1_bit2;break;case 3: CoilVal=Coil1_bit3;break;case 4: CoilVal=Coil1_bit4;break;case 5: CoilVal=Coil1_bit5;break;case 6: CoilVal=Coil1_bit6;break;case 7: CoilVal=Coil1_bit7;break;case 8: CoilVal=Coil2_bit8;break;case 9: CoilVal=Coil2_bit9;break;case 10: CoilVal=Coil2_bit10;break;case 11: CoilVal=Coil2_bit11;break;case 12: CoilVal=Coil2_bit12;break;case 13: CoilVal=Coil2_bit13;break;case 14: CoilVal=Coil2_bit14;break;case 15: CoilVal=Coil2_bit15;break;default: break;}return CoilVal;}/******************************************** Function:读开关值子函数Input:开关地址Output:开关值********************************************/ uchar GetSWVal(uint Address1){uchar CoilVal;uchar SW1,SW2=0xff;SW1=P2;Switch=SW2<<8|SW1;switch(Address1&0x0f){case 0: CoilVal=Switch&0x01;break;case 1: CoilVal=Switch>>1&0x01;break;case 2: CoilVal=Switch>>2&0x01;break;case 3: CoilVal=Switch>>3&0x01;break;case 4: CoilVal=Switch>>4&0x01;break;case 5: CoilVal=Switch>>5&0x01;break;case 6: CoilVal=Switch>>6&0x01;break;case 7: CoilVal=Switch>>7&0x01;break;case 8: CoilVal=Switch>>8&0x01;break;case 9: CoilVal=Switch>>9&0x01;break;case 10: CoilVal=Switch>>10&0x01;break;case 11: CoilVal=Switch>>11&0x01;break;case 12: CoilVal=Switch>>12&0x01;break;case 13: CoilVal=Switch>>13&0x01;break;case 14: CoilVal=Switch>>14&0x01;break;case 15: CoilVal=Switch>>15&0x01;break;default: break;}return CoilVal;}/******************************************** Function:强制单线圈值子函数Input:线圈地址,强制值Output:结果值********************************************/bit SetCoilVal(uint Address,bit Val){bit result=1;switch(Address&0x0f){case 0: Coil1_bit0=Val;break;case 1: Coil1_bit1=Val;break;case 2: Coil1_bit2=Val;break;case 3: Coil1_bit3=Val;break;case 4: Coil1_bit4=Val;break;case 5: Coil1_bit5=Val;break;case 6: Coil1_bit6=Val;break;case 7: Coil1_bit7=Val;break;case 8: Coil2_bit8=Val;break;case 9: Coil2_bit9=Val;break;case 10: Coil2_bit10=Val;break;case 11: Coil2_bit11=Val;break;case 12: Coil2_bit12=Val;break;case 13: Coil2_bit13=Val;break;case 14: Coil2_bit14=Val;break;case 15: Coil2_bit15=Val;break;default: result=0;break;}P1=Coil1;return result;}/******************************************** Function:设置单寄存器值子函数Input:寄存器地址,值Output:结果值********************************************/ bit SetRegisterVal(uint Address1,uint Val1){uchar Addr;bit result1=1;Addr=Address1&0x0f;if(Addr<16)ReWrbuf[Addr]=Val1;elseresult1=0;return result1;}。

51单片机串口多机通信的实现和编程

51单片机串口多机通信的实现和编程

51 单片机串口多机通信的实现和编程
一、51 单片机的主从模式,首先要设定工作方式3:(主从模式+波特率可变)
SCON 串口功能寄存器:SM0=1;SM1=1(工作方式3)
注:主机和从机都要为工作方式3。

【工作方式2 (SM0 SM1 :1 0):串行口为11 位异步通信接口。

发送或接收
一帧信息包括1 位起始位0、8 位数据位、1 位可编程位、1 位停止位1。

发
送数据:发送前,先根据通信协议由软件设置TB8 为奇偶校验位或数据标识位,然后将要发送的数据写入SBUF,即能启动发送器。

发送过程是由执行任何一条以SBUF 为目的寄存器的指令而启动的,把8 位数据装入SBUF,
同时还把TB8 装到发送移位寄存器的第9 位上,然后从TXD(P3.1)端口输出
一帧数据。

接收数据:先置REN=1,使串行口为允许接收状态,同时还要将RI 清0。

然后再根据SM2 的状态和所接收到的RB8 的状态决定此串行口在
信息到来后是否置R1=1,并申请中断,通知CPU 接收数据。

当SM2=0 时,
不管RB8 为0 还是为1,都置RI=1,此串行口将接收发送来的信息。

当
SM2=1 时,且RB8=1,表示在多机通信情况下,接收的信息为地址帧, 此时
置RI=1,串行口将接收发来的地址。

当SM2=1 时,且RB8=0,表示在多机通
信情况下,接收的信息为数据帧, 但不是发给本从机的,此时RI 不置为1,。

基于51单片机的多机通信系统设计

基于51单片机的多机通信系统设计

基于51单片机的多机通信系统设计多机通信系统是指通过一台主机与多台从机之间进行数据交互和通信的系统。

在本设计中,我们将使用51单片机实现一个基于串行通信的多机通信系统。

系统硬件设计如下:1.主机:使用一个51单片机作为主机,负责发送数据和接收数据。

2.从机:使用多个51单片机作为从机,每个从机负责接收数据和发送数据给主机。

3.串口:主机和从机之间通过串口进行通信。

我们可以使用RS232标准通信协议。

系统软件设计如下:1.主机设计:a.初始化串口:设置串口参数,如波特率、数据位、停止位等。

b.发送数据:将需要发送的数据存储在发送缓冲区中,通过串口发送给从机。

c.接收数据:接收从机发送的数据,并存储在接收缓冲区中。

2.从机设计:a.初始化串口:设置串口参数,如波特率、数据位、停止位等。

b.接收数据:接收主机发送的数据,并存储在接收缓冲区中。

c.发送数据:将需要发送的数据存储在发送缓冲区中,通过串口发送给主机。

系统工作流程如下:1.主机启动,执行初始化操作,包括初始化串口。

2.从机启动,执行初始化操作,包括初始化串口。

3.主机发送数据给从机:主机将需要发送的数据存储在发送缓冲区中,通过串口发送给从机。

4.从机接收并处理数据:从机接收主机发送的数据,并存储在接收缓冲区中,对接收到的数据进行处理。

5.从机发送数据给主机:从机将需要发送的数据存储在发送缓冲区中,通过串口发送给主机。

6.主机接收并处理数据:主机接收从机发送的数据,并存储在接收缓冲区中,对接收到的数据进行处理。

7.主机和从机循环执行步骤3-6,实现多机之间的数据交互和通信。

多机通信系统的设计考虑到以下几个方面:1.硬件设计:需要合理选择单片机和串口的类型和参数,确保系统的稳定性和可靠性。

2.软件设计:需要设计适应系统需求的通信协议和数据处理提取方法,保证数据的准确性和完整性。

3.通信协议:需要定义主机和从机之间的通信协议,包括数据的格式、传输方式等,以便实现正确的数据交互。

Modbus协议多机通讯系统设计

Modbus协议多机通讯系统设计

Modbus协议多机通讯系统设计【摘要】课题是基于Modbus协议的一个多单片机通信系统,整个多机通信系统是实际应用中多机通信系统的模型。

系统是由单片机AT89S52和1602液晶等模块组成的多机通信系统。

系统各部分的软件设计是根据Modbus协议规约编写,系统编程采用C语言。

系统的技术可以用于很多需要多机连接通信的系统,有很强的实用价值。

【关键词】单片机;Modbus协议;多机通信1.绪论目前单片机渗透到生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。

导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,民用豪华轿车的安全保障系统,录象机、摄象机、全自动洗衣机的控制,以及程控玩具、电子宠物等等,这些都离不开单片机。

更不用说自动控制领域的机器人、智能仪表、医疗器械了。

在大部分单片机应用领域都是多个单片机构成一个多机通信系统,他们之间相互通信接收、发送和处理信息,发挥整体的作用。

Modbus协议是MODICON公司推出的一个开放式现场总线的通信协议,由于得到众多仪表厂家的支持,正在成为仪表及智能终端的工业标准,目前,多数智能仪表已利用该协议向户提供通信接口,随着仪表和通信技术的发展,Modbus 协议由Standard Modbus(标准型)发展到Modbus Plus(增强型)。

Modbus的通信方式为主从方式。

主方首先向从方发送通信请求指令,从方根据请求指令中的功能码向主方发回数据。

每个从方都有自己独立的地址。

主方所发的请求帧和从方所发的应答帧都是以从方地址开头的。

从方只读发给自己的指令,对以其他从方地址开头的报文不予理睬,并对接收到的正确的报文予以应答,这种一问一答的通信模式,大大提高了通信的正确率。

但是在多机系统中,要求既有主机与从机通信,也要有从机与主机通信,这种结构的系统是无法满足要求的。

单片机多机通信的目的是实现分布式处理系统,其通信方式有很多种,应用前景广阔,具有很大的研究意义!2.本设计的主要内容设计制作一个一主二从的多机通信系统,用Modbus协议实现他们的通信,设计内容是:(1)选择系统元件;(2)设计一主二从三个分立系统;(3)完成一主二从的硬件制作;(4)根据Modbus协议编写多机通信程序;(5)系统整体调试;(6)撰写设计说明书。

51单片机双机通信原理(一)

51单片机双机通信原理(一)

51单片机双机通信原理(一)51单片机双机通信简介•什么是51单片机双机通信•双机通信的作用和应用场景基本原理•单片机串口通信原理–串口通讯协议–数据帧的构成•串口通信的硬件连接–引脚连接方式–串口信号格式设置单向通信实现•主从模式–主机发送数据–从机接收数据•编程实现–主机端程序设计–从机端程序设计双向通信实现•主从模式–主机发送数据–从机接收数据–主机接收数据–从机发送数据•编程实现–主机端程序设计–从机端程序设计通信协议的设计•自定义通信协议–协议的格式–数据的解析与封装高级功能扩展•多机通信实现•数据加密与解密•异常处理与误码纠错总结•51单片机双机通信的基本原理和实现方式•可能遇到的问题及解决方案•双机通信的进一步应用展望简介51单片机双机通信是指使用51系列单片机实现两台或多台单片机之间的数据传输和通信。

双机通信可以实现在多个单片机之间传递数据、完成控制指令的下发、数据的采集和处理等功能。

在各种电子设备和嵌入式系统中,双机通信被广泛应用,可以实现设备之间的互联和协同工作,提高系统的灵活性和智能化水平。

基本原理单片机串口通信原理串口通信是一种将数据通过串行线路进行传输的通信方式。

在51单片机的串口通信中,常用的是UART(通用异步收发传输器)通信协议。

UART通信采用的是异步传输方式,数据按照固定的数据帧格式进行传输。

串口通信的硬件连接在51单片机的串口通信中,需要将主机和从机的UART引脚连接起来。

常用的连接方式是通过一对直线的串行数据线(TXD和RXD)连接主从机,其中TXD是发送数据的引脚,RXD是接收数据的引脚。

为了确保数据的正确传输,还需要进行串口信号格式的设置,包括波特率、数据位数、停止位数和校验位等。

单向通信实现主从模式在单向通信中,主机负责发送数据,从机负责接收数据。

主机通过串口发送数据帧,从机通过串口接收数据帧,并进行相应的处理。

编程实现在主机端程序设计中,需要配置串口通信的参数,并使用串口发送数据的相关函数来发送数据。

基于51单片机的双机串行通信设计组单片机课程设计

基于51单片机的双机串行通信设计一、设计任务设计要求:两个AT89C51单片机使用串口进行通信。

1)1机发送,二机接收时。

使用1机发送一个数字0xAA给2机。

2)如果2机收到数据后要给1机回复,回复0xBB。

3)1机收到回复后要下发数据,下发的同时要将数据显示出来,下发的数据通过4*4的矩阵键盘产生,可以由用户进行控制。

4)2机收到后将这些数值显示出来,一次传输完毕要回复0x00。

可以使用点阵显示或者数码管显示或者 LCD显示。

二、硬件设计1、单片机串行通信功能AT89C51计算机与外界的信息交换称为通信,常用的通信方式有两种:并行通信和串行通信。

51单片机用4个接口与外界进行数据输入与数据输出就是并行通信,并行通信的特点是传输信号的速度快,但所用的信号线较多,成本高,传输的距离较近。

串行通信的特点是只用两条信号线(一条信号线,再加一条地线作为信号回路)即可完成通信,成本低,传输的距离较远。

51单片机的串行接口是一个全双工的接口,它可以作为UART(通用异步接受和发送器)用,也可以作为同步移位寄存器用。

51单片机串行接口的结构如下:(1)数据缓冲器(SBUF)接受或发送的数据都要先送到SBUF缓存。

有两个,一个缓存,另一个接受,用同一直接地址99H,发送时用指令将数据送到SBUF即可启动发送;接收时用指令将SBUF中接收到的数据取出。

(2)串行控制寄存器(PCON)SCON用于串行通信方式的选择,收发控制及状态指示,各位含义如下:SM0,SM1:串行接口工作方式选择位,这两位组合成00,01,10, 11对应于工作方式0、1、2、3。

串行接口工作方式特点见下表SM2:多机通信控制位。

REN:接收允许控制位。

软件置1允许接收;软件置0禁止接收。

TB8:方式2或3时,TB8为要发送的第9位数据,根据需要由软件置1或清0。

RB9:在方式2或3时,RB8位接收到的第9位数据,实际为主机发送的第9位数据TB8,使从机根据这一位来判断主机发送的时呼叫地址还是要传送的数据。

51多机电路

51单片机的多机通信[日期:2008-05-05 ] [来源:net 作者:佚名] [字体:大中小] (投递新闻)在单片机多机通信过程中,PC机将指令打包后发给智能接口单元(以下简称主单片机)。

主单片机收到完整一包后将包解开,按对每个从机的指令分别发送,同时将各从机发给PC机的指令送给PC机。

由于64个从机和主单片机使用同一串口通信线,为避免发生冲突,主单片机处于主动状态,按一定的定时间隔与每一台从机顺序通信。

主单片机在与每一台从机通信过程中先发送地址,从机收到地址后若与自己的地址一致,则继续接收主单片机发来的一个字节的命令码,从机收到命令后,将自己的一个字节的命令发送到主单片机。

主单片机完成与64个从机的通信需要64个定时间隔,只要定时间隔足够短,主单片机与从机基本上可以实现实时通信。

在整个通信过程中,主单片机起着通信枢纽的作用。

单片机多机通信过程安排如下:使所有从机的SM2位置1,处于只接收地址帧的状态;主机发送一帧地址信息,其中包含8位地址,第9位为地址、数据标志位,第9位置1表示发送的是地址;从机接收到地址帧后,各自将所接收的地址与本从机的地址相比较,对于地址相符的从机,使SM2清0以接收主机随后发来的信息,对于地址不相符的从机,仍保持SM2=1状态,对主机随后发送的数据不予理睬,直至发送新的地址帧;主机发送控制指令与数据,给被寻址的从机数据帧的第9位置0,表示发送的是数据。

�单片机程序采用PLM51语言设计,主单片机定时中断服务程序框图如图4所示。

主单片机RS-485串行口接收和发送中段服务程序框图如图5所示。

主单片机RS-232C串行口接收中断服务程序如图6所示。

从单片机RS-485串行口接收和发送中段服务程序框图如图7所示。

主单片机在主程序中以查询方式将各从机送来的数据从内存中读出后顺序发送给上位PC机。

程序清单略。

图1 RS485通信接口原理图2 单片机多机通信硬件电路设计中需注意的问题2.1 电路基本原理某节点的硬件电路设计如图1所示,在该电路中,使用了一种RS-485接口芯片SN75LBC184,它采用单一电源Vcc,电压在+3~+5.5 V范围内都能正常工作。

基于51单片机的双机串行通信课程设计_1000110061

基于AT89C51单片机的双机串行通信设计姓名:杨应伟学号:100110061专业:机械设计制造及其制动化班级:机电二班前言单片机广泛应用于仪器仪表、家用电器、医用设备、航空航天、专用设备的智能化管理及过程控制等领域随着计算机技术的发展及工业自动化水平的提高, 在许多场合采用单机控制已不能满足现场要求,因而必须采用多机控制的形式,而多机控制主要通过多个单片机之间的串行通信实现。

串行通信作为单片机之间常用的通信方法之一, 由于其通信编程灵活、硬件简洁并遵循统一的标准, 因此其在工业控制领域得到了广泛的应用。

在测控系统和工程应用中,常遇到多项任务需同时执行的情况,因而主从式多机分布式系统成为现代工业广泛应用的模式。

单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表、家用电器方面都有广泛的应用。

同时,IBM-PC机正好补充单片机人机对话和外围设备薄弱的缺陷。

各单片机独立完成数据采集处理和控制任务,同时通过通信接口将数据传给PC机,PC机将这些数据进行处理、显示或打印,把各种控制命令传给单片机,以实现集中管理和最优控制。

串行通信是单片机的一个重要应用,本次课程设计就是要利用单片机来完成一个系统,实现爽片单片机床航通信,通信的结果使用数码管进行显示,数码管采用查表方式显示,两个单片机之间采用RS-232进行双击通信。

在通信过程中,使用通信协议进行通信。

在测控系统和工程应用中,常遇到多项任务需同时执行的情况,因而主从式多机分布式系统成为现代工业广泛应用的模式。

单片机功能强、体积小、价格低廉、开发应用方便,尤其具有全双工串行通讯的特点,在工业控制、数据采集、智能仪器仪表、家用电器方面都有广泛的应用。

同时,IBM-PC机正好补充单片机人机对话和外围设备薄弱的缺陷。

各单片机独立完成数据采集处理和控制任务,同时通过通信接口将数据传给PC机,PC机将这些数据进行处理、显示或打印,把各种控制命令传给单片机,以实现集中管理和最优控制。

51单片机多机通信程序

51单片机多机通信程序(主机部分) /* multi_m.c *//* 多机通信的主机部分*/#ifndef __MULTI_M_C__#define __MULTI_M_C__#include <AT89X51.H>#include <STRING.H>#define __MAX_LEN_ 64 // 数据最大长度#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz) /* 以下为程序协议中使用的握手信号*/#define __SUCC_ 0x0f // 数据传送成功#define __ERR_ 0xf0 // 数据传送错误void init_serial(); // 串口初始化void send_data(unsigned char *buf); // 发送数据void delay10ms(unsigned int count); // 延时子程序(10ms) void main(){char buf[__MAX_LEN_];unsigned char i = 0;unsigned char tmp;unsigned char addr; // 该字节用于保存要通信的从机地址/* 为缓冲区赋初值*/P0 = 0xff;while(P1 != 0) // 每隔100ms从P0口读取,若读取到0则表明数据采集结束{*(buf+i) = P0;delay10ms(10); // 延时100msP0 = 0xff;i++;}*(buf+i) = 0; // 缓冲区最后一个字节为0表示数据结束/* 读要访问的分机地址*/P0 = 0xff;addr = P0;/* 串口初始化*/init_serial(); // 初始化串口EA = 0; // 关闭所有中断/* 发送地址帧并接收应答信息,如果接收的信号与发送的地址信息不同,则重新发送地址帧*/tmp = addr-1;while(tmp != addr){/* 发送从机地址*/TB8 = 1; // 发送地址帧SBUF = addr;while(!TI);TI = 0;/* 接收从机应答*/RI = 0;while(!RI);tmp = SBUF;RI = 0;}/* 发送数据并接收校验信息,如果接收的信号为0FH,表示从机接收成功,否则将重新发送该组数据*/tmp = __ERR_;while(tmp != __SUCC_){send_data(buf); // 发送数据RI = 0;while(!RI);tmp = SBUF;RI = 0;}while(1); // 程序结束,进入死循环}/* 初始化串口*/void init_serial(){TMOD = 0x20; //定时器T1使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0xd0; //工作方式3,9位数据位,波特率9600bps,允许接收}/* 发送数据*/void send_data(unsigned char *buf){unsigned char len; // 保存数据长度unsigned char ecc; // 保存校验字节len = strlen(buf); // 计算要发送数据的长度ecc = len; // 开始进行校验字节计算/* 发送数据长度*/TB8 = 0; // 发送数据帧SBUF = len; // 发送长度while(!TI);TI = 0;/* 发送数据*/for(i=0; i<len; i++){ecc = ecc^(*buf); // 计算校验字节TB8 = 0; // 发送数据帧SBUF = *buf; // 发送数据buf++;while(!TI);TI = 0;}/* 发送校验字节*/TB8 = 0; // 发送数据帧SBUF = ecc; // 发送校验字节while(!TI);TI = 0;}/* 延时10ms,精度较低,参数count为延时时间*/ void delay10ms(unsigned int count){unsigned int i, k;unsigned char j;unsigned int tmp;tmp = (int)((100*_MHZ_)/12);for(i=0; i<count; i++)for(j=0; j<100; j++)for(k=0; k<tmp; k++);}#endif51单片机多机通信程序(从机部分)/* multi_s.c *//* 多机通信的从机部分*/#ifndef __MULTI_S_C__#define __MULTI_S_C__#include <AT89X51.H>#include <STRING.H>#define __MAX_LEN_ 64 // 数据最大长度#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz)/* 以下为程序协议中使用的握手信号*/#define __SUCC_ 0x0f // 数据传送成功#define __ERR_ 0xf0 // 数据传送错误void init_serial(); // 串口初始化unsigned char recv_data(unsigned char *buf); // 接收数据void Beep_ok(); // 蜂鸣表示数据接收ok,该函数代码未给出void main() {char buf[__MAX_LEN_];unsigned char i = 0;unsigned char tmp = 0xff;unsigned char addr; // 保存本机地址/* 从P1口读取本机地址*/P1 = 0xff;addr = P1;/* 串口初始化*/init_serial(); // 初始化串口EA = 0; // 关闭所有中断/* 进入设备应答阶段*/while(1){SM2 = 1; // 只接收地址帧/* 如果接收到的地址帧不是本机地址,则继续等待*/ tmp = addr-1;while(tmp != addr){RI = 0;while(!RI);tmp = SBUF;RI = 0;}/* 发送应答信号,并做好接收数据的准备*/TI = 0;TB8 = 0; // 主机不检测该位SBUF = addr;while(!TI);TI = 0;SM2 = 0; // 允许接收数据信息/* 数据接收*/tmp = 0xff;while(tmp == 0xff) // 如果数据校验失败则重新接收数据{tmp = recv_data(buf); // 校验失败返回0xff,检测到地址帧则返回0xfe,接收成功则返回0}if(tmp == 0xfe) // 在数据接收过程中,如果发现地址帧,则重新开始整个接收过程continue;Beep_ok(); // 蜂鸣表示数据接收成功}}/* 初始化串口*/void init_serial(){TMOD = 0x20; //定时器T1使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0xd0; //工作方式3,9位数据位,波特率9600bps,允许接收}/* 接收数据,注意该函数使用buf指向的缓冲区保存数据,在数据末尾使用’\0’表示数据结束* 返回值为0,数据校验成功,返回值为0xfe,接受过程中接收到地址帧,返回值为0xff,数据校验失败*/unsigned char recv_data(unsigned char *buf){unsigned char len; // 该字节用于保存数据长度unsigned char ecc; // 该字节用于保存校验字节unsigned char i,tmp;/* 接收数据长度*/RI = 0;while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfereturn 0xfe;len = SBUF;RI = 0;/* 使用len的值为校验字节ecc赋初值*/ecc = len;/* 接收数据*/for(i=0; i<len; i++){while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfe return 0xfe; *buf = SBUF; // 接收数据ecc = ecc^(*buf); // 进行字节校验RI = 0;buf++;}*buf = 0; // 表示数据结束/* 接收校验字节*/while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfe return 0xfe; tmp = SBUF;RI = 0;/* 进行数据校验*/ecc = tmp^ecc;if(ecc != 0) // 校验失败{*(buf-len) = 0; // 清空数据缓冲区TI = 0; // 发送校验失败信号TB8 = 0;SBUF = __ERR_;while(!TI);TI = 0;return 0xff; // 返回0xff表示校验错误} TI = 0; // 校验成功TB8 = 0;SBUF = __SUCC_;while(!TI);TI = 0;return 0; // 校验成功,返回0}#endif。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档