首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ESP32直接端口操作

ESP32直接端口操作
EN

Stack Overflow用户
提问于 2018-09-15 21:14:23
回答 4查看 17.4K关注 1票数 7

亲爱的StackOverflowers:

我正在尝试使用HX8357D 3.5“来自Adafruit (链接)的TFT和esp32。TFT驱动程序有两个接口: SPI和8位并行。由Adafruit (链接)提供的库只支持esp32上的SPI。我需要更高的显示速度,所以我决定自己尝试添加对esp32的支持。我对这种编程完全没有经验,但我喜欢挑战。

我弄清楚了8位接口是如何通过反向工程实现的,Arduino Uno/Mega支持。要添加esp32支持,我需要一种直接操作寄存器、控制esp32的gpio端口的方法。我在网上环顾四周,但很少有例子说明如何做到这一点。Espressif (链接)的技术参考手册包含了所需的所有信息,但我还不够熟练,无法理解如何将其转换为代码。

要编程esp32,我使用esp32 Arduino内核。此示例(链接)演示如何将gpio引脚设置为输出,并直接使用寄存器使其高低。问题是,我需要设置8个引脚作为输出,向它们写入数据,让它们输入,然后从它们中读取数据,所有这些都使用寄存器而不是使用pinMode、digitalRead和digitalWrite函数。

我清楚它在Arduino Uno/Mega上的工作方式,有三个寄存器控制一个端口:

  • DDR*读/写
  • 端口*将gpio设置为高/低
  • 如果输入gpio,则引脚*读取高/低。

但是这是如何在esp32上工作的,我如何利用寄存器创建这个8位并行通信呢?

如果在这个问题上有比我更了解的人,我将非常感谢你的解释。提前谢谢。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-09-16 08:59:56

有很多方法可以做到这一点。我经常一针见血。

一个简单的方法是通过定义一个变量来创建您自己的“寄存器”。如果寄存器宽为8位,则定义字节变量:

代码语言:javascript
复制
unsigned char disp_register;

然后写到这个寄存器,就像它会存在于显示硬件中一样。当然,接下来您必须将此寄存器输出到ESP32的GPIO引脚。由于引脚都已经用完了,所以你必须一针见血地做这个.为可读性定义硬件引脚:

代码语言:javascript
复制
/* OUTPUTS (numbers mean GPIO port) */
#define REGISTER_BIT7_ON_PIN        9
#define REGISTER_BIT6_ON_PIN        10
#define REGISTER_BIT5_ON_PIN        5
// continue with all the pins you need

在程序开始的某个地方,将这些引脚设置为输出,并将其默认值设置为“0”:

代码语言:javascript
复制
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
io_conf.pin_bit_mask =  ((1ULL<< REGISTER_BIT7_ON_PIN) | (1ULL<< REGISTER_BIT6_ON_PIN) | (1ULL<< REGISTER_BIT5_ON_PIN)); // of course, do like this all the pins
gpio_config(&io_conf);

gpio_set_level(REGISTER_BIT7_ON_PIN, 0); // do like this all the pins you need to set the boot-up value, pin-by-pin

接下来,您需要使用您的函数将您的寄存器复制到GPIO引脚的外部世界:

代码语言:javascript
复制
/*
 * wrote this simply for ease of understanding, feel free to do this in a loop
 * or shifting bit by bit
 */
void copy_register_to_GPIO_pins(unsigned char disp_register)
{
    gpio_set_level(REGISTER_BIT7_ON_PIN, (disp_register & 0x80) >> 7);
    gpio_set_level(REGISTER_BIT6_ON_PIN, (disp_register & 0x40) >> 6);
    gpio_set_level(REGISTER_BIT5_ON_PIN, (disp_register & 0x20) >> 5);
    gpio_set_level(REGISTER_BIT4_ON_PIN, (disp_register & 0x10) >> 4);
    gpio_set_level(REGISTER_BIT3_ON_PIN, (disp_register & 0x08) >> 3);
    gpio_set_level(REGISTER_BIT2_ON_PIN, (disp_register & 0x04) >> 2);
    gpio_set_level(REGISTER_BIT1_ON_PIN, (disp_register & 0x02) >> 1);
    gpio_set_level(REGISTER_BIT0_ON_PIN, (disp_register & 0x01));
}

然后,在您将任何内容写入寄存器后,调用您的函数输出它:

代码语言:javascript
复制
disp_register = 0x2A; // example value you want to send to display
copy_register_to_GPIO_pins(disp_register);

// or, output byte WITHOUT using any register:
copy_register_to_GPIO_pins(0x2A);

希望您可以自己做相反的操作,读取引脚是由另一个函数完成的,在这个函数中,您复制每个GPIO引脚值并将其组装到字节变量中。当然,在这一点上,引脚必须设置为输入。原则上:

代码语言:javascript
复制
/*
 * wrote this simply for ease of understanding
 */
unsigned char copy_GPIO_pins_to_register(void)
{
    unsigned char retval = 0;

    retval |= gpio_get_level(REGISTER_BIT7_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT6_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT5_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT4_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT3_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT2_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT1_ON_PIN);
    retval = retval << 1;
    retval |= gpio_get_level(REGISTER_BIT0_ON_PIN);

    return retval;
}
票数 7
EN

Stack Overflow用户

发布于 2018-10-24 19:21:19

为了在操作这8个引脚时最小化计算负担,您将希望这些引脚对应于连续的GPIO数字(例如,GPIO12到GPIO19)。下面是一个并行操作多个输入/输出引脚的实现,如果满足上述要求(连续的GPIO号),如果GPIO数字都在0-31范围内,则可以工作;我使用GPIO12来实现GPIO19 (GPIO12对应于输入/输出8位值中的位0),如果您有一个带有ESP 32或ESP 32-WROVER模块的ESP32开发板,则使用起来非常方便。因此,我将对应于位0的GPIO定义如下:

代码语言:javascript
复制
#define PARALLEL_0  12

在初始化时,您需要配置所有8个引脚一个GPIOs,例如将它们全部设置为输入:

代码语言:javascript
复制
void setup() {
  for (int i = 0; i < 8; i++) {
    pinMode(PARALLEL_0 + i, INPUT);
  }
}

之后,您可以使用以下函数将8个引脚设置为输入或输出,并读取输入值和写入输出值:

代码语言:javascript
复制
void parallel_set_inputs(void) {
  REG_WRITE(GPIO_ENABLE_W1TC_REG, 0xFF << PARALLEL_0);
}

void parallel_set_outputs(void) {
  REG_WRITE(GPIO_ENABLE_W1TS_REG, 0xFF << PARALLEL_0);
}

uint8_t parallel_read(void) {
  uint32_t input = REG_READ(GPIO_IN_REG);

  return (input >> PARALLEL_0);
}

void parallel_write(uint8_t value) {
  uint32_t output =
    (REG_READ(GPIO_OUT_REG) & ~(0xFF << PARALLEL_0)) | (((uint32_t)value) << PARALLEL_0);

  REG_WRITE(GPIO_OUT_REG, output);
}
票数 13
EN

Stack Overflow用户

发布于 2019-01-30 20:21:06

对于高带宽并行数据输出,您可能需要研究ESP32 32的I2S外围设备的液晶显示模式。

请参阅ESP32 TRM中的12.5.1节和关于将外围设备映射到所需引脚的第4章。这种方法的好处是,您可以将多达24位的输出从外设映射到输出引脚。

第12.4.4节规定:

ESP32 I2S模块执行数据传输操作.按用户配置的顺序或并行方式时钟数据。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52348930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档