1、485通讯例程RS-485总线的接口电路硬件设计 笔者在火灾自动报警系统的联网设计中,经大量试验,发现在使用RS-485总线时,如果简单地按常规方式设计电路,那么在实际工程中可能存在以下两个问题:一是通信数据收发不可靠;二是在多机通信方式下,一个节点的故障(如死机)往往会使得整个系统的通信框架崩溃,而且给故障的排查带来困难。针对上述问题,对485总线接口的软硬件设计采取了有效的改进措施,大大提高了联网系统的可靠性和稳定性。 1 RS-485总线接口硬件电路的设计如图1所示,89C51单片机自带异步通信接口,外接RS-485收发器75LHCl84,89C5l的异步通信口与75LBCl84之间采用
2、3片光耦进行电气隔离。1.1 75LBCl84 DE控制端的设计由于火灾报警控制系统中主机与分机相隔较远,通信线路的总长度往往超过l000m,而分机系统上电或复位又常常不在同一个时刻完成。如果此时某个75LBCl84的DE端电位为1,那么它的485总线输出将处于发送状态,也就是占用了通信总线,这样其他分机就无法与主机进行通信。这种情况尤其表现在某个分扰出现异常情况(如死机)下,会使整个系统通信崩溃。因此在电路设计时,应保证系统上电复位时75LBCl84的DE端电位为O。由于89C51在复位期间,IO口输出高电平,故图1中电路的接法可有效地解决复位期间分机“咬”总线的问题。12 隔离光耦电路的参
3、数选取在火灾报警系统中,要对现场情况进行实时监控及响应,因此通信数据的波特率往往做得较高(本系统中控制器与显示盘之间的通信速率在6250bps)。限制通信波特率提高的“瓶颈”并不是现场的导线(现场施工一般使用非屏蔽的双绞线),而是单片机系统进行信号隔离的光耦电路。此处采用TIL117,电路设计中可以考虑采用高速光耦,如6N137、6N136等芯片;也可以优化普通光耦电路参数的设计,使之工作在最佳状态。例如:电阻R2、R3如果选取得较大,则会使光耦的发光管由截止进入饱和变得较慢;如果选取得过小,则退出饱和会很慢。所以这两只电阻的数值要精心选取,不同型号的光耦及驱动电路使得这两个电阻值略有差异,在
4、电路设计中应特别慎重,通常需要通过实验确定。13 485总线输出电路部分的设计输出电路的设计要充分考虑线路上的各种干扰及线路特性阻抗的匹配。信号在传输过程中会产生电磁干扰和终端反射使有效信号和无效信号在传输线上相互叠加,严重时会使通信无法正常进行。为解决这一问题,某些芯片的驱动器设计成限斜率方式,使输出信号边沿不要过陡,以免在传输线上产生过多的高频分量,从而有效地扼制干扰的产生。在没计选型时,最好选择具有该种功能的RS-485接口芯片。同时,RS-485接口芯片在使用、焊接或设备的运输途中都有可能受到静电的冲击而损坏;而且由于工程环境比较复杂,现场常有各种形式的干抗源,在传输线架设于户外的使用
5、场合,接口芯片乃至整个系统还有可能遭致雷电的袭击。所以485总线的传输端一定要加有保护措施,在电路设计中选用抗静电或抗雷击的芯片可有效避免此类损失。本系统中选用的是75LBCl84,它的驱动器不但设计成限斜率方式输出,而且能抗雷电的冲击,承受高达8kV的静电放电冲击,在实际使用中效果十分理想。考虑到线路的特殊情况(例如某台分机的485芯片被击穿短路),为防止总线中其他分机的通信受到影响,在75LBCl84的485信号输出端串联了两个20的电阻R10和R11。这样本机的硬件故障就不会使整个总线的通信受到影响。在消防报警产品的现场拖工中,通信载体一般采用双绞线。其特性阻抗为120左右,所以线路设计
6、时,在485网络传输线的始端和末端应各接1只120的匹配电阻(如图1中的R8),以减少线路上传输信号的反射。由于RS-485芯片的特性,接收器的检测灵敏度为200mV,即差分输入端VA-VB+200mV,输出逻辑l,VA-VB-200mV,输出逻辑0;而当A、B端屯位差的绝对值小于200mv时,输出不确定。如果在总线上所有发送器被禁止,则接收器输出逻辑0,这会误认为通信帧的起始引起工作不正常。解决这个问题的办法是人为地使A端电位高于B两端电位。这样RXD的电平在485总线不发送期间(总线悬浮时)呈现唯一的高电平,89C5l单片机就不会被误中断而收到乱字符。通过在485电路的A、B输出端加接上、
7、下拉电阻R7、R9,可以很好地解决这个问题。2 RS-485总线接口软件设计RS-485接口的软件设计对系统联网的可靠性有很大影响。由于485总线是异步半双工的通信总线,在某一个时刻总线只可能呈现一种状态,所以这种方式一般适用于主机对分机的查询方式通信,总线上必然有一台始终处于主机地位的设备在巡检其他分机,这就需要制定一套合理的通信协议来协调总线的分时共用。这里采用的是数据包通信方式,通信数据是成帧、成包发送的,每包数据都由引导码,长度码、地址码、命令码、内容和校验码等部分组成。其中:引导码是用于同步每一包数据的引导头;长度码是这一包数据的总长度;命令码是主机对分机(或分机应答主机)的控制命令
8、;地址码是分机的本机地址号;“内容”是这一包数据里的各种信息;校验码是这一包数据的校验标志,可以采用奇偶校验、“和”校验以及CRC校验等不同方式。在设计RS-485通信软件时,尤其要注意对485控制端DE的软件编程。为了保证数据收发可靠,在485总线状态切换时需要加适当延时,再进行数据的收发。具体做法是在数据发送状态下,先将控制端DE置1;延时1ms左右后,再发送有效的数据。一个数据包发送结束后再延时lms,然后将控制端DE清0。控制端DE经过这样处理后,会使总线在状态切换时有一个稳定的工作过程。结语RS-485总线具有电路设计简单、软件设计方便、成本低等优点,在火灾报警系统中应用非常广泛。本
9、系统经过对软硬件接口进行改进后,大大提高了通信可靠性、稳定性,可满足消防报警系统的实际需要。采用本文改进的485总线接口已成功地应用于数百个消防报警系统,未出现任何通信故障。应用程序main() /初始化 TMOD= 0x20; TL1=0xfd; /设定波特率为 THL=0xfd; ; ; ; ; TRL=1; REN=1; ES=1; EA=1; P27=1; /处于接收状态 SCON=0x50; TMOD=0x22;/mode 2, 8bit auto timer TR1 TH1 let TL1 start at 0xfd. PCON=0x80;/ equal SMOD=1 TH1=0x
10、0fd; TR1=1;/? TR0=1;/? both ET0=1;/ admit Timer0 interrupt equal IE=0x02 EA=1;/* means IE|=0x90; TH0=TL0=0x00; 串行口中断程序 Void serial() interrupt 4 using 1 Unsigned char address; RI=0; /关中断 Address=SBUF; /判断是否符合本机地址,如号机 if(address0x01) P35=0; SM2=; /清位,准备接收数据 /收数据及相应处理 /(发送功能可在此部分完成) SM2=1; else SM2=1;
11、 /不是发给本机数据, /置位SM,退出 #include #include #define INBUF_LEN 4 /数据长度 unsigned char inbuf1INBUF_LEN; unsigned char checksum,count3; bit read_flag=0; void init_serialcomm(void) SCON = 0x50; /SCON: serail mode 1, 8-bit UART, enable ucvr TMOD |= 0x20; /TMOD: timer 1, mode 2, 8-bit reload PCON |= 0x80; /SMOD
12、=1; TH1 = 0xF4; /Baud:4800 fosc=11.0592MHz IE |= 0x90; /Enable Serial Interrupt TR1 = 1; / timer 1 run / TI=1; /向串口发送一个字符 void send_char_com(unsigned char ch) SBUF=ch; while(TI=0); TI=0; /向串口发送一个字符串,strlen为该字符串长度 void send_string_com(unsigned char *str,unsigned int strlen) unsigned int k=0; do send_
13、char_com(*(str + k); k+; while(k 127) count3=0; inbuf1count3=ch; checksum= ch-128; else count3+; inbuf1count3=ch; checksum = ch; if( (count3=(INBUF_LEN-1) &amt;&amt; (!checksum) ) read_flag=1; /如果串口接收的数据达到INBUF_LEN个,且校验没错, /就置位取数标志 main() init_serialcomm(); /初始化串口 while(1) if(read_flag) /如果取数标志已置位,就
14、将读到的数从串口发出 read_flag=0; /取数标志清0 send_string_com(inbuf1,INBUF_LEN); /*Copyright (c)* * 广州周立功单片机发展有限公司 * 研 究 所 * 产品一部 * * * *-文件信息- *文 件 名: PCF8563.C *创 建 人: 叶皓贲 *最后修改日期: 2003-3-4 *描 述: DP-1581的8563T及7289a键盘LED演示程序 * *-历史版本信息- * 创建人: 叶皓贲 * 版 本: 1.0 * 日期: 2003-3-4 * 描述: DP-1581演示程序 * *- * 修改人: * 版 本: *
15、 日期: * 描述: * *-当前版本修订- * 修改人: * 日期: * 描述: * *- */ #include REG52.h #include #include #include VIIC_C51.h #include ZLG7290.h sbit KEY_INT=P32; sbit RS485_RE=P15; bit rec_data; unsigned char rec_temp=1; /* 全局变量 */ unsigned char disp_buf8=0,0,0,0,0,0,0,0; /* * 函数名称: display * 功能描述: 7298A led显示 * 输入: *s
16、d : 显示缓冲区的头地址 * * 输出: 0 : OK; * 1 : FAIL; * 全局变量: 无 * 调用模块: ZLG7289_SendBuf * * 作者: 叶皓贲 * 日期: 2003-3-4 *- * 修改人: * 日期: *- */ unsigned char display_send(unsigned char sd) disp_buf0 = sd; / 装载 dp-932 disp_buf1 = 31; disp_buf2 = 0x1E; disp_buf3 = 0x0e; disp_buf4 = 0x05; disp_buf5 = 31; disp_buf6 = 31;
17、disp_buf7 = 31; ZLG7290_SendBuf(disp_buf,8); return 0; unsigned char display_rec(unsigned char sd) disp_buf0 = sd; / 装载 dp-932 disp_buf1 = 31; disp_buf2 = 0x0c; disp_buf3 = 0x0e; disp_buf4 = 0x18; disp_buf5 = 31; disp_buf6 = 31; disp_buf7 = 31; ZLG7290_SendBuf(disp_buf,8); return 0; /* * 函数名称: Delay
18、NS * 功能描述: 长软件延时 * 输入: no : 延时参数,值越大时延时越久 * * 输出: 0 : OK; * 1 : FAIL; * 全局变量: 无 * 调用模块: 无 * * 作者: 叶皓贲 * 日期: 2003-3-4 *- * 修改人: * 日期: *- */ unsigned char DelayNS(unsigned char no) unsigned char i,j; /延时参数 for(; no0; no-) for(i=0; i100; i+) for(j=0; j100; j+); return 0; /* * 函数名称: delay * 功能描述: 短软件延时
19、* 输入: j : 延时参数,值越大时延时越久 * * 输出: 0 : OK; * 1 : FAIL; * 全局变量: 无 * 调用模块: 无 * * 作者: 叶皓贲 * 日期: 2003-3-4 *- * 修改人: * 日期: *- */ unsigned char delay(unsigned char j) unsigned char k,l; for(l=0;l=j;l+) for(k=0;k=250;k+); return 0; void main() unsigned char key; rec_data=0; /=设置波特率= delay(100); TMOD = 0X20; S
20、CON=0X50; TH1=0XFA; TL1=0XFA; PCON=0X80; TR1=1; EA=1; ES=1; RS485_RE=0; while(1) if(KEY_INT=0) key=ZLG7290_GetKey(); delay(20); display_send(key); RS485_RE=1; SBUF=key; delay(30); if(rec_data) rec_data=0; display_rec(rec_temp); delay(20); void Serial_ISR() interrupt 4 if(TI) TI=0; RS485_RE=0; else R
21、I=0; rec_data=1; rec_temp=SBUF; 二485例程2#ifndef _485_C_ #define _485_C_ #include #include #define unsigned char uchar #define unsigned int uint /* 通信命令 */ #define _ACTIVE_ 0x01 / 主机询问从机是否存在 #define _GETDATA_ 0x02 / 主机发送读设备请求 #define _OK_ 0x03 / 从机应答 #define _STATUS_ 0x04 / 从机发送设备状态信息 #define _MAXSIZE
22、 0x08 / 缓冲区长度 #define _ERRLEN 12 / 任何通信帧长度超过12则表示出错 uchar dbuf_MAXSIZE; / 该缓冲区用于保存设备状态信息 uchar dev; / 该字节用于保存本机设备号 sbit M_DE = P10; / 驱动器使能,1有效 sbit M_RE = P11; / 接收器使能,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; / 读取本机
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1