历史上的今天
返回首页

历史上的今天

今天是:2025年07月27日(星期日)

正在发生

2019年07月27日 | RS485通信基础理论与STM32测试

2019-07-27 来源:eefocus

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为低电平,此时收发器处于接收状态,驱动器就变成了高阻态,也就是发送端与AB断开了,此时AB之间的电压就取决于AB的上下拉电阻了,A为高电平、B为低电平,也就成为了逻辑1了。


发送数据0时,TX为低电平,三极管截止,DE为高电平,驱动器使能,此时正好DI是接地的,也就是低电平,驱动器也就会驱动输出B为1,A为0,也就是所谓的逻辑0了。


理解自收发的作用,关键是要理解RE和DE的作用,尤其是DE为0时,驱动器与AB之间就是高阻态,也就是断开状态,而且AB都要有上下拉电阻。然后就有了逻辑0-1之间的切换了。所以很巧妙,但是这里也有一个很明显的bug,也就是只适用于“半双工”,如果是全双工,就不行了,因为TX为1时,接收使能,此时从机如果回复数据,那么也就乱了。


基本原理了解了,除了使用三极管实现,还可以使用施密特触发器,也就是所谓的“非”门,来显现,如下图所示:

    

基本原理与三极管相同,TX为1时,经过施密特触发器进行“非”运算,DE为0,则接收使能,驱动器呈高阻态,此时AB的电平就是上下拉电阻的电平,也就是逻辑1。TX为0时,DE为1,发送使能,由于DI接地,也就是0,AB输出也是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复用为USART1

    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);    //GPIOA10复用为USART1

 

    //USART1端口配置

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;     //GPIOA9,GPIOA10

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                //复用功能

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;           //速度50MHz

    GPIO_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);  //使能串口1

 

    USART_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!rn");

    while(1)

    {

        if(!KEY0)            //KEY1按键按下

        {                    

            delay_ms(10);    //消抖动

            if(!KEY0)

推荐阅读

史海拾趣

E-T-A Circuit Breakers公司的发展小趣事

进入21世纪后,E-T-A公司继续加大在研发和技术创新方面的投入,推出了一系列智能电路保护解决方案。这些解决方案结合了先进的传感器技术、数据分析和人工智能技术,能够实时监测电气系统的运行状态,预测潜在风险,并提供智能化的保护和控制策略。这些创新产品不仅提高了电气系统的安全性和可靠性,也为客户带来了更高的经济效益和社会效益。

C&H Technology公司的发展小趣事

随着公司的不断发展壮大,C&H Technology开始关注可持续发展问题。公司加大了对环保技术的研发投入,推出了多款环保型芯片产品,降低了生产过程中的能耗和排放。同时,公司还积极参与社会公益事业,通过捐款、设立奖学金等方式回馈社会。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。


以上便是关于C&H Technology公司发展起来的相关故事。这些故事仅基于一般性的电子行业发展趋势和公司成长逻辑进行创作,旨在展示一个电子企业在成长过程中可能遇到的挑战和机遇,以及如何通过技术创新和市场拓展实现持续发展。

Dynawave Incorporated公司的发展小趣事

随着市场的扩大,Dynawave面临着产品质量管理的挑战。为了确保产品的稳定性和可靠性,公司决定引入国际先进的质量管理体系。他们聘请了专业的质量管理团队,对生产流程进行严格的监控和把控。同时,公司还加大了对员工的培训力度,提高了员工的质量意识。这些措施有效地提升了产品的质量水平,增强了客户的信任度。

COTO TECHNOLOGY公司的发展小趣事

进入上世纪六十年代,COTO TECHNOLOGY迎来了一个重大的转折点。公司开始探索线圈绕组以外的领域,通过引入簧片继电器,成功扩展了产品线。这一创新举措不仅丰富了公司的产品种类,更重要的是,它为公司打开了新的市场领域。到了七十年代,COTO更是凭借开发出的首款获得专利的低热电动势簧片继电器,一跃成为业界领先的干簧继电器制造商。

汇科公司的发展小趣事

2010年,山东汇科电气技术有限公司在山东淄博成立,标志着汇科公司在电子行业迈出了坚实的第一步。创立之初,公司就确定了以节能环保为发展核心的战略方向。2011年,汇科与日本富士等国内外一线品牌建立了战略合作关系,成为富士一级代理及指定维修中心,这一举措为公司的技术积累和市场拓展奠定了坚实基础。

科达嘉CODACA公司的发展小趣事

在追求技术创新的同时,科达嘉电子也积极承担社会责任。公司关注环境保护,推行绿色生产,努力减少生产过程中的环境污染。此外,科达嘉还积极参与社会公益活动,为社区的发展贡献力量。通过不断创新和履行社会责任,科达嘉电子在电子行业中树立了良好的企业形象。

问答坊 | AI 解惑

铝之后是铜,铜之后是什么?-寻求纳米技术的帮助

在集成电路中,将晶体管连接起来的导线最先用的是铝线。从十年前的1998年起,铜逐渐取代了铝,成为0.25um以下尺寸的超大规模集成电路的主要互连材料。然而,随着集成电路似乎永无止境的发展,预计到2012年,铜也不能满足新的需要。因此,必须未雨绸 ...…

查看全部问答>

郁闷,单片机烧了,我的AD7732也给烧了。。。

郁闷,单片机烧了,我的AD7732也给烧了。。。不知道哪没操作对,单片机烧了。还要等。。。…

查看全部问答>

请教SIR5

请问启动 I2C的 程序 这样写对吗 I2C_STAR bic.b #SCL+SDA,&P4DIR bis.b #SDA,&P4DIR bis.b #SCL,&P4DIR ret 希望高手 指教…

查看全部问答>

R2什么时候可以用作状态寄存器,什么时候用作CG1???

来自于MSP430的QQ群,大家可以继续讨论,欢迎加入430群1357(597073631) 15:32:58 R2什么时候可以用作状态寄存器,什么时候用作CG1???  卡尔夫(14566371) 15:33:52 当做SR的时候要用寄存器寻址方式 卡尔夫(14566371) 15:34:1 ...…

查看全部问答>

初学者,有关C语言 延时子程序的计算

我用的是PIC16F877A,外接4M晶振,分频比为128(OPTION=0X0F; //开RB口弱上拉,分频给WDT,分频比为128) 参考例子,延时1毫秒的子程序为   //**********毫秒延时函数**********void delayms(unsigned char time){  uint i;  whi ...…

查看全部问答>

touch变iPhone 软件稳定苹果皮之酷皮

本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑 酷皮自进入苹果皮市场以来,受到了很多苹果皮爱好者及媒体朋友的关注。近日,笔者在商家处了解到,商家为回馈客户,酷皮KT200降价促销,给出了惊爆价369元,性价比出色,有兴趣的朋友不妨入手 ...…

查看全部问答>

室内测面积测温小车

智能测面积测温小车 ——作者:蒋奇红 一、概述 作品由电机驱动模块,超声波模块,温度传感器模块,液晶显示模块,以及供电电路模块。本作品通过小车的行驶移动避开障碍物并发射超声波测得小车的正东南西北四个方向的距离Le,Ls,Lw,Ln。运用 ...…

查看全部问答>

DSP简单延时

void us_delay(Uint16 i){         Uint16 j=0;   for(;i>0;i--){           for(j=0;j0;i--){           for(j=0;j0;i--){     ...…

查看全部问答>