官网esp-idf参考代码:D:\esp-idf\examples\peripherals\uart\uart_events

开发环境:Source Insight  + esp-idf 

esp32模块:ESP32-WROOM-32

实现功能:使用ESP32的3个UART全部实现收发,要求3个UART同时接收每条数据长度25间隔时间为100ms。

 

初期看了一下官网的uart例程代码,官网推荐使用模式检测。自己也可以使用直接在ISR中处理中断。

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "driver/gpio.h"


#define BUF_SIZE				(1024)
#define RD_BUF_SIZE 			(BUF_SIZE)


uart_event_t    uart0_event, uart1_event, uart2_event;
QueueHandle_t	uart0_queue, uart1_queue, uart2_queue;


void uart_event_handle(uart_port_t uart_num, QueueHandle_t queue, uart_event_t *event);





void app_main(void)
{
	uart_config_t	uart_config =
	{
		.baud_rate			= 115200,
		.data_bits			= UART_DATA_8_BITS,
		.parity 			= UART_PARITY_DISABLE,
		.stop_bits	        = UART_STOP_BITS_1,
		.flow_ctrl			= UART_HW_FLOWCTRL_DISABLE
	};
    
	uart_param_config(UART_NUM_0, &uart_config);
	uart_param_config(UART_NUM_1, &uart_config);
	uart_param_config(UART_NUM_2, &uart_config);

	uart_set_pin(UART_NUM_0, GPIO_NUM_1,  GPIO_NUM_3,  UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
	uart_set_pin(UART_NUM_1, GPIO_NUM_18, GPIO_NUM_19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
	uart_set_pin(UART_NUM_2, GPIO_NUM_16, GPIO_NUM_17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

	uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
	uart_driver_install(UART_NUM_1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart1_queue, 0);
	uart_driver_install(UART_NUM_2, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart2_queue, 0);

	uart_pattern_queue_reset(UART_NUM_0, 20);
	uart_pattern_queue_reset(UART_NUM_1, 20);
	uart_pattern_queue_reset(UART_NUM_2, 20);

	while (1)
	{
		if (xQueueReceive(uart0_queue, (uint32_t *) &uart0_event, 0))
		{
			uart_event_handle(UART_NUM_0, uart0_queue, &uart0_event);
		}
        if (xQueueReceive(uart1_queue, (uint32_t *) &uart1_event, 0))
		{
			uart_event_handle(UART_NUM_1, uart1_queue, &uart1_event);
		}
   		if (xQueueReceive(uart2_queue, (uint32_t *) &uart2_event, 0))
		{
			uart_event_handle(UART_NUM_2, uart2_queue, &uart2_event);
		}

        vTaskDelay(pdMS_TO_TICKS(10));      //Delay 10ms
	}
    
}


void uart_event_handle(uart_port_t uart_num, QueueHandle_t queue, uart_event_t *event)
{
	uint8_t *dtmp = malloc(RD_BUF_SIZE);
    bzero(dtmp, RD_BUF_SIZE);

	switch (event->type)
	{
		//Event of UART receving data
		/*We'd better handler data event fast, there would be much more data events than
		other types of events. If we take too much time on data event, the queue might
		be full.*/
		case UART_DATA:
			uart_read_bytes(uart_num, dtmp, event->size, portMAX_DELAY);
			uart_write_bytes(uart_num, (const char *) dtmp, event->size);
			break;

		//Event of HW FIFO overflow detected
		case UART_FIFO_OVF:
			// If fifo overflow happened, you should consider adding flow control for your application.
			// The ISR has already reset the rx FIFO,
			// As an example, we directly flush the rx buffer here in order to read more data.
			uart_flush_input(uart_num);
			xQueueReset(queue);
			break;

		//Event of UART ring buffer full
		case UART_BUFFER_FULL:
			// If buffer full happened, you should consider encreasing your buffer size
			// As an example, we directly flush the rx buffer here in order to read more data.
			uart_flush_input(uart_num);
			xQueueReset(queue);
			break;

		//Event of UART RX break detected
		case UART_BREAK:
			break;

		//Event of UART parity check error
		case UART_PARITY_ERR:
			break;

		//Event of UART frame error
		case UART_FRAME_ERR:
			break;

		//UART_PATTERN_DET
		case UART_PATTERN_DET:
			break;

		//Others
		default:
			break;
	}
    
  	free(dtmp);
	dtmp = NULL;
}

 

解析:

uart_config_t	uart_config =
	{
		.baud_rate			= 115200,
		.data_bits			= UART_DATA_8_BITS,
		.parity 			= UART_PARITY_DISABLE,
		.stop_bits	        = UART_STOP_BITS_1,
		.flow_ctrl			= UART_HW_FLOWCTRL_DISABLE
	};

    uart_param_config(UART_NUM_0, &uart_config);

调用该函数uart_param_config()并将其所需参数UART_NUM_0串口号,和传递给结构uart_config_t。该uart_config_t结构应包含所有uart的设置必需的参数。

 

uart_set_pin(UART_NUM_0, GPIO_NUM_1,  GPIO_NUM_3,  UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

该函数uart_set_pin()为配置UART设备将连接到的物理GPIO引脚,

即指定驱动程序应将Tx,Rx,RTS和CTS信号路由到的GPIO引脚号。

UART0的TX为GPIO1,RX为GPIO3,不使用RTS和CTS信号。

 

uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);

通过调用安装驱动程序uart_driver_install()并指定以下参数:

UART0,Rx环形缓冲区的大小BUF_SIZE * 2, TX环形缓冲区的大小为BUF_SIZE * 2, 创建20个UART事件队列,UART事件队指针,中断标志位为0表示使用默认的中断服务函数。

注:Rx环形缓冲区的大小BUF_SIZE一定要大于128;TX环形缓冲区如果写0,则不使用缓存区发送数据。

RX环形缓存区大小 由自定义接收到的单条数据最大决定,比如上面使用了20个事件队列,那么缓存区至少要能容纳20条最大长度的数据,宁大不可小分配。

 

uart_pattern_queue_reset(UART_NUM_0, 20);

 分配给定长度的新存储器,以将检测到的图案位置记录保存在rx缓冲区中。

 

xQueueReceive(uart0_queue, (uint32_t *) &uart0_event, 0)

判断UART0 是否有事件发生,有则进行事件处理,最后的0表示不阻塞。

 

void uart_event_handle(uart_port_t uart_num, QueueHandle_t queue, uart_event_t *event)

事件处理函数:

枚举uart_event_type_t 环形缓冲区中使用的UART事件类型。值:
UART_DATA                UART数据事件
UART_BREAK               UART中断事件
UART_BUFFER_FULL    UART RX缓冲区已满事件
UART_FIFO_OVF          UART FIFO溢出事件
UART_FRAME_ERR      UART RX帧错误事件
UART_PARITY_ERR      UART RX奇偶校验事件
UART_DATA_BREAK    UART TX数据和中断事件
UART_PATTERN_DET   检测到UART模式
UART_EVENT_MAX      UART事件最大索引

 

 

esp32 外部中断会频繁触发 esp32 uart 中断_环形缓冲

 

 

 更简单的写法,前提是确定环形缓存区足够大,数据处理足够快。

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

#define BUF_SIZE				(1024)

size_t length = 0;
unsigned char data[BUF_SIZE] = {0};
uart_event_t    uart0_event, uart1_event, uart2_event;
QueueHandle_t	uart0_queue, uart1_queue, uart2_queue;


void app_main(void)
{
	uart_config_t	uart_config =
	{
		.baud_rate			= 115200,
		.data_bits			= UART_DATA_8_BITS,
		.parity 			= UART_PARITY_DISABLE,
		.stop_bits	        = UART_STOP_BITS_1,
		.flow_ctrl			= UART_HW_FLOWCTRL_DISABLE
	};
    
	uart_param_config(UART_NUM_0, &uart_config);
	uart_param_config(UART_NUM_1, &uart_config);
	uart_param_config(UART_NUM_2, &uart_config);

	uart_set_pin(UART_NUM_0, GPIO_NUM_1,  GPIO_NUM_3,  UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
	uart_set_pin(UART_NUM_1, GPIO_NUM_18, GPIO_NUM_19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
	uart_set_pin(UART_NUM_2, GPIO_NUM_16, GPIO_NUM_17, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

	uart_driver_install(UART_NUM_0, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
	uart_driver_install(UART_NUM_1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart1_queue, 0);
	uart_driver_install(UART_NUM_2, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart2_queue, 0);

	uart_pattern_queue_reset(UART_NUM_0, 20);
	uart_pattern_queue_reset(UART_NUM_1, 20);
	uart_pattern_queue_reset(UART_NUM_2, 20);

	while (1)
	{
        uart_get_buffered_data_len(UART_NUM_0, (size_t*)&length);
        if(length > 0)
        {
            memset(data, 0, BUF_SIZE);
            uart_read_bytes(UART_NUM_0, data, length, 100);
            uart_write_bytes(UART_NUM_0, (const char*)data, strlen((const char*)data));
        }
        uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length);
        if(length > 0)
        {
            memset(data, 0, BUF_SIZE);
            uart_read_bytes(UART_NUM_1, data, length, 100);
            uart_write_bytes(UART_NUM_1, (const char*)data, strlen((const char*)data));
        }
        uart_get_buffered_data_len(UART_NUM_2, (size_t*)&length);
        if(length > 0)
        {
            memset(data, 0, BUF_SIZE);
            uart_read_bytes(UART_NUM_2, data, length, 100);
            uart_write_bytes(UART_NUM_2, (const char*)data, strlen((const char*)data));
        }        
        vTaskDelay(pdMS_TO_TICKS(10));      //Delay 10ms
	}
    
}

现象:10ms定时发送,收发不掉数据。 

esp32 外部中断会频繁触发 esp32 uart 中断_#include_02

 

全篇完。

 

 

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解方便记录成长笔记。

若有与大神大大见解有冲突,我坚信大神大大见解是对的,我的是错的。

感谢~!