added DeveiceAddDemo

This commit is contained in:
nopnop2002 2024-09-09 11:17:01 +09:00
parent 2e6910b549
commit fa0a78a837
6 changed files with 559 additions and 0 deletions

View File

@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../components/ssd1306)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ssd1306)

253
DeviceAddDemo/README.md Normal file
View File

@ -0,0 +1,253 @@
# DeviceAddDemo for SSD1306
I received a question about using an SSD1306 and other i2c/spi devices at the same time.
A new i2c driver is now available in ESP-IDF V5.2.
This complicated the use of other i2c devices at the same time as the SSD1306.
I will record the survey results here.
If you want to use SSD1306 and other i2c/spi devices at the same time, please follow the guide below.
# Using i2c interface
### Case 1
Use multiple i2c devices on one i2c bus.
SCL and SDA are shared by all devices.
```
I2C_NUM_0 --+-- I2C SSD1306
+---Any I2C Device
```
In the XTENSA series, you can use I2C_NUM_1 bus instead of I2C_NUM_0 bus.
```
I2C_NUM_1 --+-- I2C SSD1306
+---Any I2C Device
```
- Legacy driver
We only need to run this code once.
There is no need to memorize any data.
SSD1306 and other device use the same frequency.
Please note that the maximum i2c clock frequency of SSD1306 is 400KHz.
Under ESP-IDF V5.2 or later, this project uses the new I2C driver, but there is an option to force the use of the legacy I2C driver.
```
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_SDA_GPIO,
.scl_io_num = CONFIG_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));
```
This project uses the following functions to install the i2c driver.
```
i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
```
This project allows you to use an initialization function that does not install the i2c driver.
```
i2c_device_add(&dev, i2c_num, CONFIG_RESET_GPIO);
```
The i2c driver must be installed before using this initialization function.
```
// install i2c master driver
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_SDA_GPIO,
.scl_io_num = CONFIG_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_config));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));
// add new device to i2c bus
i2c_device_add(&dev, I2C_NUM_0, CONFIG_RESET_GPIO);
```
- New i2c driver
We need to run this code on the first i2c device.
```
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.i2c_port = I2C_NUM_0,
.scl_io_num = scl,
.sda_io_num = sda,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = I2C_ADDRESS1,
.scl_speed_hz = I2C_MASTER_FREQ_HZ1,
};
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
```
We need to run this code on the second device.
SSD1306 and other device can use different frequencies.
```
// We need to load bus_handle from somewhere.
i2c_device_config_t dev_cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = I2C_ADDRESS2,
.scl_speed_hz = I2C_MASTER_FREQ_HZ2,
};
i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
```
This project uses the following functions to install the i2c driver.
```
i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
```
This project allows you to use an initialization function that does not install the i2c driver.
```
i2c_bus_add(&dev, bus_handle, i2c_num, CONFIG_RESET_GPIO);
```
The i2c driver must be installed before using this initialization function.
```
// install i2c master driver
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.i2c_port = I2C_NUM_0,
.scl_io_num = CONFIG_SCL_GPIO,
.sda_io_num = CONFIG_SDA_GPIO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
// add new device to i2c bus
i2c_bus_add(&dev, bus_handle, I2C_NUM_0, CONFIG_RESET_GPIO);
```
---
### Case 2
Use multiple i2c devices on two i2c bus.
SCL and SDA each use separate GPIOs.
Install the i2c master driver for each of I2C_NUM_0 and I2C_NUM_1.
The frequencies of I2C_NUM_0 and I2C_NUM_1 can be set completely independently.
```
I2C_NUM_0 ----- I2C SSD1306
I2C_NUM_1 ----- Any I2C Device
```
This is possible with both the new i2c driver or the legacy i2c driver, but **both buses must use the same driver.**
This is not acceptable.
```
I2C_NUM_0 ----- I2C SSD1306 using new i2c driver
I2C_NUM_1 ----- Any I2C Device using legacy i2c driver
```
If other i2c devices use legacy i2c drivers, SSD1306 must also use legacy i2c drivers.
Under ESP-IDF V5.2 or later, this project uses the new I2C driver, but there is an option to force the use of the legacy I2C driver.
```
I2C_NUM_0 ----- I2C SSD1306 using legacy i2c driver
I2C_NUM_1 ----- Any I2C Device using legacy i2c driver
```
If SSD1306 use new i2c drivers, other i2c devices must also use new i2c drivers.
```
I2C_NUM_0 ----- I2C SSD1306 using new i2c driver
I2C_NUM_1 ----- Any I2C Device using new i2c driver
```
ESP32C series has only one i2c bus.
This is not available on the ESP32C series.
Can only be used with XTENSA series.
---
# Using spi interface
### Case 1
Use multiple spi devices on one spi bus.
MOSI and SCLK are shared by all devices.
```
SPI2_HOST --+-- SPI SSD1306
+---Any SPI Device
```
In the XTENSA series, you can use SPI2_HOST bus instead of SPI3_HOST bus.
```
SPI3_HOST --+-- SPI SSD1306
+---Any SPI Device
```
We only need to run this code once.
```
spi_bus_config_t spi_bus_config = {
.mosi_io_num = CONFIG_MOSI_GPIO,
.miso_io_num = -1,
.sclk_io_num = CONFIG_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 0,
.flags = 0
};
ESP_LOGI(tag, "SPI HOST_ID=%d", host_id);
esp_err_t ret = spi_bus_initialize( host_id, &spi_bus_config, SPI_DMA_CH_AUTO );
ESP_LOGI(tag, "spi_bus_initialize=%d",ret);
```
This project uses the following functions to install the spi driver.
```
spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
```
This project allows you to use an initialization function that does not install the spi driver.
```
spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
```
The spi driver must be installed before using this initialization function.
```
// install spi master driver
spi_bus_config_t spi_bus_config = {
.mosi_io_num = CONFIG_MOSI_GPIO,
.miso_io_num = -1,
.sclk_io_num = CONFIG_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 0,
.flags = 0
};
esp_err_t ret = spi_bus_initialize( SPI2_HOST, &spi_bus_config, SPI_DMA_CH_AUTO );
ESP_LOGI(tag, "spi_bus_initialize=%d",ret);
assert(ret==ESP_OK);
// add new device to spi bus
spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
```
### Case 2
Use multiple spi devices on two spi bus.
MOSI and SCLK each use separate GPIOs.
Install the spi master driver for each of SPI2_HOST and SPI3_HOST.
```
SPI2_HOST ----- SPI SSD1306
SPI3_HOST ----- Any SPI Device
```

View File

@ -0,0 +1,4 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS "")
register_component()

View File

@ -0,0 +1,8 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#

268
DeviceAddDemo/main/main.c Normal file
View File

@ -0,0 +1,268 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#if CONFIG_LEGACY_DRIVER
#include "driver/i2c.h"
#else
#include "driver/i2c_master.h"
#endif
#include "ssd1306.h"
#include "font8x8_basic.h"
/*
You have to set this config value with menuconfig
CONFIG_INTERFACE
for i2c
CONFIG_MODEL
CONFIG_SDA_GPIO
CONFIG_SCL_GPIO
CONFIG_RESET_GPIO
for SPI
CONFIG_CS_GPIO
CONFIG_DC_GPIO
CONFIG_RESET_GPIO
*/
#define tag "SSD1306"
void app_main(void)
{
SSD1306_t dev;
int center, top, bottom;
char lineChar[20];
#if CONFIG_I2C_INTERFACE
ESP_LOGI(tag, "INTERFACE is i2c");
ESP_LOGI(tag, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
ESP_LOGI(tag, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
#if CONFIG_I2C_PORT_0
i2c_port_t i2c_num = I2C_NUM_0;
#else
i2c_port_t i2c_num = I2C_NUM_1;
#endif
#if CONFIG_LEGACY_DRIVER
ESP_LOGI(tag, "I2C_LEGACY_DRIVER");
// install i2c master driver
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = CONFIG_SDA_GPIO,
.scl_io_num = CONFIG_SCL_GPIO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000
};
ESP_ERROR_CHECK(i2c_param_config(i2c_num, &i2c_config));
ESP_ERROR_CHECK(i2c_driver_install(i2c_num, I2C_MODE_MASTER, 0, 0, 0));
// add new device to i2c bus
i2c_device_add(&dev, i2c_num, CONFIG_RESET_GPIO);
#else
ESP_LOGI(tag, "I2C_NEW_DRIVER");
// install i2c master driver
i2c_master_bus_config_t i2c_mst_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.i2c_port = i2c_num,
.scl_io_num = CONFIG_SCL_GPIO,
.sda_io_num = CONFIG_SDA_GPIO,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
// add new device to i2c bus
i2c_bus_add(&dev, bus_handle, i2c_num, CONFIG_RESET_GPIO);
#endif
#endif // CONFIG_I2C_INTERFACE
#if CONFIG_SPI_INTERFACE
ESP_LOGI(tag, "INTERFACE is SPI");
ESP_LOGI(tag, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
ESP_LOGI(tag, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
ESP_LOGI(tag, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
ESP_LOGI(tag, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
spi_bus_config_t spi_bus_config = {
.mosi_io_num = CONFIG_MOSI_GPIO,
.miso_io_num = -1,
.sclk_io_num = CONFIG_SCLK_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 0,
.flags = 0
};
#if CONFIG_SPI2_HOST
spi_host_device_t host_id = SPI2_HOST;
#else
spi_host_device_t host_id = SPI3_HOST;
#endif
ESP_LOGI(tag, "SPI HOST_ID=%d", host_id);
esp_err_t ret = spi_bus_initialize( host_id, &spi_bus_config, SPI_DMA_CH_AUTO );
ESP_LOGI(tag, "spi_bus_initialize=%d",ret);
assert(ret==ESP_OK);
spi_device_add(&dev, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE
#if CONFIG_FLIP
dev._flip = true;
ESP_LOGW(tag, "Flip upside down");
#endif
#if CONFIG_SSD1306_128x64
ESP_LOGI(tag, "Panel is 128x64");
ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
ESP_LOGI(tag, "Panel is 128x32");
ssd1306_init(&dev, 128, 32);
#endif // CONFIG_SSD1306_128x32
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
vTaskDelay(3000 / portTICK_PERIOD_MS);
#if CONFIG_SSD1306_128x64
top = 2;
center = 3;
bottom = 8;
ssd1306_display_text(&dev, 0, "SSD1306 128x64", 14, false);
ssd1306_display_text(&dev, 1, "ABCDEFGHIJKLMNOP", 16, false);
ssd1306_display_text(&dev, 2, "abcdefghijklmnop",16, false);
ssd1306_display_text(&dev, 3, "Hello World!!", 13, false);
//ssd1306_clear_line(&dev, 4, true);
//ssd1306_clear_line(&dev, 5, true);
//ssd1306_clear_line(&dev, 6, true);
//ssd1306_clear_line(&dev, 7, true);
ssd1306_display_text(&dev, 4, "SSD1306 128x64", 14, true);
ssd1306_display_text(&dev, 5, "ABCDEFGHIJKLMNOP", 16, true);
ssd1306_display_text(&dev, 6, "abcdefghijklmnop",16, true);
ssd1306_display_text(&dev, 7, "Hello World!!", 13, true);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
top = 1;
center = 1;
bottom = 4;
ssd1306_display_text(&dev, 0, "SSD1306 128x32", 14, false);
ssd1306_display_text(&dev, 1, "Hello World!!", 13, false);
//ssd1306_clear_line(&dev, 2, true);
//ssd1306_clear_line(&dev, 3, true);
ssd1306_display_text(&dev, 2, "SSD1306 128x32", 14, true);
ssd1306_display_text(&dev, 3, "Hello World!!", 13, true);
#endif // CONFIG_SSD1306_128x32
vTaskDelay(3000 / portTICK_PERIOD_MS);
// Display Count Down
uint8_t image[24];
memset(image, 0, sizeof(image));
ssd1306_display_image(&dev, top, (6*8-1), image, sizeof(image));
ssd1306_display_image(&dev, top+1, (6*8-1), image, sizeof(image));
ssd1306_display_image(&dev, top+2, (6*8-1), image, sizeof(image));
for(int font=0x39;font>0x30;font--) {
memset(image, 0, sizeof(image));
ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
memcpy(image, font8x8_basic_tr[font], 8);
if (dev._flip) ssd1306_flip(image, 8);
ssd1306_display_image(&dev, top+1, (7*8-1), image, 8);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// Scroll Up
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, 0, "---Scroll UP---", 16, true);
//ssd1306_software_scroll(&dev, 7, 1);
ssd1306_software_scroll(&dev, (dev._pages - 1), 1);
for (int line=0;line<bottom+10;line++) {
lineChar[0] = 0x01;
sprintf(&lineChar[1], " Line %02d", line);
ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
// Scroll Down
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, 0, "--Scroll DOWN--", 16, true);
//ssd1306_software_scroll(&dev, 1, 7);
ssd1306_software_scroll(&dev, 1, (dev._pages - 1) );
for (int line=0;line<bottom+10;line++) {
lineChar[0] = 0x02;
sprintf(&lineChar[1], " Line %02d", line);
ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
// Page Down
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, 0, "---Page DOWN---", 16, true);
ssd1306_software_scroll(&dev, 1, (dev._pages-1) );
for (int line=0;line<bottom+10;line++) {
//if ( (line % 7) == 0) ssd1306_scroll_clear(&dev);
if ( (line % (dev._pages-1)) == 0) ssd1306_scroll_clear(&dev);
lineChar[0] = 0x02;
sprintf(&lineChar[1], " Line %02d", line);
ssd1306_scroll_text(&dev, lineChar, strlen(lineChar), false);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
// Horizontal Scroll
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, center, "Horizontal", 10, false);
ssd1306_hardware_scroll(&dev, SCROLL_RIGHT);
vTaskDelay(5000 / portTICK_PERIOD_MS);
ssd1306_hardware_scroll(&dev, SCROLL_LEFT);
vTaskDelay(5000 / portTICK_PERIOD_MS);
ssd1306_hardware_scroll(&dev, SCROLL_STOP);
// Vertical Scroll
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, center, "Vertical", 8, false);
ssd1306_hardware_scroll(&dev, SCROLL_DOWN);
vTaskDelay(5000 / portTICK_PERIOD_MS);
ssd1306_hardware_scroll(&dev, SCROLL_UP);
vTaskDelay(5000 / portTICK_PERIOD_MS);
ssd1306_hardware_scroll(&dev, SCROLL_STOP);
// Invert
ssd1306_clear_screen(&dev, true);
ssd1306_contrast(&dev, 0xff);
ssd1306_display_text(&dev, center, " Good Bye!!", 12, true);
vTaskDelay(5000 / portTICK_PERIOD_MS);
// Fade Out
ssd1306_fadeout(&dev);
#if 0
// Fade Out
for(int contrast=0xff;contrast>0;contrast=contrast-0x20) {
ssd1306_contrast(&dev, contrast);
vTaskDelay(40);
}
#endif
// Restart module
esp_restart();
}

View File

@ -0,0 +1,18 @@
#
# ESP32-specific
#
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
#
# ESP32S2-specific
#
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=240
#
# ESP32S3-specific
#
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240