ESP32 中断方式操作串口

ESP32 DK45 3评论

ESP32的IDF提供了两种操作串口的方式:第一种是使用官方的驱动方式,这种方式中断服务函数是官方写好的,自己需要通过另建一个任务来获取封装好的串口事件,这种方式操作简便,自己无需写太多代码就可以使用已经定义好的各种事件。但是呢这种方式有个缺点就是从串口接受到数据再到通过事件的方式通知到一个任务里面来需要一定的事件,这个和freertos系统调度有关。所有有些非常需要实时处理的串口数据就没办法。

第二种方式呢就是自己写串口中断服务函数,这个也就是我们在平时单片机编程中最常使用的方式。

这里主要讲下基于中断的方式来操作ESP32 串口。基于事件的方式可以直接参考官方example里面的代码已经很完整。

要使用一个外设很简单,第一步就是初始化:

void uart2_init(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_2, &uart_config);
    //设置串口使用的引脚
    uart_set_pin(UART_NUM_2,GPIO_NUM_17, GPIO_NUM_16, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //这里是关键点,必须要先uart_driver_install安装驱动,在把中断服务给释放掉
    uart_driver_install(UART_NUM_2, 128 * 2, 0, 0, NULL, 0);
    uart_isr_free(UART_NUM_2);
    //重新注册中断服务函数
    uart_isr_handle_t handle;
    uart_isr_register(UART_NUM_2, uart2_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle);
    //使能串口接收中断
    uart_enable_rx_intr(UART_NUM_2);
}

可以看出来初始化代码很简单,但是里面却有个大坑,之前一直找不出来问题,添加的终端服务函数不管用。就是少执行了uart_driver_install和uart_isr_free这两步。关键是官方并没有说明需要这样操作,国内网上帖子看遍了每一个这样操作的,最后还是翻墙看到一个印度人这么写的。

下面就是中断服务函数:

//中断服务函数放在IRAM中执行,所以在这里定义的时候要添加IRAM_ATTR
STATIC void IRAM_ATTR uart2_irq_handler(void *arg) {
    volatile uart_dev_t *uart = &UART2;
    uart->int_clr.rxfifo_full = 1;
    uart->int_clr.frm_err = 1;
    uart->int_clr.rxfifo_tout = 1;
    while (uart->status.rxfifo_cnt) {
        uint8_t c = uart->fifo.rw_byte;
        uart_write_bytes(UART_NUM_2, (char *)&c, 1);  //把接收的数据重新打印出来
    }
}

喜欢 (8)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(3)个小伙伴在吐槽
  1. 你好,为什么用你这种方法,中断接收数据时,会复位。
    shengfeng19912019-09-03 16:44 回复
    • 你看下是不是你串口io错了啊,反正我自己的esp32串口2是5和18引脚,跟版主的不一样,你要是io不一样照搬的话就会导致硬件错误复位的
      三日月2021-01-18 20:22 回复
  2. 解决没有,我用这个方法也是接收会复位
    cooper2020-09-08 11:40 回复