|
楼主 |
发表于 2021-10-26 11:11:48
|
显示全部楼层
移植代码,就这么点:
- /* SPI Master example
- This example code is in the Public Domain (or CC0 licensed, at your option.)
- Unless required by applicable law or agreed to in writing, this
- software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "sdkconfig.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/event_groups.h"
- #include "freertos/portmacro.h"
- #include "esp_system.h"
- #include "esp_task.h"
- #include "driver/spi_master.h"
- #include "driver/gpio.h"
- #include "lvgl/lvgl.h"
- #include "lv_demos/lv_demo.h"
- #include "app.h"
- #define LCD_PANEL_W (320)
- #define LCD_PANEL_H (240)
- #define DISP_BUF_SIZE (LCD_PANEL_W*10)
- #define LENOF(ar) (sizeof(ar)/sizeof(ar[0]))
- /*
- This code displays some fancy graphics on the 320x240 LCD on an ESP-WROVER_KIT board.
- This example demonstrates the use of both spi_device_transmit as well as
- spi_device_queue_trans/spi_device_get_trans_result and pre-transmit callbacks.
- Some info about the ILI9341/ST7789V: It has an C/D line, which is connected to a GPIO here. It expects this
- line to be low for a command and high for data. We use a pre-transmit callback here to control that
- line: every transaction has as the user-definable argument the needed state of the D/C line and just
- before the transaction is sent, the callback will set this line to the correct state.
- */
- #define LCD_HOST HSPI_HOST
- #define DMA_CHAN 2
- #define PIN_NUM_BCKL 5
- #define PIN_NUM_CS 22
- #define PIN_NUM_DC 21
- #define PIN_NUM_RST 18
- #define PIN_NUM_MISO 17
- #define PIN_NUM_MOSI 23
- #define PIN_NUM_CLK 19
- //To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use,
- //but less overhead for setting up / finishing transfers. Make sure LCD_PANEL_H is dividable by this.
- #define PARALLEL_LINES 16
- /*
- The LCD needs a bunch of command/argument values to be initialized. They are stored in this struct.
- */
- typedef struct {
- uint8_t cmd;
- uint8_t data[16];
- uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
- } lcd_init_cmd_t;
- //Place data into DRAM. Constant data gets placed into DROM by default, which is not accessible by DMA.
- DRAM_ATTR static const lcd_init_cmd_t lcm_init_cmds[] = {
- /* Power contorl B, power control = 0, DC_ENA = 1 */
- {0xCF, {0x00, 0x83, 0x30}, 3},
- /* Power on sequence control,
- * cp1 keeps 1 frame, 1st frame enable
- * vcl = 0, ddvdh=3, vgh=1, vgl=2
- * DDVDH_ENH=1
- */
- {0xED, {0x64, 0x03, 0x12, 0x81}, 4},
- /* Driver timing control A,
- * non-overlap=default +1
- * EQ=default - 1, CR=default
- * pre-charge=default - 1
- */
- {0xE8, {0x85, 0x01, 0x79}, 3},
- /* Power control A, Vcore=1.6V, DDVDH=5.6V */
- {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5},
- /* Pump ratio control, DDVDH=2xVCl */
- {0xF7, {0x20}, 1},
- /* Driver timing control, all=0 unit */
- {0xEA, {0x00, 0x00}, 2},
- /* Power control 1, GVDD=4.75V */
- {0xC0, {0x26}, 1},
- /* Power control 2, DDVDH=VCl*2, VGH=VCl*7, VGL=-VCl*3 */
- {0xC1, {0x11}, 1},
- /* VCOM control 1, VCOMH=4.025V, VCOML=-0.950V */
- {0xC5, {0x35, 0x3E}, 2},
- /* VCOM control 2, VCOMH=VMH-2, VCOML=VML-2 */
- {0xC7, {0xBE}, 1},
- /* Memory access contorl, MX=MY=0, MV=1, ML=0, BGR=1, MH=0 */
- {0x36, {0xF8}, 1},
- /* Pixel format, 16bits/pixel for RGB/MCU interface */
- {0x3A, {0x55}, 1},
- /* Frame rate control, f=fosc, 70Hz fps */
- {0xB1, {0x00, 0x1B}, 2},
- /* Enable 3G, disabled */
- {0xF2, {0x08}, 1},
- /* Gamma set, curve 1 */
- {0x26, {0x01}, 1},
- /* Positive gamma correction */
- {0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15},
- /* Negative gamma correction */
- {0xE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15},
- /* Column address set, SC=0, EC=0xEF */
- {0x2A, {0x00, 0x00, 0x00, 0xEF}, 4},
- /* Page address set, SP=0, EP=0x013F */
- {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4},
- /* Memory write */
- {0x2C, {0}, 0},
- /* Entry mode set, Low vol detect disabled, normal display */
- {0xB7, {0x07}, 1},
- /* Display function control */
- {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4},
- /* Sleep out */
- {0x11, {0}, 0x80},
- /* Display on */
- {0x29, {0}, 0x80},
- {0, {0}, 0xff},
- };
- /* Send a command to the LCD. Uses spi_device_polling_transmit, which waits
- * until the transfer is complete.
- *
- * Since command transactions are usually small, they are handled in polling
- * mode for higher speed. The overhead of interrupt transactions is more than
- * just waiting for the transaction to complete.
- */
- static void IRAM_ATTR lcd_cmd(spi_device_handle_t spi, const uint8_t cmd)
- {
- esp_err_t ret;
- spi_transaction_t t;
- memset(&t, 0, sizeof(t)); //Zero out the transaction
- t.length = 8; //Command is 8 bits
- t.tx_buffer = &cmd; //The data is the cmd itself
- t.user = (void*)0; //D/C needs to be set to 0
- ret = spi_device_polling_transmit(spi, &t); //Transmit!
- assert(ret == ESP_OK); //Should have had no issues.
- }
- /* Send data to the LCD. Uses spi_device_polling_transmit, which waits until the
- * transfer is complete.
- *
- * Since data transactions are usually small, they are handled in polling
- * mode for higher speed. The overhead of interrupt transactions is more than
- * just waiting for the transaction to complete.
- */
- static void IRAM_ATTR lcd_data(spi_device_handle_t spi, const uint8_t* data, int len)
- {
- esp_err_t ret;
- spi_transaction_t t;
- if (len == 0)
- return; //no need to send anything
- memset(&t, 0, sizeof(t)); //Zero out the transaction
- t.length = len * 8; //Len is in bytes, transaction length is in bits.
- t.tx_buffer = data; //Data
- t.user = (void*)1; //D/C needs to be set to 1
- ret = spi_device_polling_transmit(spi, &t); //Transmit!
- assert(ret == ESP_OK); //Should have had no issues.
- }
- //This function is called (in irq context!) just before a transmission starts. It will
- //set the D/C line to the value indicated in the user field.
- static void IRAM_ATTR lcd_spi_pre_transfer_callback(spi_transaction_t* t)
- {
- int dc = (int)t->user;
- gpio_set_level(PIN_NUM_DC, dc);
- }
- //Initialize the display
- static void lcd_init(spi_device_handle_t spi)
- {
- const lcd_init_cmd_t* lcd_init_cmds;
- int cmd = 0;
- //Initialize non-SPI GPIOs
- gpio_set_direction(PIN_NUM_DC, GPIO_MODE_OUTPUT);
- gpio_set_direction(PIN_NUM_RST, GPIO_MODE_OUTPUT);
- gpio_set_direction(PIN_NUM_BCKL, GPIO_MODE_OUTPUT);
- //Reset the display
- gpio_set_level(PIN_NUM_RST, 0);
- vTaskDelay(100 / portTICK_RATE_MS);
- gpio_set_level(PIN_NUM_RST, 1);
- vTaskDelay(100 / portTICK_RATE_MS);
- //Send all the commands
- lcd_init_cmds = lcm_init_cmds;
- while (lcd_init_cmds[cmd].databytes != 0xff) {
- lcd_cmd(spi, lcd_init_cmds[cmd].cmd);
- lcd_data(spi, lcd_init_cmds[cmd].data, lcd_init_cmds[cmd].databytes & 0x1F);
- if (lcd_init_cmds[cmd].databytes & 0x80) {
- vTaskDelay(100 / portTICK_RATE_MS);
- }
- cmd++;
- }
- ///Enable backlight
- gpio_set_level(PIN_NUM_BCKL, 1);
- }
- static void IRAM_ATTR send_line_finish(spi_device_handle_t spi)
- {
- spi_transaction_t* rtrans;
- esp_err_t ret;
- //Wait for all 6 transactions to be done and get back the results.
- for (int x = 0; x < 6; x++) {
- ret = spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
- assert(ret == ESP_OK);
- //We could inspect rtrans now if we received any info back. The LCD is treated as write-only, though.
- }
- }
- static void IRAM_ATTR lv_simulator_disp_flush_callback(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_t* color_p)
- {
- static bool need_wait = false;
- static spi_transaction_t trans[6];
- size_t count;
- if (need_wait) {
- send_line_finish(disp_drv->user_data);
- }
- if (color_p) {
- esp_err_t ret;
- int x;
- for (x = 0; x < 6; x++) {
- memset(&trans[x], 0, sizeof(spi_transaction_t));
- if ((x & 1) == 0) {
- //Even transfers are commands
- trans[x].length = 8;
- trans[x].user = (void*)0;
- } else {
- //Odd transfers are data
- trans[x].length = 8 * 4;
- trans[x].user = (void*)1;
- }
- trans[x].flags = SPI_TRANS_USE_TXDATA;
- }
- count = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1);
- trans[0].tx_data[0] = 0x2A; //Column Address Set
- trans[1].tx_data[0] = (area->x1 >> 8); //Start Col High
- trans[1].tx_data[1] = (area->x1 & 0xFF); //Start Col Low
- trans[1].tx_data[2] = (area->x2 >> 8); //End Col High
- trans[1].tx_data[3] = (area->x2 & 0xFF); //End Col Low
- trans[2].tx_data[0] = 0x2B; //Page address set
- trans[3].tx_data[0] = (area->y1 >> 8); //Start page high
- trans[3].tx_data[1] = (area->y1 & 0xFF); //start page low
- trans[3].tx_data[2] = (area->y2 >> 8); //end page high
- trans[3].tx_data[3] = (area->y2 & 0xFF); //end page low
- trans[4].tx_data[0] = 0x2C; //memory write
- trans[5].tx_buffer = color_p; //finally send the line data
- trans[5].length = 16 * count; //Data length, in bits
- trans[5].flags = 0; //undo SPI_TRANS_USE_TXDATA flag
- //Queue all transactions.
- for (x = 0; x < 6; x++) {
- ret = spi_device_queue_trans(disp_drv->user_data, &trans[x], portMAX_DELAY);
- assert(ret == ESP_OK);
- }
- need_wait = true;
- lv_disp_flush_ready(disp_drv);
- }
- }
- static void IRAM_ATTR lv_simulator_init(spi_device_handle_t spi)
- {
- static lv_disp_draw_buf_t display_buffer;
- static lv_color_t buf1[DISP_BUF_SIZE];
- static lv_color_t buf2[DISP_BUF_SIZE];
- lv_disp_draw_buf_init(&display_buffer, buf1, buf2, DISP_BUF_SIZE);
- static lv_disp_drv_t display_driver;
- lv_disp_drv_init(&display_driver);
- display_driver.user_data = spi;
- display_driver.hor_res = LCD_PANEL_W;
- display_driver.ver_res = LCD_PANEL_H;
- display_driver.draw_buf = &display_buffer;
- display_driver.flush_cb = lv_simulator_disp_flush_callback;
- lv_disp_drv_register(&display_driver);
- }
- static TaskHandle_t thread_handle;
- static StaticTask_t thread_buffer;
- static StackType_t thread_statck[ 3072 + TASK_EXTRA_STACK_SIZE ];
- static void thread_function(void* pvParameter);
- void app_main(void)
- {
- thread_handle = xTaskCreateStaticPinnedToCore(thread_function,
- "lvgl",
- LENOF(thread_statck),
- NULL,
- ESP_TASKD_EVENT_PRIO - 1,
- thread_statck,
- &thread_buffer,
- 1);
- }
- uint32_t IRAM_ATTR glory_systick(void)
- {
- return (uint32_t)((uint64_t)esp_timer_get_time() / 1000ul);
- }
- static void thread_function(void* pvParameter)
- {
- esp_err_t ret;
- spi_device_handle_t spi;
- spi_bus_config_t buscfg = {
- .miso_io_num = -1,
- .mosi_io_num = PIN_NUM_MOSI,
- .sclk_io_num = PIN_NUM_CLK,
- .quadwp_io_num = -1,
- .quadhd_io_num = -1,
- .max_transfer_sz = PARALLEL_LINES * LCD_PANEL_W * 2 + 8
- };
- spi_device_interface_config_t devcfg = {
- .clock_speed_hz = 40 * 1000 * 1000, //Clock out at 40 MHz
- .mode = 0, //SPI mode 0
- .spics_io_num = PIN_NUM_CS, //CS pin
- .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
- .queue_size = 7, //We want to be able to queue 7 transactions at a time
- .pre_cb = lcd_spi_pre_transfer_callback, //Specify pre-transfer callback to handle D/C line
- };
- //Initialize the SPI bus
- ret = spi_bus_initialize(LCD_HOST, &buscfg, DMA_CHAN);
- ESP_ERROR_CHECK(ret);
- //Attach the LCD to the SPI bus
- ret = spi_bus_add_device(LCD_HOST, &devcfg, &spi);
- ESP_ERROR_CHECK(ret);
- //Initialize the LCD
- lcd_init(spi);
- /*Initialize LittlevGL*/
- lv_init();
- /* Initialize drivers */
- lv_simulator_init(spi);
- /*Run the demo*/
- //lv_demo_widgets();
- lv_demo_stress();
- //lv_demo_music();
- //lv_demo_benchmark();
- while (true) {
- lv_task_handler();
- vTaskDelay(1);
- }
- }
复制代码
|
|