第二章节 ESP32的外设
2.1 引言
本章节主要介绍项目中所用到的一的外设,比如串口,SPI等。
2.2 UART串口模块
2.2.1 串口简介
串口基本的一些相关知识可自行百度了解一下。
esp32-s这款芯片提供了三组的UART串口引脚,在本项目中所用到的是串口0,它的两个引脚U0TXD和U0RXD分别对应GPIO1和GPIO3,硬件电路图上是连接到microusb接口。
2.2.2参考代码解析
这里面主要参考的是官方所给的示例代码,这里主要分析两个示例代码:uart_echo和uart_events
代码的目录为:D:\Espressif\frameworks\esp-idf-v4.4.5\examples\peripherals\uart
uart_echo
//宏定义 可在idf环境下输入idf.py menuconfig配置串口的相关参数
#define ECHO_TEST_TXD (CONFIG_EXAMPLE_UART_TXD)
#define ECHO_TEST_RXD (CONFIG_EXAMPLE_UART_RXD)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
#define ECHO_UART_PORT_NUM (CONFIG_EXAMPLE_UART_PORT_NUM)
#define ECHO_UART_BAUD_RATE (CONFIG_EXAMPLE_UART_BAUD_RATE)
#define ECHO_TASK_STACK_SIZE (CONFIG_EXAMPLE_TASK_STACK_SIZE)
//打印日志
static const char *TAG = "UART TEST";
//缓存区大小
#define BUF_SIZE (1024)
static void echo_task(void *arg)
{
//串口的基本参数配置:波特率 数据位 停止位等
uart_config_t uart_config = {
.baud_rate = ECHO_UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
//安装uart驱动程序
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags));
//配置uart参数
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config));
//设置uart引脚GPIO
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS));
// 动态申请分配串口缓存区内存
uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
while (1) {
// 读取数据
int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, (BUF_SIZE - 1), 20 / portTICK_RATE_MS);
// 写数据
uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len);
if (len) {
data[len] = '\0';
ESP_LOGI(TAG, "Recv str: %s", (char *) data);
}
}
}
void app_main(void)
{
xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL);
}
上述例子实现功能是串口回响功能,即电脑端发送数据给esp32,esp32原封不动的发送给电脑。
剖析:
app_mian函数:程序开始执行
首先调用xTaskCreate()函数创建一个任务,任务名称为uart_echo_task,入口函数为echo_task
echo_task函数:
结构体定义:uart_config_t
该结构体主要配置UART串口地参数,如波特率,停止位,优先级,时钟等
串口的初始化步骤:
1.uart_driver_install() 加载UART驱动
2.uart_param_config() 配置串口参数
3.uart_set_pin() 配置GPIO引脚位UART功能
数据接受发送
数据发送接受部分:
uart_read_bytes()数据接受函数
uart_write_bytes()数据发送函数
程序执行:
打开idf软件,采用cd命令将路径定位到uart_echo目录下
输入idf.py menuconfig配置模组信息,如下图所示
保存退出,输入idf.py build编译程序
完成后,输入idf.py -p COM6 flash烧录程序 COM6需要根据用户自己的模组的实际端口号来确定
在烧录过程中,需要先按板子上SW1按钮后再按RST按钮
按完后先松开RST按钮再松开SW1按钮即可完成下载
实验结果为:
uart_events:
该例程主要是利用freertos中的队列来实现数据的回响
#define EX_UART_NUM UART_NUM_0
#define PATTERN_CHR_NUM (3)
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
//申明队列
static QueueHandle_t uart0_queue;
static void uart_event_task(void *pvParameters)
{
uart_event_t event;
size_t buffered_size;
//动态申请缓存区
uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
for(;;) {
//等待串口事件发生 event 串口发生的事件
if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);//清空缓存区
ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
switch(event.type) {
case UART_DATA://接收到数据
ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
ESP_LOGI(TAG, "[DATA EVT]:");
uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size);
break;
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
uart_flush_input(EX_UART_NUM);
xQueueReset(uart0_queue);
break;
//Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error")