RS485——RS485通信基础理论与STM32测试

news/2024/11/22 23:36:21/

1.优劣

优势:RS485的可靠传输距离远,接线简单成为了相对于RS232的最大优势。

 

不足:RS485总线是一种常规的通信总线,它不能够做总线的自动仲裁,也就是不能够同时发送数据以避免总线竞争,所以整个系统的通信效率必然较低,数据冗余量较大,对于速度要求高的应用场所不适应用RS485总线。同时由于RS485总线上通常只有一台主机,所以这种总线方式是典型的集中—分散型控制系统。一旦主机出现故障,会使整个系统的通信限于瘫痪状态,因此做好主机的在线备份是一个重要措施。

 

2. 硬件层协议

通讯协议主要是实现两个设备之间的数据交换功能,通讯协议分硬件层协议和软件层协议。硬件层协议决定数据如何传输问题,比如要在设备1向设备2发送0x63,0x63的二进制数为0110 0011,这8个二进制数从设备1传输到设备2,涉及到1怎么传,0怎么传的问题,这就是硬件层要解决的问题。 
硬件层协议目前比较多见的有RS-232、RS-485、SPI、IIC等。RS-232规定,线上的电压为x伏都表示传输的是0,y伏传输的则是1。再者,比如要选择多少条线传输数据,选择什么材质的线传输输入,这些也属于硬件层协议约束的。

 

3.RS-485通讯协议

MCU管脚输出TTL电平,TTL电平的意思是,当MCU管脚输出0电平时,一般情况下电压是0V,当MCU管脚输出1电平时,电压是5V。因TTL电平的是由一条信号线,一条地线产生,信号线上的干扰信号会跟随有效信号传送到接收端,使得有效信号受到干扰,485通讯实际上是把MCU出来的TTL电平通过硬件层的一个转换器芯片进行转换: 

把MCU出来的一条的TTL信号经过芯片转换为两根线(线A、线B)上的信号。当MCU给转换器输入低TTL电平时,转换器会使得B的电压比A的电压高,反之,A的电压比B的电压高。 
485协议规约两条电平线上差值为多少表示0或者1,电压是通过仪表可以测量得到的,所以说RS-485是硬件层协议。 
485协议的接收端可能是另一个MCU,MCU管脚也只接受TTL电平,转换芯片过来的是两条线的电压,所以需要对此两条线差分电压转换为TTL电平。 

把TTL转为485,实质是一个集成芯片,其间无任何程序代码,纯粹硬件逻辑。同理,将485电平转为TTL也是如此。现在很多芯片把接收和转换都集成到一块IC,注意,转换器和接收器依旧是没有同时工作的,常见的转换芯片是MAX485。 
可以这样理解,硬件层协议是公路,路的目的是为了让车辆能够过去。

 

4.半双工通讯

首先了解什么是单工通讯,单工通讯是指数据只能朝着一个方向传输的通讯方式。而半双工通讯则是指对于通讯两端,不能同时相对方法发送数据,必须错开时间段发送。 

RS-485的通讯线只有2条,且这两条通讯线在一次传输中都需要用到,因此485只可实现半双工通讯。485实现半双工通讯,会遇到一个问题,MCU1向MCU2发数据时,并不知道线上是否正传来MCU2数据,因为没有其他线可用来判断对方的收发状态,那么可能也会导致数据冲突。因此,RS-485要实现半双工通讯,就需要上层的软件协议加以规约,也就是做到”不能你想发数据就发数据”。可以理解,软件层协议就好像交通规则,它能让数据有序传输。

5.基本电路

 

三种常用电路如下:

 

5.1 基本的RS485电路

上图是最基本的RS485电路,R/D为低电平时,发送禁止,接收有效,R/D为高电平时,则发送有效,接收截止。上拉电阻R7和下拉电阻R8,用于保证无连接的SP485R芯片处于空闲状态,提供网络失效保护,提高RS485节点与网络的可靠性,R7,R8,R9这三个电阻,需要根据实际应用改变大小,特别是使用120欧或更小的终端电阻时,R9就不需要了,此时R7,R8使用680欧电阻。正常情况下,一般R7=R8=4.7K,R9不要。

图中钳位于6.8V的管V4,V5,V6,都是为了保护RS485总线的,避免受外界干扰,也可以选择集成的总线保护原件。另外图中的L1,L2,C1,C2为可选安装原件,用于提高电路的EMI性能.

 

5.2 带隔离的RS485电路

根本原理与基本电路的原理相似。使用DC-DC器件可以产生1组与微处理器电路完全隔离的电源输出,用于向RS485收发器提供+5V电源。电路中的光耦器件速率会影响RS485电路的通信速率。上图中选用了NEC的光耦PS2501,受其影响,该电路的通讯速率控制在19200bps下。

 

5.3 自动切换电路

上图中,TX,RX引脚均需要上拉电阻,这一点特别重要。
接收:默认没有数据时,TX为高电平,三极管导通,RE为低电平使能,RO收数据有效,MAX485为接收态。
发送:发送数据1时,TX为高电平时,三极管导通,DE为低电平,此时收发器处于接收状态,驱动器就变成了高阻态,也就是发送端与A\B断开了,此时A\B之间的电压就取决于A\B的上下拉电阻了,A为高电平、B为低电平,也就成为了逻辑1了。
发送数据0时,TX为低电平,三极管截止,DE为高电平,驱动器使能,此时正好DI是接地的,也就是低电平,驱动器也就会驱动输出B为1,A为0,也就是所谓的逻辑0了。
理解自收发的作用,关键是要理解RE和DE的作用,尤其是DE为0时,驱动器与A\B之间就是高阻态,也就是断开状态,而且A\B都要有上下拉电阻。然后就有了逻辑0-1之间的切换了。所以很巧妙,但是这里也有一个很明显的bug,也就是只适用于“半双工”,如果是全双工,就不行了,因为TX为1时,接收使能,此时从机如果回复数据,那么也就乱了。
基本原理了解了,除了使用三极管实现,还可以使用施密特触发器,也就是所谓的“非”门,来显现,如下图所示:
基本原理与三极管相同,TX为1时,经过施密特触发器进行“非”运算,DE为0,则接收使能,驱动器呈高阻态,此时A\B的电平就是上下拉电阻的电平,也就是逻辑1。TX为0时,DE为1,发送使能,由于DI接地,也就是0,A\B输出也是0.

 

6.SP3485内部结构图: 

2 
图中: 
A、B总线接口,用于连接485总线。RO是接收输出端,DI是发送数据收入端,RE是接收使能信号(低电平有效),DE是发送使能信号(高电平有效)。

SP3485硬件连接: 
这里写图片描述 
注意: 
R55和R56是两个偏置电阻,用来保证总线空闲时,AB之间的电压差都会大约200mV,避免总线空闲时压差不定逻辑混乱。

 

7. RS485串口编程

 

7.1 编程思路

使用RS485实现两个MCU之间的通信,把接收到的数据通过串口助手显示在超级终端上。首先对Usart1和Usart2进行初始化,Usart1负责与串口助手通信,Usart2与RS485连接进行两个MCU之间的通信。然后编写发送和接收函数,接收函数在Usart2的中断服务函数中实现。最后把接收到的数据和必要的提示信息发送到超级终端上显示。

 

7.2 功能模块代码

①串口初始化

void Uart1_Init(void)
{//USART1 初始化GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);        //开启GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);       //开启USART1时钟//串口1对应引脚复用映射GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);     //GPIOA9复用为USART1GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);    //GPIOA10复用为USART1//USART1端口配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;     //GPIOA9,GPIOA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                //复用功能GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;           //速度50MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP;              //推挽复用输出GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                //上拉GPIO_Init(GPIOA,&GPIO_InitStructure);                       //初始化PA9,PA10//USART1 端口配置USART_InitStructure.USART_BaudRate      = 115200;USART_InitStructure.USART_WordLength    = USART_WordLength_8b;USART_InitStructure.USART_StopBits      = USART_StopBits_1;USART_InitStructure.USART_Parity        = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode          = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE);  //使能串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);          //开启相关中断NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         NVIC_Init(&NVIC_InitStructure);                         
}void Uart2_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);       //串口2对应引脚复用映射GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);     GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                    GPIO_Init(GPIOA,&GPIO_InitStructure);                                   //USART2 端口配置USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_Cmd(USART2, ENABLE);  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);      //Usart2 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(&NVIC_InitStructure); 
}

②接收数据

void USART2_IRQHandler(void)
{static u32 rx_i=0;if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){     USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除标志位rx_buf[rx_i++] = USART_ReceiveData(USART2);    //rx_buf是在main.c定义的全局变量while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); }rx_flag = 1;
}

③RS485初始化 

 

(SP3485的RE,DE引脚与MCU的PG8引脚相连接)

 

void Rs485_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);   GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_8;        GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_UP;  GPIO_Init(GPIOG, &GPIO_InitStruct);     //  RS485_TX_EN = 0; //默认为接收模式
}

④主函数

int main(void)
{char *tx_buf = "I believe I can fly!";u8 len;Led_Init();Key_Init();Systick_Init();Uart1_Init();Uart2_Init();Rs485_Init();printf("Usart test succeeded!\r\n");while(1){if(!KEY0)            //KEY1按键按下{                    delay_ms(10);    //消抖动if(!KEY0){while(!KEY0);RS485_TX_EN = 1; //发送模式,RS485_TX_EN是自定义的一个宏,即对PG8进行置位复位len = strlen(tx_buf);while(len--){USART_SendData(USART2, *tx_buf++);while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);}printf("Send data succeeded!\r\n"); //printf函数已经重定义}}if(!KEY1)              //KEY1按键按下{delay_ms(10);      //消抖动if(!KEY1)          //等待按键松开{while(!KEY1);RS485_TX_EN = 0;    //接收模式if(rx_flag){rx_flag = 0; //清除标志printf("Receive data: %s\r\n", rx_buf);}}}}
}

 


http://www.ppmy.cn/news/137286.html

相关文章

RS485基本特性

概念 RS-485是美国电子工业协会(EIA)在1983年批准了一个新的平衡传输标准(balanced transmission standard),EIA一开始将RS(Recommended Standard)做为标准的前缀,不过后来为了便于识…

UART/RS485/RS232

RS485和RS232是物理总线。 RS232 传输距离大概15米左右只允许一对一通信全双工 RS485 传输距离大概1200米总线上允许接多达32个发射器和43个接收器半双工 UART UART是基于RS485/RS232/USB等物理层上层通信协议。全双工和半双工是物理链路决定的(有的应用层协议…

485通信详解

上边是我一直在用的485通信自动收发电路,不但要把电路送给你,还要把电路原理给你讲明白了。实测波特率9600不会有问题,但是,波特率115200的话,曾经出现过问题。 我们先看看普通的收发电路。 普通的485电路&#xff0…

常见通信协议之UART、RS485

UART 通用异步收发器一种通用的串行、异步通信总线,该总线有两条数据线,可以实现全双工的发送和接受并行通信和串行通信 总线传递数据的本质—高低电信号并行通信—一次性传输多个位—布线难度高—存在数据干扰串行通信—逐次传输单工通信—单向通信双工…

RS485简介

▉ RS-485概述 RS-485和RS-232一样,都是串行通信标准,现在的标准名称是TIA485/EIA-485-A,但是人们会习惯称为RS-485标准,RS-485常用在工业、自动化、汽车和建筑物管理等领域。 RS-485总线弥补了RS-232通信距离短,速率低…

485接口

485接口 串口 串口是一种接口标准,它规定了接口的电气标准,简单说只是物理层的一个标准。没有规定接口插件电缆以及使用的协议,所以只要我们使用的接口插件电缆符合串口标准就可以在实际中灵活使用,在串口接口标准上使用各种协议…

联想Z485安装64位ubantu

开始今天的正式写作之前不得不吐槽一下联想电脑,真的是很垃圾!联想Z485使用的是AMD的处理器,性能差的很,更让人不能忍的是,居然不能正常安装64位ubantu。这个情况让那些想在自己笔记电脑上安装TensorFlow的人头都大了一…

bootmgr is conmpressed联想Z485

昨天清理磁盘空间的时候,手贱把驱动器给压缩了。再开机的时候就遇到了bootmgr is conmpressed。 我把解决办法发布到百度经验上了 http://jingyan.baidu.com/article/e9fb46e1566c587521f76680.html 转载于:https://www.cnblogs.com/sdadx/p/6265593.html