ESP32 ARDUINO RS485 DE/RE#流向控制编程

本文介绍了如何使用ESP32和ARDUINO对RS485的DE/RE#流向进行控制。方法一通过delay函数确保数据发送,而方法二利用中断实现类似RS232的发送和接收。现在ESP32的HardwareSerial库支持RS485流控制,简化了编程。作者在实践中遇到波特率问题,可能导致数据错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ESP32使用ARDUINO 对RS485 的DE/RE#流向控制

概述

原来一直用74HC04配合SP3485做RS485输出模块,对SP3485模块的DE/RE#端不控制。线路图如下:
在这里插入图片描述
但这次因为线路板尺寸紧张,并且有多余的点可以控制DE/RE#, 就选择了如下的线路:
在这里插入图片描述
现在来说一下编程遇到的困惑和解决问题的思路。

编程方法

方法一

当要向外部输出数据数据时,采用delay(10) 的方式,才能让串口的数据输出到外部接口。

比如我使用了RX2,TX2作为RS485的输出模块。程序应该这样,不然不能输出数据。

    if ( Serial.available())
    {
        uint8_t x = Serial.read();
        if ( x == 's' )
        {
            char sendBuff[] = "Send message to RS485";
            digitalWrite(DE_485, HIGH);
            Serial2.println(sendBuff);
            delay(10);
            digitalWrite(DE_485, LOW);
			Serial.println("Message sneded to RS485");
		}
	}

程序说明:如果在digitalWrite(DE_485, HIGH)后不延时10ms的话无法在串口2上输出信息。在程序中添加这个delay(10)后可以正常输出了。还没有试,大量的数据可能要延长这个延时时间。

方法二

采用中断的方式。
中断程序:

void IRAM_ATTR isrDown()    // edge falling
{
    digitalWrite(DE_485, HIGH);
}

void IRAM_ATTR isrRDown()   // edge falling
{
    digitalWrite(DE_485, LOW);
}

在setup中将中断程序分配给特定的端子:

    attachInterrupt(17, isrDown, FALLING);
    attachInterrupt(16, isrRDown, RISING);  

17是TX2,16是RX2,分别是串口2对应的TX和RX。这时,程序就像RS232或USB普通串口一样发送和接收就可以了。

    if ( Serial.available())
    {
        uint8_t x = Serial.read();
        if ( x == 's' )
        {
            char sendBuff[] = "Send message to RS485";
            Serial2.println(sendBuff);
			Serial.println("Message sneded to RS485");
		}
	}

2024年4月21日,看了现在的库,好像是有了变化,过去没有注意到。ESP32的HardwareSerial库。可以实现对RS485的流硬件进行控制,具体方法:

const uint8_t RS485_RX2_PIN = 16;        // Serial2 RXD2
const uint8_t RS485_TX2_PIN = 17;        // Serial2 TXD2
const uint8_t RS485_RTS2_PIN = 4;       // flow control

定义管脚,RX2和TX2是默认的Serial2的管脚。

	HardwareSerial RS485(2);     //在这里定义第二个串口,名字为RS485
	RS485.begin(2073600, SERIAL_8N1, RS485_RX2_PIN, RS485_TX2_PIN);

	if ( !RS485.setPins(-1, -1, -1, RS485_RTS2_PIN))   // 用RTS控制DE/RE端
    {
        Serial.println("Failed to set RS485 pins");
    }

    if (!RS485.setMode(MODE_RS485_HALF_DUPLEX))
    {
        Serial.println("Failed to set RS485 mode");
    }
    RS485.setRxTimeout(10);
    RS485.onReceive(OnCallback, true);

这里我们实验波特率,最高能够达到多少的波特率,并用RTS管脚控制DE/RE端。

void OnCallback()
{
    uint8_t dLen = RS485.available();
    Serial.print("Bytes received = ");
    Serial.println(dLen);
    if ( dLen == 0 ) return;
    RS485.readBytes(rx2Buff, dLen);
    printHEX(rx2Buff, dLen);
}

上面是自动接收程序并打印的串口1.

总结

从程序可以看出,Arduino还是有操作系统的特点,在代码上看Serial2.println(sendBuff)在后台是运行的,当我们发送这个指令时,后台按波特率不断的执行,这条语句后面如果直接执行digitalWrite(DE_485, LOW), 会使数据发送不出去。采用中断形式是一种尝试。或许在频繁操作的RS485时会不会健康运行有待于验证,也希望网友提宝贵意见。

现在版本的HardwareSerial库也支持RS485的流控制了。方法是:

Serial2.begin(115200);
// bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
Serial2.setPins(-1, -1, -1, DE485);
Serial2.setMode(MODE_RS485_HALF_DUPLEX);

上面的代码可以是程序直接读串口和写串口,不需要考虑流控制。但似乎一切并不那么顺利,在波特率是57600的情况下,情况变得不丝滑了,多了一个字节,0x00. 不停得发送,不能停止。有指导得大咖看一下,哪里不对。2024-4-18, 问题解决。

使用ESP8266的模块发现Arduino编程时在使用SoftwareSerial库时有:

    /// Transmit control pin.
    void setTransmitEnablePin(int8_t txEnablePin);

可以用这个函数来定义DE485输出点。但在使用过程中发现,当波特率较高时,出错的机率比较高,200ms发送一次,一晚上出现了200多次的收发故障。选用的波特率时57600. 说明在高波特率情况下不稳定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值