Arduino中ESP32 P4 中一次性设置多个 GPIO的方法

一般情况下我们可以用过 digitalWrite() 在 Arduino 中设置 GPIO 的 HIGH/LOW, 但是这种方法非常耗时。这里给出一种可以一次性设置多个 GPIO 的方法:

在 C:\Users\USERNAME\AppData\Local\Arduino15\packages\esp32\tools\esp32-arduino-libs\idf-release_v5.4-858a988d-v1-cn\esp32p4\include\soc\esp32p4\register\soc\gpio_struct.h 有如下定义:

extern gpio_dev_t GPIO;

typedef struct gpio_dev_t {
    volatile gpio_bt_select_reg_t bt_select;
    volatile gpio_out_reg_t out;
    volatile gpio_out_w1ts_reg_t out_w1ts;
    volatile gpio_out_w1tc_reg_t out_w1tc;
    volatile gpio_out1_reg_t out1;
    volatile gpio_out1_w1ts_reg_t out1_w1ts;
    volatile gpio_out1_w1tc_reg_t out1_w1tc;
    uint32_t reserved_01c;
    volatile gpio_enable_reg_t enable;
    volatile gpio_enable_w1ts_reg_t enable_w1ts;
    volatile gpio_enable_w1tc_reg_t enable_w1tc;
    volatile gpio_enable1_reg_t enable1;
    volatile gpio_enable1_w1ts_reg_t enable1_w1ts;
    volatile gpio_enable1_w1tc_reg_t enable1_w1tc;
    volatile gpio_strap_reg_t strap;
    volatile gpio_in_reg_t in;
    volatile gpio_in1_reg_t in1;
    volatile gpio_status_reg_t status;
    volatile gpio_status_w1ts_reg_t status_w1ts;
    volatile gpio_status_w1tc_reg_t status_w1tc;
    volatile gpio_status1_reg_t status1;
    volatile gpio_status1_w1ts_reg_t status1_w1ts;
    volatile gpio_status1_w1tc_reg_t status1_w1tc;
    volatile gpio_intr_0_reg_t intr_0;
    volatile gpio_intr1_0_reg_t intr1_0;
    volatile gpio_intr_1_reg_t intr_1;
    volatile gpio_intr1_1_reg_t intr1_1;
    volatile gpio_status_next_reg_t status_next;
    volatile gpio_status_next1_reg_t status_next1;
    volatile gpio_pin_reg_t pin[57];
    volatile gpio_func_in_sel_cfg_reg_t func_in_sel_cfg[256]; /* func0-func255: reserved for func0, 46, 67, 72, 73, 79, 81, 82, 84, 85, 87, 88, 115, 116, 119-125, 157, 204-213 */
    volatile gpio_func_out_sel_cfg_reg_t func_out_sel_cfg[57];
    volatile gpio_intr_2_reg_t intr_2;
    volatile gpio_intr1_2_reg_t intr1_2;
    volatile gpio_intr_3_reg_t intr_3;
    volatile gpio_intr1_3_reg_t intr1_3;
    volatile gpio_clock_gate_reg_t clock_gate;
    uint32_t reserved_650[44];
    volatile gpio_int_raw_reg_t int_raw;
    volatile gpio_int_st_reg_t int_st;
    volatile gpio_int_ena_reg_t int_ena;
    volatile gpio_int_clr_reg_t int_clr;
    volatile gpio_zero_det_filter_cnt_reg_t zero_det_filter_cnt[2];
    volatile gpio_send_seq_reg_t send_seq;
    volatile gpio_recive_seq_reg_t recive_seq;
    volatile gpio_bistin_sel_reg_t bistin_sel;
    volatile gpio_bist_ctrl_reg_t bist_ctrl;
    uint32_t reserved_728[53];
    volatile gpio_date_reg_t date;
} gpio_dev_t;

其中的out_w1ts 和 out_w1tc 可以用来一次性设置多个 GPIO 为高或者为低。

测试代码:

#include "soc/gpio_struct.h" // GPIO

void setup() {
   pinMode(7,OUTPUT);pinMode(8,OUTPUT);
   pinMode(30,OUTPUT);pinMode(32,OUTPUT);pinMode(33,OUTPUT);pinMode(49,OUTPUT);
   pinMode(50,OUTPUT);pinMode(52,OUTPUT);
   digitalWrite(7,LOW);digitalWrite(8,LOW);
   digitalWrite(30,LOW);digitalWrite(32,LOW);digitalWrite(33,LOW);digitalWrite(49,LOW);
   digitalWrite(50,LOW);digitalWrite(52,LOW);

}

void loop() {
    GPIO.out_w1ts.val = (1<<30)|(1<<8)|(1<<7); 
    GPIO.out1_w1ts.val=(1<<(33-32))|(1<<(32-32))|(1<<(52-32))|(1<<(49-32))|(1<<(50-32));
    GPIO.out_w1tc.val = (1<<30)|(1<<8)|(1<<7); 
    GPIO.out1_w1tc.val=(1<<(33-32))|(1<<(32-32))|(1<<(52-32))|(1<<(49-32))|(1<<(50-32));
    delay(1000);
}

硬件上GPIO33, 32, 30, 8, 7, 52, 49, 50分别连接到逻辑分析的4-11通道。

其中的 GPIO 初始化使用 Arduino 代码来完成,GPIO 的设置直接使用位操作。超过31的GPIO要在out1_w1ts和out1_w1tc上设置。

最终抓到的结果可以从下面看到:

参考:

1.https://github.com/maarten-pennings/howto/blob/main/esp32-fast-gpio/esp32-fast-gpio.md

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注