ESP32显示驱动

 ESP32有4组的SPI,SPI0和SPI又叫SPI,SPI2又叫HSPI,SPI3又叫VSPI,这里的HSPI和VSPI只是名字不同,并不是high-speed SPI 和Very High-speed SPI。SPI0作为cache访问外部存储接口使用,SPI1一般用作连接外部Flash,应用一般只使用SPI2和SPI3。

如果SPI采用GPIO矩阵,则最大频率会限制在26.6MHz,如果采用IOMUX,最高频率会限制在80MHz。因为显示屏是个高速刷数据的硬件,所以我使用IOMUX,如何使用,只要根据稳定要求配置指定的IO口就行,我这里使用SPI3,即VSPI。

PinHSPIVSPI
CS0*155
SCLK1418
MISO1219
MOSI1323
QUADWP222
QUADHD421

这里我们只需要输出SPI,所以MOSI引脚不配,另外QUADWP和QUADHD也不需要,所以SPI相关的,只需要配置CS0、SCLK和MISO。

我的LCD驱动IC是ILI9341,看模块的引脚,还需要一个IO接DC,用来切换命令/数据,还有一个IO用来控制背光。这两个IO口没有特殊要求,最后看下LCD驱动的IO口定义

#define DISP_SPI_MOSI 23
#define DISP_SPI_CLK 18
#define DISP_SPI_CS 5
#define DISP_SPI_DC 12
#define DISP_BCKL 27

1、初始化

申请双缓冲区内存,用来发送到SPI控制器

   #define LINE_BUFFERS (2)
   #define LINE_COUNT (8)

    const size_t lineSize = LCD_WIDTH * LINE_COUNT * sizeof(uint16_t);
    for (int x = 0; x < LINE_BUFFERS; x++)
    {
        line[x] = heap_caps_malloc(lineSize, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
        if (!line[x])
            abort();
    }

这里的缓冲区有2个,一个用来发送到SPI,另一个用来绘制,而且每次只发送8行数据。

    #define SPI_CLOCK_SPEED 80000000


    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[DISP_SPI_DC], PIN_FUNC_GPIO);
    gpio_set_direction(DISP_SPI_DC, GPIO_MODE_OUTPUT);
    esp_err_t ret;

    spi_bus_config_t buscfg = {
        .miso_io_num = -1,
        .mosi_io_num = DISP_SPI_MOSI,
        .sclk_io_num = DISP_SPI_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 8 * 320 * 2 + 8};

    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = SPI_CLOCK_SPEED,
        .mode = 0,                   //SPI mode 0
        .spics_io_num = DISP_SPI_CS, //CS pin
        .queue_size = 7,
        .pre_cb = disp_spi_pre_transfer_callback,
        .post_cb = NULL,
        //.flags=SPI_DEVICE_NO_DUMMY
    };

    //Initialize the SPI bus
    ret = spi_bus_initialize(VSPI_HOST, &buscfg, 1);
    assert(ret == ESP_OK);

    //Attach the LCD to the SPI bus
    ret = spi_bus_add_device(VSPI_HOST, &devcfg, &spi);
    assert(ret == ESP_OK);

SPI总线初始化,然后添加LCD设备,这里基本就是配置相关的引脚,然后速率配置为80Mhz。

ili9341_init();

最后还需要初始化驱动IC,不同的驱动IC代码不一样,一般厂商会提供代码,这里不展开研究。

2、发送数据

void send_lines(int ypos, int width, uint16_t *linedata, int lineCount)
{
    esp_err_t ret;
    int x;
    static spi_transaction_t trans[6];

    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;
    }
    trans[0].tx_data[0] = 0x2A;                      //Column Address Set
    trans[1].tx_data[0] = 0;                         //Start Col High
    trans[1].tx_data[1] = 0;                         //Start Col Low
    trans[1].tx_data[2] = (width - 1) >> 8;          //End Col High
    trans[1].tx_data[3] = (width - 1) & 0xff;        //End Col Low
    trans[2].tx_data[0] = 0x2B;                      //Page address set
    trans[3].tx_data[0] = ypos >> 8;                 //Start page high
    trans[3].tx_data[1] = ypos & 0xff;               //start page low
    trans[3].tx_data[2] = (ypos + lineCount) >> 8;   //end page high
    trans[3].tx_data[3] = (ypos + lineCount) & 0xff; //end page low
    trans[4].tx_data[0] = 0x2C;                      //memory write
    trans[5].tx_buffer = linedata;                   //finally send the line data
    trans[5].length = width * 2 * 8 * lineCount;     //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(spi, &trans[x], portMAX_DELAY);
        assert(ret == ESP_OK);
    }
}

每发送一次数据,需要分6个事务来做,这里还是根据I9341驱动IC来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值