485通讯协议程序怎么写(51单片机的485通信程序案例)
- 格式:doc
- 大小:12.50 KB
- 文档页数:1
//-----------------------函数声明,变量定义--------------------------------------------------------#include <reg51.h>sbit RE_DE=P1^0;#define COUNT 10 // 定义接收缓冲区大小#define ADD 5 //定义设备地址unsigned char buffer[COUNT]; //定义接收缓冲区unsigned char point; //定义接收数据个数指示变量void UART_init(); //串口初始化函数void COM_send(void); //串口接收函数unsigned char CLU_checkdata(void);//计算校验位函数//--------------------------------------------------------------------------------------------------// 函数名称:UART_init()串口初始化函数// 函数功能:在系统时钟为11.059MHZ时,设定串口波特率为9600bit/s// 串口接收中断允许,发送中断禁止//--------------------------------------------------------------------------------------------------void UART_init(){//初始化串行口和波特率发生器SCON =0x0F0; //选择串口工作方式为3,打开接收允许TMOD =0x21; //定时器1工作在方式2,定时器0工作在方式1TH1 =0xfd; //实现波特率9600(系统时钟11.0592MHZ)TL1 =0xfd; //实现波特率9600(系统时钟11.0592MHZ)TR1 =1; //启动定时器T1ET1 =0;ES=1; //允许串行口中断PS=1; //设计串行口中断优先级EA =1; //单片机中断允许SM2=1; //设备处于地址监听状态}//--------------------------------------------------------------------------------------------------// 函数名称:com_interrup()串口接收中断处理函数// 函数功能:接收包括起始位0xFE,地址位和终止位0xEF在内的十位数据到数据缓冲区,// 地址不匹配,则接收到的是无效数字,不写到接收缓冲区//--------------------------------------------------------------------------------------------------com_interrupt(void) interrupt 4 using 3{unsigned char RECEIVR_buffer;if(RI){ //处理接收中断RI=0; //清除中断标志位RECEIVR_buffer=SBUF; //接收串口数据if(point==0) //如果还没有接收到起始位{if(RECEIVR_buffer==0xFE) //判断是否起始标志位buffer[point++]=RECEIVR_buffer;//起始正确,接收起始位elsepoint=0; //不是,继续等待起始位}else if(point==1) //是否地址位{if(RECEIVR_buffer==ADD) //判断地址是否匹配buffer[point++]=RECEIVR_buffer;//地址匹配,接收开始接收elsepoint=0; //不匹配,继续下一个起始位}else if(point>0&&point<10) //判断是否接收够十位数据buffer[point++]=RECEIVR_buffer; //不够,把接收到的数据放入接收缓存区else point=0; //缓冲区已满,清除缓存区内数据重新接收}if(TI) //串口发送中断{TI=0; //清除发送中断}}//--------------------------------------------------------------------------------------------------// 函数名称:COM_send()串口发送函数// 函数功能:把数据缓冲区的十位数据发送出去//--------------------------------------------------------------------------------------------------void COM_send(void){RE_DE=1; //设置MAX483进入发送状态for(point=0;point<=10,TI=1;point++) //连续发送十位数据//把缓存区的数据都发送到串口{SBUF=buffer[point];TI=0;}RE_DE=0; //设置MAX483进入接收状态}//--------------------------------------------------------------------------------------------------// 函数名称:主函数// 函数功能:调度个子函数,完成通信过程//--------------------------------------------------------------------------------------------------void main(void){UART_init(); //初始化串口do{}while(point!=10); //判断数据是否接收完成COM_send(); //地址匹配,数据完整接收,调用发送程序通知主机SM2=0; //设置为点对点通信状态}。
在工业控制、电力通讯、智能仪表等领域,通常情况下是采用串口通信的方式进行数据交换。
最初采用的方式是RS232接口,由于工业现场比较复杂,各种电气设备会在环境中产生比较多的电磁干扰,会导致信号传输错误.除此之外,RS232接口只能实现点对点通信,不具备联网功能,最大传输距离也只能达到几十米,不能满足远距离通信要求。
而RS485则解决了这些问题,数据信号采用差分传输方式,可以有效的解决共模干扰问题,最大距离可以到1200米,并且允许多个收发设备接到同一条总线上。
随着工业应用通信越来越多,1979年施耐德电气制定了一个用于工业现场的总线协议Modbus协议,现在工业中使用RS485通信场合很多都采用Modbus协议,本节课我们要讲解一下RS485通信和Modbus协议。
单单使用一块KST-51开发板是不能够进行RS485实验的,应很多同学的要求,把这节课作为扩展课程讲一下,如果要做本课相关实验,需要自行购买USB转485通信模块。
18.1 RS485通信实际上在RS485之前RS232就已经诞生,但是RS232有几处不足的地方:1、接口的信号电平值较高,达到十几V,容易损坏接口电路的芯片,而且和TTL电平不兼容,因此和单片机电路接起来的话必须加转换电路。
2、传输速率有局限,不可以过高,一般到几十Kb/s就到极限了。
3、接口使用信号线和GND与其他设备形成共地模式的通信,这种共地模式传输容易产生干扰,并且抗干扰性能也比较弱。
4、传输距离有限,最多只能通信几十米。
5、通信的时候只能两点之间进行通信,不能够实现多机联网通信。
针对RS232接口的不足,就不断出现了一些新的接口标准,RS485就是其中之一,他具备以下的特点:1、我们在讲A/D的时候,讲过差分信号输入的概念,同时也介绍了差分输入的好处,最大的优势是可以抑制共模干扰。
尤其工业现场的环境比较复杂,干扰比较多,所以通信如果采用的是差分方式,就可以有效的抑制共模干扰。
485通信程序(51单片机)什么是485通信?RS-485是一种串行通信协议,它使用差分信号传输数据。
485通信支持了在两个或以上设备之间传输数据的需求,比如用于电子计算机、通信设备、工业自动化等等。
RS-485已广泛应用于数控机床、自动化设备控制等领域中。
单纯的485通信包含四种通信模式:点对点、总线形、多主机和简介式通信。
其中,点对点通信指的是一对一的通信方式;总线形通信指的是一对多的群通信方式,所有设备都在同一条总线上发送和接收数据;多主机通信指的是多台主机的通信方式,多个设备都可以同时发送数据;简介式通信是一种用于仅需要发送少量数据的情况的通信方式。
下面介绍一下485通信的部分基本知识1.485通信的传输距离远,一般可以达到1200米。
2.485通信具有较强的抗干扰能力。
3.485通信使用差分信号进行传输,信号稳定,传输速率也比较快。
4.485通信可以支持多个设备同时进行通信,但是在同一时间内只有一个设备可发送数据。
5.在采用485通信时,一定要注意通讯端口的设置,如波特率、数据位、停止位等。
程序实现原理该程序使用了51单片机作为主控制器实现了基本的485通信,具体实现如下:1.通信模式的设置在程序开始时,需要设置通信模式。
如果通信模式为点对点通信,则可以直接使用UART通信模块进行通信;如果是多点通信,则需要使用485通信芯片。
2.通讯端口的配置在进行485通讯时,需要进行通讯端口的配置,包括波特率、数据位、停止位等参数的设定。
在485通信模式下,只有一个设备可为主设备,其他设备均为被设备。
在发送数据时,主设备的TXD口要与外部总线的D+口相连,而D-口不连接,从设备的TXD口要与D-口相连,而D+口不连接。
在接收数据时,主设备的RXD口要与D+口相连,而D-口不连接,从设备的RXD口要与D-口相连,而D+口不连接。
3.数据的发送和接收在发送和接收数据时,需要采用特定的方式进行报文的封装和解析。
/* 以下为单片机串口485通讯程序,从机程序(当然也适用于主机程序),主机发送可以先用串口帮手软件来调试,经过Keil uVision4实际测试,测试效果如结尾图片所示, 大部分来自网络,只是改了两个地方: len = sizeof(dbuf),if(i >=( __ERRLEN+1)) // 帧超长,错误,返回,就可以实现了,其中的原因自已体会吧*/#ifndef __485_C__#define __485_C__#include <reg51.h>#include <string.h>#include <stdio.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int/* 通信命令*/#define __ACTIVE_ 0x01 // 主机询问从机是否存在#define __GETDATA_ 0x02 // 主机发送读设备请求#define __OK_ 0x03 // 从机应答#define __STATUS_ 0x04 // 从机发送设备状态信息#define __MAXSIZE 0x08 // 缓冲区长度#define __ERRLEN 12 // 任何通信帧长度超过12则表示出错//uchar dbuf[__MAXSIZE]; // 该缓冲区用于保存设备状态信息uchar dbuf[__MAXSIZE];//={0,1,2,3,4,5,6,7}; // 该缓冲区用于保存设备状态信息uchar dev; // 该字节用于保存本机设备号sbit M_DE = P1^0; // 驱动器使能,1有效sbit M_RE = P1^1; // 接收器使能,0有效void get_status(); // 调用该函数获得设备状态信息,函数代码未给出void send_data(uchar type, uchar len, uchar *buf); // 发送数据帧bit recv_cmd(uchar *type); // 接收主机命令,主机请求仅包含命令信息void send_byte(uchar da); // 该函数发送一帧数据中的一个字节,由send_data()函数调用void main(){uchar type;uchar len;/* 系统初始化*/P1 = 0xff; // 读取本机设备号//dev = (P1>>2);dev = 0x01;TMOD = 0x20; // 定时器T1使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0x50; // 工作方式1,波特率9600bps,允许接收ES = 0; // 关闭串口中断//IT0 = 0; // 外部中断0使用电平触发模式//EX0 = 1; // 开启外部中断0EA = 1; // 开启中断/* 主程序流程*/while(1) // 主循环{if(recv_cmd(&type) == 0) // 发生帧错误或帧地址与本机地址不符,丢弃当前帧后返回continue;switch(type){case __ACTIVE_: // 主机询问从机是否存在send_data(__OK_, 0, dbuf); // 发送应答信息,这里buf的内容并未用到break;case __GETDA TA_:// len = strlen(dbuf);//在C51中不能这个函数计算unsigned char型,这个函数只能计算char型len = sizeof(dbuf);// len =0x08;send_data(__STA TUS_, len, dbuf); // 发送设备状态信息break;default:break; // 命令类型错误,丢弃当前帧后返回}}}void READSTATUS() interrupt 0 using 1 // 产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1{get_status(); // 获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一字节置0表示数据结束}/* 该函数接收一帧数据并进行检测,无论该帧是否错误,函数均会返回* 函数参数type保存接收到的命令字* 当接收到数据帧错误或其地址位不为0时(非主机发送帧),函数返回0,反之返回1*/bit recv_cmd(uchar *type){bit db = 0; // 当接收到的上一个字节为0xdb时,该位置位bit c0 = 0; // 当接收到的上一个字节为0xc0时,该位置位uchar data_buf[__ERRLEN]; // 保存接收到的帧__ERRLEN=12;uchar tmp;uchar ecc = 0;uchar i;M_DE = 0; // 置发送禁止,接收允许M_RE = 0;/* 接收一帧数据*/i = 0;while(!c0) // 循环直至帧接收完毕{RI = 0;while(!RI);tmp = SBUF;RI = 0;if(db == 1) // 接收到的上一个字节为0xdb{switch(tmp){case 0xdd:data_buf[i] = 0xdb; // 0xdbdd表示0xdbecc = ecc^0xdb;db = 0;break;case 0xdc:data_buf[i] = 0xc0; // 0xdbdc表示0xc0ecc = ecc^0xc0;db = 0;break;default:return 0; // 帧错误,返回}i++;}switch(tmp) // 正常情况{case 0xc0: // 帧结束c0 = 1;break;case 0xdb: // 检测到转义字符db = 1;break;default: // 普通数据data_buf[i] = tmp; // 保存数据ecc = ecc^tmp; // 计算校验字节i++;}//if(i == __ERRLEN) // 帧超长,错误,返回if(i >=( __ERRLEN+1)) // 帧超长,错误,返回return 0;}/* 判断帧是否错误*/if(i<4) // 帧过短,错误,返回return 0;if(ecc != 0) // 校验错误,返回return 0;if(data_buf[0] != dev) // 非访问本机命令,错误,返回return 0;*type = data_buf[1]; // 获得命令字return 1; // 函数成功返回}/* 该函数发送一帧数据帧,参数type为命令字、len为数据长度、buf为要发送的数据内容*/void send_data(uchar type, uchar len, uchar *buf){uchar i;uchar ecc = 0; // 该字节用于保存校验字节M_DE = 1; // 置发送允许,接收禁止M_RE = 1;send_byte(dev); // 发送本机地址ecc = dev;send_byte(type); // 发送命令字ecc = ecc^type;send_byte(len); // 发送长度ecc = ecc^len;for(i=0; i<len; i++) // 发送数据{send_byte(*buf);ecc = ecc^(*buf);buf++;}send_byte(ecc); // 发送校验字节TI = 0; // 发送帧结束标志SBUF = 0xc0;while(!TI);TI = 0;}/* 该函数发送一个数据字节,若该字节为0xdb,则发送0xdbdd,若该字节为0xc0则,发送0xdbdc */void send_byte(uchar da){switch(da){case 0xdb: // 字节为0xdb,发送0xdbdd TI = 0;SBUF = 0xdb;while(!TI);TI = 0;SBUF = 0xdd;while(!TI)TI = 0;break;case 0xc0: // 字节为0xc0,发送0xdbdcTI = 0;SBUF = 0xdb;while(!TI);TI = 0;SBUF = 0xdc;while(!TI)TI = 0;break;default: // 普通数据则直接发送TI = 0;SBUF = da;while(!TI);TI = 0;}}#endif/* 调试结果*/。
本实验实现的功能和12.5节的完全相同,也是通过串行口接收上位机的启、停协议,然后根据协议来控制计数的启动和暂停,单片机每次计数过0向上位机返回过0消息。
本实验的主要代码如下:main.c源文件//main.c#include <reg51.h> //包含头文件#include "fun.h"void Timer0_interrupt() interrupt 1{TH0 = T0_50ms >> 8; //重装初值TL0 = T0_50ms;if ((++ count_in_T0) == 20) //count_in_T0自加到20,计时1s{count_in_T0 = 0;if ( (++ display_num) ==60){ //display_num自加1后判断是否等于60display_num = 0;//上发过0消息send(0xf0);send(0x01);send(0xf1);}}}void USART_interrupt() interrupt 4{char checkXOR;if (RI) //接收中断{RI = 0;reciev[rec_num] = SBUF;rec_num ++;if ((rec_num == 3) && (reciev[0] == 0x0f) )//接收到3字节,并且包头正确{checkXOR = reciev[0] ^ reciev[1];if (checkXOR == reciev[2] ) //如果异或校验正确,判断命令 {switch (reciev[1]){case 0x01:TR0 = 1; //启动rec_num = 0; //指令正确,清空缓冲区break;case 0x02:TR0 = 0; //暂停rec_num = 0; //指令正确,清空缓冲区break;default: //如果指令不正确,缓冲区左移reciev[0] = reciev[1];reciev[1] = reciev[2];rec_num --;break;}}}}if (TI){TI = 0;}}main(){unsigned char shi, ge; //定义十位、个位要输出的数据 ms_delay(100);init_port();init_usart();init_timer();dir = 0; //485接收数据rec_num = 0;display_num = 0;count_in_T0 = 0;//把两个数码管都关闭en2 = 1;en1 = 1;EA = 1; //开总中断while(1){shi = display_num / 10;ge = display_num % 10;display(shi,ge);}}fun.h头文件代码如下://fun.h//定义端口寄存器sfr P0M0 = 0X93;sfr P0M1 = 0X94;sfr P1M0 = 0X91;sfr P1M1 = 0X92;sfr P2M0 = 0X95;sfr P2M1 = 0X96;sfr P3M0 = 0Xb1;sfr P3M1 = 0Xb2;#define fosc 11059200L#define T0_50ms (65536 - (fosc/12/50000)) //50ms定时参数sbit en1 = P2^6;sbit en2 = P2^7;sbit dir = P3^2; //485方向控制unsigned char display_num,count_in_T0; //计数值、进入定时器的次数char reciev[3], rec_num; //保存接收到的数据/*共阴极数码管0~9的字形码"0" 3FH "5" 6DH"1" 06H "6" 7DH"2" 5BH "7" 07H"3" 4FH "8" 7FH"4" 66H "9" 6FH*/const unsigned char seg7[10] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};void init_port(){P0M1 = 0xff;P0M0 = 0xff;P2M1 |= 0xc0;P2M0 |= 0xc0;P3M1 = 0x00; //P3.2准双向口模式P3M0 = 0x00;}void init_usart(){SM0 = 0;SM1 = 1;REN = 1;ES = 1;}void init_timer(){TMOD |= 0X01; //定时器0模式1,16bitTH0 = T0_50ms >> 8; //TH0 = T0_50ms / 256TL0 = T0_50ms; //TL0 = T0_50ms % 256ET0 = 1; //允许T0中断TMOD |= 0X20; //定时器1模式2,8bit自动重装 TH0 = 0xfd; //对应波特率9600TL0 = 0xfd;ET1 = 1; //允许T1中断TR1 = 1;}//定义延时函数void ms_delay(unsigned int t){unsigned int i;for (t; t > 0; t--) //外层循环t次for (i = 110;i > 0; i--) //内层循环110次;}void display(unsigned char c2, unsigned char c1) {P0 = seg7[c2]; //送入十位的段码en2 = 0; //显示DS2ms_delay(10);en2 = 1; //关闭DS2P0 = seg7[c1]; //送入个位的段码en1 = 0; //显示DS1ms_delay(10);en1 = 1; //关闭DS1}void send(char c){dir = 1; //485发送数据SBUF = c;while(!TI); //等待发完dir = 0; //485接收数据}讲解:本实验和12.5节的串行口收发实验基本相同,单片机串行口经由MAX1487芯片收发数据的过程对编程人员来说是完全透明的,我们只用跟平时操作串行口一样的方法来控制就可以了。
#include〈reg52.h〉#include<string。
h〉#define uchar unsigned char#define uint unsigned int/*通信命令*/#define _ACTIVE_ 0x01 // 主机询问从机是否存在#define _GETDATA_ 0x02 //主机发送读设备请求#define _OK_ 0x03 //从机应答#define _STATUS_ 0x04 //从机发送设备状态信息#define _MAXSIZE 0x08 //缓冲区长度#define _ERRLEN 12 //任何通信帧长度超过12则表示出错uchar dbuf[MAXSIZE] ;//该缓冲区用于保存设备状态信息uchar dev; //该字节用于保存本机设备号sbit M_DE = P1^0; //驱动器使能,1有效sbit M_RE = P1^1; //接收器使能,0 有效void get_status();//调用该函数获得设备状态信息,函数全码未给出void send_data(uchar type,uchar len,uchar *buf);//发送数据帧bit recv_cmd(uchar *type); //接收主机命令,主机请求包含命令信息。
void send_byte(uchar da); //该函数发送一帧数据中的一个字节,由send_data()函数调用void main(){uchar type;uchar len;/*系统初始化*/P1 = 0xff ;//读取本机设备号dev = (P1>〉2);TMOD = 0x20;//定时器T1使用方式2TH1 = 250;TL1 = 250;TR1 = 1;//开始计时PCON = 0x80;//SMOD = 1;SCON = 0x50;//工作方式1,波特优选法9600bps,允许接收ES = 0; // 关闭串品中断IT0 = 0; //外部中断0使有电平触发模式EX0 = 1; // 开启外部中断0EA = 0;//开启总中断/*主程序流程*/while(1){if(recv_cmd(&type) ==0) //发送帧错误或帧地址与本机地址不符,丢弃当前帧后返回continue;switch(type){case _ACTIVE_://主机询问从机是否存在send_data(_OK_,0,dbuf);// 发送应答信息,这里的buf 的内容并未用到break;case _GETDA TA_: //主机发送读设备请求len = strlen(dbuf);snd_data(_STA TUS_,len,dbuf) ;// 发送设备信息break;default:break;//命令类型错误,丢弃当前帧返回}}}}void READSTATUS() interrput 0 using 1 //产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1{get_status(); //获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一个字节置0表示数据结束}}/*该函数接收一帧数据度进行检测,无论该帧是否错误,函数均会返回。
rs485协议详解单片机编程RS485协议详解单片机编程1. 协议双方基本信息甲方:(以下简称“甲方”)地址:联系人:电话:邮箱:乙方:(以下简称“乙方”)地址:联系人:电话:邮箱:2. 各方身份、权利、义务、履行方式、期限、违约责任2.1 甲方身份、权利、义务、履行方式、期限、违约责任甲方为RS485通讯协议的发起方,其权利、义务、履行方式、期限、违约责任如下:权利:1. 确定通讯协议的实现方案;2. 对乙方提供的通讯协议实现方案进行审核并提出修改意见;3. 在付款后,获得乙方提供的符合要求的实现方案。
义务:1. 提供通讯协议的需求文档及其他相关资料;2. 对乙方提供的通讯协议实现方案进行评估并提出需要修改的意见;3. 对于乙方提供的符合要求的实现方案进行支付。
履行方式:1. 双方确认和签署本协议后,甲方向乙方提供通讯协议的需求文档及其他相关资料;2. 乙方拟定通讯协议实现方案并提交给甲方审查;3. 甲方对乙方提供的通讯协议实现方案进行评估并提出需要修改的意见,乙方对意见进行修改并重新提交审查;4. 经过双方的多次确认和修改后,乙方提供符合甲方要求的实现方案,并向甲方提供;5. 甲方对乙方提供的符合要求的实现方案进行支付。
期限:本协议签署后,甲乙双方应在合理时间内完成上述流程。
违约责任:1. 若乙方违约,甲方有权解除本协议,并要求乙方承担相应的赔偿责任;2. 若甲方违约,应承担相应的违约责任。
2.2 乙方身份、权利、义务、履行方式、期限、违约责任乙方为RS485通讯协议的实现方,其权利、义务、履行方式、期限、违约责任如下:权利:1. 按照甲方提供的需求文档及其他相关资料进行通讯协议实现方案的拟定;2. 享有按约定支付的费用。
义务:1. 按照甲方提供的需求文档及其他相关资料提供符合要求的通讯协议实现方案;2. 对于甲方提出的修改意见,及时进行修改并重新提交审查。
履行方式:1. 双方确认和签署本协议后,甲方向乙方提供通讯协议的需求文档及其他相关资料;2. 乙方拟定通讯协议实现方案并提交给甲方审查;3. 甲方对乙方提供的通讯协议实现方案进行评估并提出需要修改的意见,乙方对意见进行修改并重新提交审查;4. 经过双方的多次确认和修改后,乙方提供符合甲方要求的实现方案,并向甲方提供;5. 甲方对乙方提供的符合要求的实现方案进行支付。
“485双机通信”程序设计说明1 程序设计思路与方法本案例程序设计主要分为:串行口通信、按键检测和数码管显示3个部分。
两块单片机初始化后均为接收状态,通过按键扫描模块对KEY1,KEY2,KEY3进行按键判断,单片机通过对P3.3和P1.7的电平检测,每检测到端口有低电平产生则相应实现变量display的加减,使P2.3=0将数据传递给P0口通过数码管显示出来,当按下KEY1键触发外部中断0,单片机由接收态转换为发送态,将数据通过485模块传递给另一块单片机显示出来,然后立即返回接收状态,从而实现双机通信。
1.1 宏定义#define S2RI 0x01 //接收中断请求标志位#define S2TI 0x02 //发送中断请求标志位#define NONE_PARITY 0 //无校验#define PARITYBIT NONE_PARITY //定义校验位#define FOSC 11059200L //系统时钟频率#define BAUD 9600 //串口波特率#define TM (65536-(FOSC/4/BAUD)) //定时器初始时间1.2 定义变量bit busy ; //串口忙信号标志(1表示正在发送,0表示空闲)uint8 rev_data ; //串口接收的数据uint8 display ; //数码管显示数据uint8 seg_sel[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00}; //数码管段选数组,显示0-f 1.3 相关函数void Uart2Init(void); //串行口初始化函数void CPUInit(void); //CPU初始化函数,配置相关寄存器和IO口模式void delay(void); //延时函数void ser2_int(void) interrupt 8 using 1 //串口中断处理函数void ex_int0() interrupt 0 //外部中断0处理函数开始If 按键3被按下Then 当前值加一If 按键2被按下Then 当前值减一按键扫描初始化(串口、数码管等)485处于接收态485转换为发送态发送数据(串口中断)485转换回接收态退出按键中断进入按键中断当按键1被按下时,进入中断图1 双机通信流程图2 相关寄存器的配置 2.1 选择485芯片引脚:P_SW2:外围设备功能切换控制寄存器2(不可位寻址)串口2可在2个地方切换,由S2_S 控制位来选择。
基于RS-485协议实现单片机与单片机之间的通信摘要:介绍以RS-485为通信方式的两个单片机之间的通信,同时给出单片机与单片机之间的通信程序设计。
关键词:RS-485通信单片机串行通信0 引言随着工业化的进展,人们对现场仪表的要求愈来愈高,为了知足操纵室对现场的实时监控,确保现场数据的实时获取,需要用一种方式将现场情形实时反映给操纵室,咱们研究了一种方便简单功、能优越的通信方式:用RS-485实现现场单片机和操纵室单片机的实时通信。
通过操作操纵室单片机就能够实现对现场单片机的操作,节省了大量的时刻和相应的人力。
1、RS-485通信协议RS-485采纳平稳传输方式,连接时需要在传输线上接终接电阻。
RS-485能够采纳二线与四线方式,二线制可实现真正的多点双向通信,采纳四线连接时,即只能有一个主(Master)设备,其余为从设备,不管是四线仍是二线连接方式总线上最多可接32个设备。
RS-485最大传输距离约为1219米,最大传输速度为10Mb/s。
平稳双绞线的长度与传输速度成反比,在100kb/s速度以下,才可能利用规定最长的电缆长度。
只有在很短的距离下才能取得最高速度传输。
一样100米长双绞线最大传输速度仅为1Mb/s。
RS-485需要2个终接电阻,其阻值要求等于传输电缆的特性阻抗,终接电阻接在传输总线的两头。
在短距离传输时可不需终接电阻,即一样在300米以下不需终接电阻。
本设计中采纳的485通信元件是75LBC184,该器件带有内置高能量瞬变噪声爱惜装置,可提供靠得住的低本钱的直连(不带绝缘变压器)数据线接口,不需要任何外部元件。
2、单片机与单片机的通信系统本设计中单片机选用C8051F020,该单片机有100个功能引脚,其中有64个通用I/O端口。
C8051F020内有2个增强型串行口:UARTO和UART1,这两个串行口都能够工作在全双工异步方式或半双工同步方式,而且支持多处置器通信。
75LBC184与单片机连接时只需将R和D端别离与单片机的RXD 和TXD 相连即可。
485通讯协议程序怎么写(51单片机的485通信程序案例)
RS-485总线接口是一种常用的串口,具有网络连接方便、抗干扰性能好、传输距离远等优点。
RS-485收发器采用平衡发送和差分接收,因此具有抑制共模干扰的能力,加上收发器具有高的灵敏度,能检测到低达200mv的电压,可靠通信的传输距离可达数千米。
使用RS-485总线组网,只需一对双绞线就可实现多系统联网构成分布式系统、设备简单、价格低廉、通信距离长。
51单片机的485通信程序
#ifndef __485_C__ #define __485_C__
#include 《reg51.h》
#include 《string.h》
#define unsigned char uchar
#define unsigned int uint
/* 通信命令*/
#define __ACTIVE_ 0x01 // 主机询问从机是否存在
#define __GETDATA_ 0x02 // 主机发送读设备请求
#define __OK_ 0x03 // 从机应答
#define __STATUS_ 0x04 // 从机发送设备状态信息
#define __MAXSIZE 0x08 // 缓冲区长度
#define __ERRLEN 12 // 任何通信帧长度超过12则表示出错
uchar dbuf[__MAXSIZE]; // 该缓冲区用于保存设备状态信息
uchar dev; // 该字节用于保存本机设备号
sbit M_DE = P1。