esp32开发与应用(从esp32到esp32s3)
【 声明版权所有欢迎转载请勿用于商业用途。 联系信箱feixiaoxing 163.com】从最早的8266到现在的esp32s31其实本身esp32有很多的型号。这些型号差异不小使用的时候需要注意下。当然不仅仅是产品本身性能的差异有的时候也可能是供货、成本、产品规划的差异让我们选择不同的esp32芯片。1、停止生产有的时候替换是因为之前的产品厂家开始不再生产了。这个时候就要开始慢慢导入新的产品。导入的时候不光是软件有的时候硬件、pin脚也要做同步的修改。2、产品性能提升的需要除了停供产生的替换还有一种情况就是产品性能的需要。比如之前的产品对cpu要求比较低但是现在要求相对而言要高一点这种情况下出于性能的原因也需要替换一下esp32的类型。3、新增接口的需要接口方面主要有两种情况。一种是接口的数量不够这种情况下大概率是原来的接口数量偏少现在需要接口更多的模块还有一种情况就是之前的模块不具备某种接口比如usb这种情况也是很普遍的。4、交叉备份的需要芯片厂家生产芯片一般都是交替生产的特定类型的芯片不一定每个月都生产。这种情况下让自己的底板可以支持多种模块这反而是一种比较稳妥的选择。5、主要是pin脚的差别不同的esp32模块如果差异不大一般改起来也不是特别麻烦。比如我们之前写的这篇文章https://feixiaoxing.blog.csdn.net/article/details/162178073?spm1001.2014.3001.5502如果换到esp32s3上面其实替换一下tp的编号就可以了其他部分都是一样的#include stdio.h #include stdlib.h #include string.h #include freertos/FreeRTOS.h #include freertos/task.h #include driver/spi_master.h #include driver/gpio.h #include esp_log.h #include esp_timer.h #include lvgl.h static void lvgl_task(void *arg); // CONFIG #define LCD_W 480 #define LCD_H 320 #define PIN_MOSI 13 #define PIN_CLK 14 #define PIN_CS 15 #define PIN_DC 2 #define PIN_RST 4 #define PIN_BL 12 #define TP_MOSI 6 #define TP_MISO 7 #define TP_CLK 18 #define TP_CS 5 #define TP_IRQ 8 static spi_device_handle_t spi_lcd; static spi_device_handle_t spi_tp; static const char *TAG ILI9488_LVGL; // // GPIO control // static inline void dc_cmd(void) { gpio_set_level(PIN_DC, 0); } static inline void dc_data(void) { gpio_set_level(PIN_DC, 1); } static void lcd_reset(void) { gpio_set_level(PIN_RST, 0); vTaskDelay(pdMS_TO_TICKS(100)); gpio_set_level(PIN_RST, 1); vTaskDelay(pdMS_TO_TICKS(150)); } // // SPI CMD / DATA // static void lcd_cmd(uint8_t cmd) { spi_transaction_t t { .length 8, .tx_buffer cmd, }; dc_cmd(); spi_device_polling_transmit(spi_lcd, t); } static void lcd_data(const void *data, int len) { spi_transaction_t t { .length len * 8, .tx_buffer data, }; dc_data(); spi_device_polling_transmit(spi_lcd, t); } // // ILI9488 INIT (stable version) // static void ili9488_init(void) { lcd_reset(); lcd_cmd(0x01); // Software reset vTaskDelay(pdMS_TO_TICKS(120)); lcd_cmd(0x11); // Sleep out vTaskDelay(pdMS_TO_TICKS(120)); // RGB565 mode (important for stability) lcd_cmd(0x3A); uint8_t pix 0x66; lcd_data(pix, 1); // MADCTL (display orientation) lcd_cmd(0x36); uint8_t mad 0x28; // change to 0x28 if upside-down lcd_data(mad, 1); lcd_cmd(0x29); // Display ON vTaskDelay(pdMS_TO_TICKS(50)); ESP_LOGI(TAG, LCD init OK); } // // Set drawing window // static void set_window(int x1,int y1,int x2,int y2) { uint8_t d[4]; lcd_cmd(0x2A); d[0]x18; d[1]x1; d[2]x28; d[3]x2; lcd_data(d,4); lcd_cmd(0x2B); d[0]y18; d[1]y1; d[2]y28; d[3]y2; lcd_data(d,4); lcd_cmd(0x2C); } // // Touch read (XPT2046 style) // static uint16_t tp_read(uint8_t cmd) { uint8_t tx[3] {cmd,0,0}; uint8_t rx[3] {0}; spi_transaction_t t { .length 24, .tx_buffer tx, .rx_buffer rx, }; spi_device_polling_transmit(spi_tp, t); return ((rx[1] 8) | rx[2]) 3; } static void touch_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { static bool touched false; if (gpio_get_level(TP_IRQ) 0) { data-state LV_INDEV_STATE_PRESSED; // Read raw touch coordinates uint16_t x_raw tp_read(0xD0); uint16_t y_raw tp_read(0x90); // Calibrate and convert to screen coordinates // Swap X and Y, and invert Y axis for correct orientation // Adjust these values based on your touch panel calibration int x (LCD_W * (3900 - y_raw)) / 3900; // very critical, by feixiaoxing int y LCD_H - 1 - (LCD_H * (x_raw - 100)) / 3900; // Clamp values if (x 0) x 0; if (x LCD_W) x LCD_W - 1; if (y 0) y 0; if (y LCD_H) y LCD_H - 1; data-point.x x; data-point.y y; if (!touched) { ESP_LOGI(TAG, Touch: x%d, y%d (raw: x%d, y%d), data-point.x, data-point.y, x_raw, y_raw); touched true; } } else { data-state LV_INDEV_STATE_RELEASED; touched false; } } // // LVGL flush (stable version) // static uint8_t line_buf[480 * 3]; static void lcd_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { int w area-x2 - area-x1 1; int h area-y2 - area-y1 1; set_window(area-x1, area-y1, area-x2, area-y2); dc_data(); spi_transaction_t t { .length w * 3 * 8, .tx_buffer line_buf, }; for (int y 0; y h; y) { for (int x 0; x w; x) { uint16_t c color_p[y * w x].full; line_buf[x*30] ((c 11) 0x1F) 3; line_buf[x*31] ((c 5) 0x3F) 2; line_buf[x*32] (c 0x1F) 3; } spi_device_polling_transmit(spi_lcd, t); } lv_disp_flush_ready(disp); } // Lottery Program // static lv_obj_t *label_number; // Display the random number static lv_obj_t *btn_start; // Start button static lv_obj_t *btn_stop; // Stop button static bool is_running false; // Lottery running flag static int current_number 0; // Current random number // Lottery update task static void lottery_task(void *arg) { char buf[16]; while (1) { if (is_running) { // Generate random number between 1-999 current_number (rand() % 1000); sprintf(buf, %03d, current_number); lv_label_set_text(label_number, buf); } vTaskDelay(pdMS_TO_TICKS(50)); // Update every 50ms } } // Start button callback static void btn_start_event_cb(lv_event_t *e) { lv_event_code_t code lv_event_get_code(e); if (code LV_EVENT_CLICKED) { if (!is_running) { is_running true; ESP_LOGI(TAG, Lottery started); } } } // Stop button callback static void btn_stop_event_cb(lv_event_t *e) { lv_event_code_t code lv_event_get_code(e); if (code LV_EVENT_CLICKED) { if (is_running) { is_running false; ESP_LOGI(TAG, Lottery stopped: %03d, current_number); } } } static void ui_create(void) { // Initialize random seed srand(esp_timer_get_time()); // Create title label lv_obj_t *label_title lv_label_create(lv_scr_act()); lv_label_set_text(label_title, LOTTERY); lv_obj_align(label_title, LV_ALIGN_CENTER, 0, -80); lv_obj_set_style_text_font(label_title, lv_font_montserrat_14, LV_PART_MAIN); // Create number display label label_number lv_label_create(lv_scr_act()); lv_label_set_text(label_number, 0); lv_obj_align(label_number, LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_text_font(label_number, lv_font_montserrat_32, LV_PART_MAIN); lv_obj_set_style_text_color(label_number, lv_color_hex(0xFF0000), LV_PART_MAIN); // Create start button btn_start lv_btn_create(lv_scr_act()); lv_obj_set_size(btn_start, 120, 50); lv_obj_align(btn_start, LV_ALIGN_CENTER, -80, 70); lv_obj_add_event_cb(btn_start, btn_start_event_cb, LV_EVENT_ALL, NULL); lv_obj_t *label_start lv_label_create(btn_start); lv_label_set_text(label_start, Start); lv_obj_center(label_start); // Create stop button btn_stop lv_btn_create(lv_scr_act()); lv_obj_set_size(btn_stop, 120, 50); lv_obj_align(btn_stop, LV_ALIGN_CENTER, 80, 70); lv_obj_add_event_cb(btn_stop, btn_stop_event_cb, LV_EVENT_ALL, NULL); lv_obj_t *label_stop lv_label_create(btn_stop); lv_label_set_text(label_stop, Stop); lv_obj_center(label_stop); // Create lottery task xTaskCreate(lottery_task, lottery, 2048, NULL, 5, NULL); } // LVGL Tick Timer static void lv_tick_cb(void *arg) { lv_tick_inc(1); // LVGL 1ms tick } // // Backlight control // static void backlight_init(void) { gpio_config_t io { .pin_bit_mask 1ULL PIN_BL, .mode GPIO_MODE_OUTPUT }; gpio_config(io); gpio_set_level(PIN_BL, 1); } // // MAIN ENTRY // void app_main(void) { gpio_set_direction(PIN_DC, GPIO_MODE_OUTPUT); gpio_set_direction(PIN_RST, GPIO_MODE_OUTPUT); // LCD SPI spi_bus_config_t bus_lcd { .mosi_io_num PIN_MOSI, .miso_io_num -1, .sclk_io_num PIN_CLK, .max_transfer_sz 1024 * 10 }; spi_bus_initialize(SPI2_HOST, bus_lcd, SPI_DMA_CH_AUTO); spi_device_interface_config_t dev_lcd { .clock_speed_hz 20 * 1000 * 1000, // 20MHz .mode 0, .spics_io_num PIN_CS, .queue_size 7, }; spi_bus_add_device(SPI2_HOST, dev_lcd, spi_lcd); // TOUCH SPI spi_bus_config_t bus_tp { .mosi_io_num TP_MOSI, .miso_io_num TP_MISO, .sclk_io_num TP_CLK, .max_transfer_sz 32 }; spi_bus_initialize(SPI3_HOST, bus_tp, SPI_DMA_CH_AUTO); spi_device_interface_config_t dev_tp { .clock_speed_hz 2 * 1000 * 1000, .mode 0, .spics_io_num TP_CS, .queue_size 3, }; spi_bus_add_device(SPI3_HOST, dev_tp, spi_tp); gpio_set_direction(TP_IRQ, GPIO_MODE_INPUT); // LCD INIT ili9488_init(); // LVGL INIT lv_init(); static lv_color_t *buf1; buf1 heap_caps_malloc(LCD_W * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA); static lv_disp_draw_buf_t draw_buf; lv_disp_draw_buf_init(draw_buf, buf1, NULL, LCD_W * 20); // LVGL tick timer (1ms) esp_timer_handle_t timer; const esp_timer_create_args_t tick_args { .callback lv_tick_cb, .name lv_tick }; esp_timer_create(tick_args, timer); esp_timer_start_periodic(timer, 1000); // 1ms static lv_disp_drv_t disp_drv; lv_disp_drv_init(disp_drv); disp_drv.hor_res LCD_W; disp_drv.ver_res LCD_H; disp_drv.flush_cb lcd_flush; disp_drv.draw_buf draw_buf; disp_drv.full_refresh 1; lv_disp_drv_register(disp_drv); static lv_indev_drv_t indev_drv; lv_indev_drv_init(indev_drv); indev_drv.type LV_INDEV_TYPE_POINTER; indev_drv.read_cb touch_read; lv_indev_drv_register(indev_drv); ui_create(); // Create LVGL UI // Create LVGL task handler in separate task xTaskCreate(lvgl_task, lvgl_task, 4096, NULL, 5, NULL); // no flush operation here again backlight_init(); // Initialize backlight here, by feixiaoxing // Keep main task alive while (1) { vTaskDelay(pdMS_TO_TICKS(100)); } } // LVGL Task static void lvgl_task(void *arg) { while (1) { lv_timer_handler(); // LVGL main loop vTaskDelay(pdMS_TO_TICKS(10)); } }