#【ESP32学习】SPI驱动ILI9341屏幕

【ESP32学习】SPI驱动ILI9341屏幕

温馨提示:文章仅用于记录博主的项目代码,便于后续自己查阅,临时上传代码用于保存,因此不太易于博友们观看,敬请谅解。

项目采用ESP32的SPI2来驱动ILI9341屏幕,采用espidf-v4.02版本的spi_master_example_main例程上修改。引脚定义修改为

#define PIN_NUM_MISO 25
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK  18
#define PIN_NUM_CS   5

#define PIN_NUM_DC   17
#define PIN_NUM_RST  4
#define PIN_NUM_BCKL 2

原版例程是通过解码一张图片,通过函数来实现图片正弦波浮动,从而实现图片动态效果。但是我们驱动屏幕,最希望的是可以实现数字、汉字、图形的显示。
因此,在原函数基础上进行修改,得到以下函数

绘制点函数

static void draw_point(spi_device_handle_t spi,int x0,int y0,int color)        
{

    for (int y = 0; y < 1; y += 1)
    {
        send_point(spi, x0, x0 + 1, y0, y0 + 1, &color);
        send_line_finish(spi);
    }
}

绘制线函数

//dir    直线方向 0-左,1-右,2-上,3-下
//length 直线长度
static void draw_line(spi_device_handle_t spi,int x0,int y0,int length,char dir,int color) 
{
    if (dir == 0)												//(x0,y0)向左画长度为length的直线
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0+y,y0,color);
        }
    }
    if (dir == 1)												//(x0,y0)向右画长度为length的直线
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0-y,y0,color);
        }
    }
    if (dir == 2)												//(x0,y0)向上画长度为length的直线
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0,y0+y,color);
        }
    }
    if (dir == 3)												//(x0,y0)向下画长度为length的直线
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0,y0-y,color);
        }
    }
}

绘制数字

void draw_num(spi_device_handle_t spi, int num, int x, int y, char size, int color)
{
    int xpos = 0;
    int ypos = 0;
    if (size == 16)
    {
        for (int i = 0; i < 16; i++)
        {
            for (char j = 0; j < 8; j++)
            {
                char temp = ((number[num][i]>>j));
                if (temp& 0x01) draw_point(spi, x - xpos, y - ypos, color);        
                else            draw_point(spi, x - xpos, y - ypos, 0x0000);
                ypos++;
                if (ypos > 15)
                {
                    xpos += 1;
                    ypos = 0;
                }      
            }
        }
    }
}

绘制汉字库

void draw_chinese(spi_device_handle_t spi, int num, int x, int y, char size, int color)
{
    int xpos = 0;
    int ypos = 0;
    if (size == 16)
    {
        for (int i = 0; i < 32; i++)
        {
            for (char j = 0; j < 8; j++)
            {
                char temp = ((GBK[num][i]>>j));
                if (temp& 0x01) draw_point(spi, x - xpos, y - ypos, color);
                // else            draw_point(spi, x - xpos, y - ypos, 0xffff);
                ypos++;
                if (ypos > 15)
                {
                    xpos += 1;
                    ypos = 0;
                }      
            }
        }
    }
}

初始化颜色

static void display_pretty_colors(spi_device_handle_t spi)
{
    uint16_t *lines[1];
    lines[0] = heap_caps_malloc(320 * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA);

    for (int y = 0; y < 240; y += PARALLEL_LINES)
    {
        pretty_effect_calc_lines(lines[0], y, 0, PARALLEL_LINES);
        send_point(spi, 0 ,320 ,y,y+PARALLEL_LINES, lines[0]);
        send_line_finish(spi);
    }
}

在显示时,采用PCtoLCD2002软件进行取模,取模格式设置为

在这里插入图片描述

最后,在main函数内循环

    display_pretty_colors(spi);

    draw_line(spi, 100, 100, 40, 0, 0xff);
    draw_line(spi, 140, 100, 40, 2, 0xff);
    draw_line(spi, 140, 140, 40, 1, 0xff);
    draw_line(spi, 100, 140, 40, 3, 0xff);

    // vTaskDelay(1000 / 10);
    draw_chinese(spi, 0, 200, 200, 16, 0xffff);
    draw_chinese(spi, 1, 184, 200, 16, 0xffff);
    while (1)
    {
        draw_num(spi, ii, 184, 184, 16, 0xffff);
        ii++;
        if (ii > 9)
            ii = 0;
        // vTaskDelay(1000/10);
    }

全部代码如下,在espidf-v4.02版本的spi_master_example_main例程复制一下代码,对应SPI引脚映射,即可实现屏幕驱动

/* 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"

#include "pretty_effect.h"

/*
 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 PIN_NUM_MISO 25
#define PIN_NUM_MOSI 23
#define PIN_NUM_CLK  18
#define PIN_NUM_CS   5

#define PIN_NUM_DC   17
#define PIN_NUM_RST  4
#define PIN_NUM_BCKL 2

#define CONFIG_LCD_OVERCLOCK 1

//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 240 is dividable by this.
#define PARALLEL_LINES 1

uint16_t *lines[1];


/*
 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;

typedef enum {
    LCD_TYPE_ILI = 1,
    LCD_TYPE_ST,
    LCD_TYPE_MAX,
} type_lcd_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 st_init_cmds[]={
    /* Memory Data Access Control, MX=MV=1, MY=ML=MH=0, RGB=0 */
    {0x36, {(1<<5)|(1<<6)}, 1},
    /* Interface Pixel Format, 16bits/pixel for RGB/MCU interface */
    {0x3A, {0x55}, 1},
    /* Porch Setting */
    {0xB2, {0x0c, 0x0c, 0x00, 0x33, 0x33}, 5},
    /* Gate Control, Vgh=13.65V, Vgl=-10.43V */
    {0xB7, {0x45}, 1},
    /* VCOM Setting, VCOM=1.175V */
    {0xBB, {0x2B}, 1},
    /* LCM Control, XOR: BGR, MX, MH */
    {0xC0, {0x2C}, 1},
    /* VDV and VRH Command Enable, enable=1 */
    {0xC2, {0x01, 0xff}, 2},
    /* VRH Set, Vap=4.4+... */
    {0xC3, {0x11}, 1},
    /* VDV Set, VDV=0 */
    {0xC4, {0x20}, 1},
    /* Frame Rate Control, 60Hz, inversion=0 */
    {0xC6, {0x0f}, 1},
    /* Power Control 1, AVDD=6.8V, AVCL=-4.8V, VDDS=2.3V */
    {0xD0, {0xA4, 0xA1}, 1},
    /* Positive Voltage Gamma Control */
    {0xE0, {0xD0, 0x00, 0x05, 0x0E, 0x15, 0x0D, 0x37, 0x43, 0x47, 0x09, 0x15, 0x12, 0x16, 0x19}, 14},
    /* Negative Voltage Gamma Control */
    {0xE1, {0xD0, 0x00, 0x05, 0x0D, 0x0C, 0x06, 0x2D, 0x44, 0x40, 0x0E, 0x1C, 0x18, 0x16, 0x19}, 14},
    /* Sleep Out */
    {0x11, {0}, 0x80},
    /* Display On */
    {0x29, {0}, 0x80},
    {0, {0}, 0xff}
};

DRAM_ATTR static const lcd_init_cmd_t ili_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, {0x28}, 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.
 */
void 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.
 */
void 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.
void lcd_spi_pre_transfer_callback(spi_transaction_t *t)
{
    int dc=(int)t->user;
    gpio_set_level(PIN_NUM_DC, dc);
}

uint32_t lcd_get_id(spi_device_handle_t spi)
{
    //get_id cmd
    lcd_cmd(spi, 0x04);

    spi_transaction_t t;
    memset(&t, 0, sizeof(t));
    t.length=8*3;
    t.flags = SPI_TRANS_USE_RXDATA;
    t.user = (void*)1;

    esp_err_t ret = spi_device_polling_transmit(spi, &t);
    assert( ret == ESP_OK );

    return *(uint32_t*)t.rx_data;
}

//Initialize the display
void lcd_init(spi_device_handle_t spi)
{
    int cmd=0;
    const lcd_init_cmd_t* lcd_init_cmds;

    //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);

    //detect LCD type
    uint32_t lcd_id = lcd_get_id(spi);
    int lcd_detected_type = 0;
    int lcd_type;

    printf("LCD ID: %08X\n", lcd_id);
    if ( lcd_id == 0 ) {
        //zero, ili
        lcd_detected_type = LCD_TYPE_ILI;
        printf("ILI9341 detected.\n");
    } else {
        // none-zero, ST
        lcd_detected_type = LCD_TYPE_ST;
        printf("ST7789V detected.\n");
    }

#ifdef CONFIG_LCD_TYPE_AUTO
    lcd_type = lcd_detected_type;
#elif defined( CONFIG_LCD_TYPE_ST7789V )
    printf("kconfig: force CONFIG_LCD_TYPE_ST7789V.\n");
    lcd_type = LCD_TYPE_ST;
#elif defined( CONFIG_LCD_TYPE_ILI9341 )
    printf("kconfig: force CONFIG_LCD_TYPE_ILI9341.\n");
    lcd_type = LCD_TYPE_ILI;
#endif
    if ( lcd_type == LCD_TYPE_ST ) {
        printf("LCD ST7789V initialization.\n");
        lcd_init_cmds = st_init_cmds;
    } else {
        printf("LCD ILI9341 initialization.\n");
        lcd_init_cmds = ili_init_cmds;
    }

    //Send all the commands
    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, 0);
}





/* To send a set of lines we have to send a command, 2 data bytes, another command, 2 more data bytes and another command
 * before sending the line data itself; a total of 6 transactions. (We can't put all of this in just one transaction
 * because the D/C line needs to be toggled in the middle.)
 * This routine queues these commands up as interrupt transactions so they get
 * sent faster (compared to calling spi_device_transmit several times), and at
 * the mean while the lines for next transactions can get calculated.
 */


// static void send_point(spi_device_handle_t spi, int x0,int xpos,int y0,int ypos, uint16_t *linedata)
static void send_point(spi_device_handle_t spi, int x0,int xpos,int y0,int ypos, uint16_t *linedata)
{
    esp_err_t ret;
    int x;
    //Transaction descriptors. Declared static so they're not allocated on the stack; we need this memory even when this
    //function is finished because the SPI driver needs access to it even while we're already calculating the next line.
    static spi_transaction_t trans[6];

    //In theory, it's better to initialize trans and data only once and hang on to the initialized
    //variables. We allocate them on the stack, so we need to re-init them each call.
    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]=x0>>8;              //Start Col High
    trans[1].tx_data[1]=x0&0xff;              //Start Col Low
    trans[1].tx_data[2]=xpos>>8;       //End Col High
    trans[1].tx_data[3]=xpos&0xff;     //End Col Low
    trans[2].tx_data[0]=0x2B;           //Page address set
    trans[3].tx_data[0]=y0>>8;        //Start page high
    trans[3].tx_data[1]=y0&0xff;      //start page low
    trans[3].tx_data[2]=(ypos)>>8;    //end page high
    trans[3].tx_data[3]=(ypos)&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=(xpos-x0)*2*8*(ypos-y0);          //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);
    }

    //When we are here, the SPI driver is busy (in the background) getting the transactions sent. That happens
    //mostly using DMA, so the CPU doesn't have much to do here. We're not going to wait for the transaction to
    //finish because we may as well spend the time calculating the next line. When that is done, we can call
    //send_line_finish, which will wait for the transfers to be done and check their status.
}

static void 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 draw_point(spi_device_handle_t spi,int x0,int y0,int color)        
{

    for (int y = 0; y < 1; y += 1)
    {
        send_point(spi, x0, x0 + 1, y0, y0 + 1, &color);
        send_line_finish(spi);
    }
}


//dir    直线方向 0-左,1-右,2-上,3-//length 直线长度
static void draw_line(spi_device_handle_t spi,int x0,int y0,int length,char dir,int color) 
{
    if (dir == 0)
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0+y,y0,color);
        }
    }
    if (dir == 1)
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0-y,y0,color);
        }
    }
    if (dir == 2)
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0,y0+y,color);
        }
    }
    if (dir == 3)
    {
        for(int y = 0; y < length; y += 1)
        {
            draw_point(spi,x0,y0-y,color);
        }
    }


}

char GBK[][32] = {
    {0x10, 0x04, 0x10, 0x03, 0xD0, 0x00, 0xFF, 0xFF, 0x90, 0x00, 0x10, 0x03, 0x40, 0x40, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x7F, 0x7F, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x40, 0x00, 0x00}, /*"桂",0*/
    {0x40, 0x80, 0x48, 0x60, 0x48, 0x1F, 0x48, 0x20, 0xFF, 0x7F, 0x48, 0x44, 0x48, 0x44, 0x42, 0x40, 0xA2, 0x4F, 0x9E, 0x48, 0x82, 0x48, 0xA2, 0x48, 0xC2, 0x48, 0xBE, 0x4F, 0x00, 0x40, 0x00, 0x00}, /*"超",1*/

};

char number[][16] = {
    {0x00, 0x00, 0xE0, 0x0F, 0x10, 0x10, 0x08, 0x20, 0x08, 0x20, 0x10, 0x10, 0xE0, 0x0F, 0x00, 0x00}, /*"0",0*/
    {0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x10, 0x20, 0xF8, 0x3F, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00}, /*"1",1*/
    {0x00, 0x00, 0x70, 0x30, 0x08, 0x28, 0x08, 0x24, 0x08, 0x22, 0x08, 0x21, 0xF0, 0x30, 0x00, 0x00}, /*"2",2*/
    {0x00, 0x00, 0x30, 0x18, 0x08, 0x20, 0x08, 0x21, 0x08, 0x21, 0x88, 0x22, 0x70, 0x1C, 0x00, 0x00}, /*"3",3*/
    {0x00, 0x00, 0x00, 0x06, 0x80, 0x05, 0x40, 0x24, 0x30, 0x24, 0xF8, 0x3F, 0x00, 0x24, 0x00, 0x24}, /*"4",4*/
    {0x00, 0x00, 0xF8, 0x19, 0x88, 0x20, 0x88, 0x20, 0x88, 0x20, 0x08, 0x11, 0x08, 0x0E, 0x00, 0x00}, /*"5",5*/
    {0x00, 0x00, 0xE0, 0x0F, 0x10, 0x11, 0x88, 0x20, 0x88, 0x20, 0x90, 0x20, 0x00, 0x1F, 0x00, 0x00}, /*"6",6*/
    {0x00, 0x00, 0x18, 0x00, 0x08, 0x00, 0x08, 0x3E, 0x88, 0x01, 0x68, 0x00, 0x18, 0x00, 0x00, 0x00}, /*"7",7*/
    {0x00, 0x00, 0x70, 0x1C, 0x88, 0x22, 0x08, 0x21, 0x08, 0x21, 0x88, 0x22, 0x70, 0x1C, 0x00, 0x00}, /*"8",8*/
    {0x00, 0x00, 0xF0, 0x01, 0x08, 0x12, 0x08, 0x22, 0x08, 0x22, 0x10, 0x11, 0xE0, 0x0F, 0x00, 0x00}, /*"9",9*/

};

void draw_num(spi_device_handle_t spi, int num, int x, int y, char size, int color)
{
    int xpos = 0;
    int ypos = 0;
    if (size == 16)
    {
        for (int i = 0; i < 16; i++)
        {
            for (char j = 0; j < 8; j++)
            {
                char temp = ((number[num][i]>>j));
                if (temp& 0x01) draw_point(spi, x - xpos, y - ypos, color);
                 else            draw_point(spi, x - xpos, y - ypos, 0x0000);
                ypos++;
                if (ypos > 15)
                {
                    xpos += 1;
                    ypos = 0;
                }      
            }
        }
    }
}


void draw_chinese(spi_device_handle_t spi, int num, int x, int y, char size, int color)
{
    int xpos = 0;
    int ypos = 0;
    if (size == 16)
    {
        for (int i = 0; i < 32; i++)
        {
            for (char j = 0; j < 8; j++)
            {
                char temp = ((GBK[num][i]>>j));
                if (temp& 0x01) draw_point(spi, x - xpos, y - ypos, color);
                // else            draw_point(spi, x - xpos, y - ypos, 0xffff);
                ypos++;
                if (ypos > 15)
                {
                    xpos += 1;
                    ypos = 0;
                }      
            }
        }
    }
}

static void display_pretty_colors(spi_device_handle_t spi)
{
    uint16_t *lines[1];
    lines[0] = heap_caps_malloc(320 * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA);

    for (int y = 0; y < 240; y += PARALLEL_LINES)
    {
        pretty_effect_calc_lines(lines[0], y, 0, PARALLEL_LINES);
        send_point(spi, 0 ,320 ,y,y+PARALLEL_LINES, lines[0]);
        send_line_finish(spi);
    }
}


void app_main()
{
    esp_err_t ret;
    spi_device_handle_t spi;
    spi_bus_config_t buscfg={
        .miso_io_num=PIN_NUM_MISO,
        .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*320*2+8
    };
    spi_device_interface_config_t devcfg = {
#ifdef CONFIG_LCD_OVERCLOCK
        .clock_speed_hz = 27 * 1000 * 1000, //Clock out at 26 MHz
#else
        .clock_speed_hz = 10 * 1000 * 1000, //Clock out at 10 MHz
#endif
        .mode = 0,                               //SPI mode 0
        .spics_io_num = PIN_NUM_CS,              //CS pin
        .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
    };

    //lines[0]=heap_caps_malloc(1*1*sizeof(uint16_t), MALLOC_CAP_DMA);
    //Initialize the SPI bus
    ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
    ESP_ERROR_CHECK(ret);
    //Attach the LCD to the SPI bus
    ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);
    //Initialize the LCD
    lcd_init(spi);
    //Initialize the effect displayed
    ret=pretty_effect_init();
    ESP_ERROR_CHECK(ret);
    char ii = 0;

    display_pretty_colors(spi);

    draw_line(spi, 100, 100, 40, 0, 0xff);
    draw_line(spi, 140, 100, 40, 2, 0xff);
    draw_line(spi, 140, 140, 40, 1, 0xff);
    draw_line(spi, 100, 140, 40, 3, 0xff);

    // vTaskDelay(1000 / 10);
    draw_chinese(spi, 0, 200, 200, 16, 0xffff);
    draw_chinese(spi, 1, 184, 200, 16, 0xffff);
    while (1)
    {
        draw_num(spi, ii, 184, 184, 16, 0xffff);
        ii++;
        if (ii > 9)
            ii = 0;
        // vTaskDelay(1000/10);
    }
}

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值