esp-idf/examples/peripherals/uart_echo_rs485/main/rs485_example.c
Alex Lisitsyn ef5dc73f6f driver: add rs485 half duplex interface support to uart driver (update after review)
An existing UART driver does not support RS485 half duplex mode.
This task adds this functionality to ESP_IDF UART driver.
driver/uart.c/h: updated to add support of RS485 half duplex mode
examples/peripherals/uart_echo_rs485/main/rs485_example.c: added test example
components/driver/test/test_uart.c: added test of RS485 half duplex mode
docs/en/api-reference/peripherals/uart.rst: updated documentation
test_uart.c: suppress GCC warnings about discarded const qualifiers
uart.rst: remove sphinx warning - "Duplicate explicit target name"
simple change in uart.h file
update (test_uart.c) after rebase from master
update uart.rst, uart.c, rs485_example.c
Update example description in file Readme.md
update uart.c/h, uart.rst, test_uart.c according to review results
update uart.h (uart_set_rx_timeout() description
test_uart.c remove ignore tag
uart.c/h: fix param errors
test_uart.c: Remove GCC warning supress
uart.rst: fix the notes
rs485_example.c: fix output

The tests are completed using RS485 adapters hardware connected to two ESP32 WROVER KITs.

TW#13812
Closes https://github.com/espressif/esp-idf/pull/667
Closes https://github.com/espressif/esp-idf/pull/1006
2018-07-02 15:24:58 +02:00

127 lines
4.0 KiB
C

/* Uart Events Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"
/**
* This is a example example which echos any data it receives on UART back to the sender.
*
* - port: UART2
* - rx buffer: on
* - tx buffer: off
* - flow control: off
*
* This example has been tested on a 3 node RS485 Serial Bus
*
*/
// Note: UART2 default pins IO16, IO17 do not work on ESP32-WROVER module
// because these pins connected to PSRAM
#define ECHO_TEST_TXD (23)
#define ECHO_TEST_RXD (22)
// RTS for RS485 Half-Duplex Mode manages DE/~RE
#define ECHO_TEST_RTS (18)
// CTS is not used in RS485 Half-Duplex Mode
#define ECHO_TEST_CTS UART_PIN_NO_CHANGE
#define BUF_SIZE (127)
#define BAUD_RATE (115200)
// Read packet timeout
#define PACKET_READ_TICS (100 / portTICK_RATE_MS)
#define ECHO_TASK_STACK_SIZE (2048)
#define ECHO_TASK_PRIO (10)
#define ECHO_UART_PORT (UART_NUM_2)
static const char *TAG = "RS485_ECHO_APP";
// An example of echo test with hardware flow control on UART
static void echo_task()
{
const int uart_num = ECHO_UART_PORT;
uart_config_t uart_config = {
.baud_rate = BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
};
// Set UART log level
esp_log_level_set(TAG, ESP_LOG_INFO);
ESP_LOGI(TAG, "Start RS485 application test and configure UART.");
// Configure UART parameters
uart_param_config(uart_num, &uart_config);
ESP_LOGI(TAG, "UART set pins, mode and install driver.");
// Set UART1 pins(TX: IO23, RX: I022, RTS: IO18, CTS: IO19)
uart_set_pin(uart_num, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
// Install UART driver (we don't need an event queue here)
// In this example we don't even use a buffer for sending data.
uart_driver_install(uart_num, BUF_SIZE * 2, 0, 0, NULL, 0);
// Set RS485 half duplex mode
uart_set_mode(uart_num, UART_MODE_RS485_HALF_DUPLEX);
// Allocate buffers for UART
uint8_t* data = (uint8_t*) malloc(BUF_SIZE);
ESP_LOGI(TAG, "UART start recieve loop.\r\n");
uart_write_bytes(uart_num, "Start RS485 UART test.\r\n", 24);
while(1) {
//Read data from UART
int len = uart_read_bytes(uart_num, data, BUF_SIZE, PACKET_READ_TICS);
//Write data back to UART
if (len > 0) {
uart_write_bytes(uart_num, "\r\n", 2);
char prefix[] = "RS485 Received: [";
uart_write_bytes(uart_num, prefix, (sizeof(prefix) - 1));
ESP_LOGI(TAG, "Received %u bytes:", len);
printf("[ ");
for (int i = 0; i < len; i++) {
printf("0x%.2X ", (uint8_t)data[i]);
uart_write_bytes(uart_num, (const char*)&data[i], 1);
// Add a Newline character if you get a return charater from paste (Paste tests multibyte receipt/buffer)
if (data[i] == '\r') {
uart_write_bytes(uart_num, "\n", 1);
}
}
printf("] \n");
uart_write_bytes(uart_num, "]\r\n", 3);
} else {
// Echo a "." to show we are alive while we wait for input
uart_write_bytes(uart_num, ".", 1);
}
}
}
void app_main()
{
//A uart read/write example without event queue;
xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, ECHO_TASK_PRIO, NULL);
}