目录

GD3206-SPI-含ST7735S-TFT-LCD屏幕驱动

目录

【GD32】06 - SPI (含ST7735S TFT-LCD屏幕驱动)

这篇文章我们看看GD32中如何实现SPI,软件SPI的话可以参考我之前的文章,把对应操作GPIO口的代码从STM32改成GD32就可以使用了。

[【快速上手STM32】SPI通信协议&&1.8寸TFT-LCD(ST7735S)_tftlcdst7735和stm32-CSDN博客

文章浏览阅读3.7k次,点赞46次,收藏60次。SPI,英文全称Serial Peripheral Interface,即串行外围设备接口,是一种高速、全双工、同步的串行通信总线。我们之前说过I2C,那么我们就拿I2C和SPI做个对比。SPI和I2C对比,优势在于SPI的传输速率比I2C快得多,劣势在于SPI需要用的通信线比较多。_tftlcdst7735和stm32

https://i-blog.csdnimg.cn/blog_migrate/be19846480ab44ce477585fc567aeaa0.png “【快速上手STM32】SPI通信协议&&1.8寸TFT-LCD(ST7735S)_tftlcdst7735和stm32-CSDN博客”) 这边就来看看硬件SPI如何使用。

和之前不一样,我这篇文章使用的GD32是GD32F407VET6,其实大体上没差别,因为我们使用的是固件库。要注意的就是两种型号的单片机的引脚SPI资源不一样,不同的SPI对应的引脚是不一样的,这个要查手册去对应上,不过相同的SPI资源好像引脚是一样的,比如说GD32E230的SPI0和GD32F407的引脚是一样的。那么我们接下来就使用SPI0来做示范,这样不管是哪个型号的板子都可以兼容。

https://i-blog.csdnimg.cn/blog_migrate/1e818bc3989aa98cee226a55daa3b922.png

https://i-blog.csdnimg.cn/blog_migrate/8014740599aaccb0e431f78eb166099a.png

流程上都是先配置好GPIO为复用模式,接着是初始化SPI,然后就直接可以用了,GD32的硬件SPI还是非常方便的。

第一步先配置时钟。

https://i-blog.csdnimg.cn/blog_migrate/54314c6a525632b419a0ed874fd70ad1.png

要配置的有硬件SPI0,以及对应的引脚所在的GPIO端口,因为SPI0对应的引脚都在GPIOA,因此我们只需要使能GPIOA的时钟,如果是其他的SPI资源的话可能就要使能多个端口了。

https://i-blog.csdnimg.cn/blog_migrate/8a5bc01818e07dc1c943aa13c955294b.png

rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIOA
rcu_periph_clock_enable(RCU_SPI0);     // 使能SPI0

接下来我们要开启引脚复用,SPI一共是四个引脚,MISO,MOSI,SS,SCK,其中SS一般来说我们不让他硬件控制,通常我们会另外软件控制,因为硬件SPI的SS是固定死的,这样可能会和我们其他要用的引脚冲突,而且使用硬件SPI就是为了速度更快,而SS软件另外控制并不会影响多少速度,因此我们就算使用硬件SPI,也会让SS引脚使用软件控制。

所以开启引脚复用只需要开启另外三个即可。

https://i-blog.csdnimg.cn/blog_migrate/0311fa042ba53c10d00f4ca9373313fa.png

https://i-blog.csdnimg.cn/blog_migrate/038318a98c3e6d4c215b5604934f5eeb.png

#define Z_SPI_PORT  GPIOA
#define Z_SPI_SS    GPIO_PIN_4
#define Z_SPI_SCK   GPIO_PIN_5
#define Z_SPI_MISO  GPIO_PIN_6
#define Z_SPI_MOSI  GPIO_PIN_7

上面是宏定义,但是其实好像没什么必要,因为硬件SPI的引脚是固定死的,留着宏定义是因为代码是之前软件SPI的代码,懒得改了就留下来了。大家看下面示例代码的时候看见“Z_”开头的知道是SPI引脚的宏定义就可以了。

    //开启引脚复用
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_SCK);
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MISO);
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MOSI);

接下来就是配置GPIO口的模式了。

https://i-blog.csdnimg.cn/blog_migrate/9cd60c5894f7ffa3bd1bb969fbda7ded.png

SS引脚我们不用硬件SPI的,我们单独控制,直接配置为输出模式即可,因为默认我们不选中,所以加个上拉电阻。

其他三个引脚我们选择复用模式(GPIO_MODE_AF),因为是交给硬件SPI了,所以我们不加电阻。

    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Z_SPI_SS);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_SCK);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MISO);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MOSI);

接下来就是配置输出模式了。

https://i-blog.csdnimg.cn/blog_migrate/73608839244a7d98cbb509ab9474e67d.png

都配置为输出模式即可,速度选择50MHz就够用了,一般用于通信的引脚的输出频率为两倍传输速率就可以了。

    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SS);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SCK);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MISO);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MOSI);

配置完引脚,接下来就可以配置SPI了。

https://i-blog.csdnimg.cn/blog_migrate/261d26e5484a683f1f5229bf0594a71d.png

这是从GD32F407固件库手册里截取的,如果是GD32E230的话SPI就只有0和1,没有2345了,其他是一样的。

https://i-blog.csdnimg.cn/blog_migrate/aec43688f78e5a101afa63d251f4fbfd.png

device_mode :一般我们就选择主机模式 SPI_MASTER

trans_mode : 选择全双工模式 SPI_TRANSMODE_FULLDUPLEX ,说实话,除了仅接受之外的其他两个选项没看懂。

frame_size : 数据帧格式我们都是选择8bit的 SPI_FRAMESIZE_8BIT ,如果要发送16bit的时候发送两次8bit就行了。

nss : 前面说了,我们SS就软件控制就行了 SPI_NSS_SOFT ,因此这边选择软件控制。

endian : 大端小端就是高位在前在后的区别,我们SPI基本上都是高位在前,因此选择大端模式 SPI_ENDIAN_MSB

spi_init_struct.clock_polarity_phase : 相位和极性配置,说通俗一点就是选择SPI的模式。

一般来说有四种模式。

https://i-blog.csdnimg.cn/blog_migrate/3e074c78e528f887e1e12b2154ed4538.png

时序图可以参考下面的。

https://i-blog.csdnimg.cn/blog_migrate/bbe6c03994590946cc78a6da12da1f72.png

不懂要通信的模块支持哪种模式的话就默认选模式0就行 SPI_CK_PL_LOW_PH_1EDGE ,一般来说模式0是都支持的,实在不行就四种模式都试一遍(但是得保证其他环节不出错)。

prescale : 这是预分频器,这就要看看SPI的速率以及时钟频率了。

我们先来看看SPI的时钟频率。

https://i-blog.csdnimg.cn/blog_migrate/e1d4a5cde73e80e987f33939836cb815.png

SPI0挂载在APB2上,频率是84MHz。那么我们分频可以分个8,也就是差不多10MHz的速率。

因为我问的科大讯飞的大模型,它说ST7735S支持的速率是12MHz,当然了,仅供参考。因为我2分频之后也是可以正常使用ST7735S的。

https://i-blog.csdnimg.cn/blog_migrate/126c15e80967ca27c9e78c9029e2f96f.png

综上,我们安装下面这样配置就可以了。

    spi_parameter_struct spi_init_struct;
    spi_init_struct.trans_mode        		= SPI_TRANSMODE_FULLDUPLEX;  // 传输模式全双工
    spi_init_struct.device_mode       		= SPI_MASTER;                // 配置为主机
    spi_init_struct.frame_size         		= SPI_FRAMESIZE_8BIT;        // 8位数据
    spi_init_struct.clock_polarity_phase 	= SPI_CK_PL_LOW_PH_1EDGE;    // 模式0  
    spi_init_struct.nss               		= SPI_NSS_SOFT;              // 软件cs
    spi_init_struct.prescale           		= SPI_PSC_8;                 // 8分频
    spi_init_struct.endian            		= SPI_ENDIAN_MSB;            // 高位在前

    spi_init(SPI0, &spi_init_struct);

接下来就是使能。

https://i-blog.csdnimg.cn/blog_migrate/703bbf99719d6b8918b659d3402e17a9.png

spi_enable(SPI0);

配置完上面之后我们就可以直接发送数据了。

https://i-blog.csdnimg.cn/blog_migrate/12997dfa6306028ec0eaca3738fa7b4c.png

因为我们之前配置的是8bit,因此第二个参数传入8位的数据就可以了,这边形参类型是16bit是为了兼容两种传输格式。

spi_i2s_data_transmit(SPI0, data);

然后我们注意到了函数的名称是SPI_i2s开头的,因此i2s发送数据的函数也是用的这个。

接收数据的话我们用另外一个函数。

https://i-blog.csdnimg.cn/blog_migrate/eee19b3f652d3079c4f71561c9ec31d8.png

在发送和接收之前,我们需要检查缓冲区是否满足要求——发送的时候缓冲区是否为空,接收的时候缓冲区是否有数据。

https://i-blog.csdnimg.cn/blog_migrate/18b61a8becc29a91fc3719a66b93a10f.png

常用的标志我用红框框出来了,完整的标志可以到固件库手册里查看。

因此我们发送一次数据可以封装起来。也就是在发送数据之前先检测发送缓冲区为空,在接收之前检测接收缓冲区非空。而且SPI它通信是类似于交换的,所以我们发送和接收放在一起。

uint8_t Z_SPI_SwapByte(uint8_t data){
    //等待发送缓冲区为空
    while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE)); 
    spi_i2s_data_transmit(SPI0, data);
    //等待接收缓冲区不空
    while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));
    return spi_i2s_data_receive(SPI0);
}

有了上面这些函数,我们就可以使用硬件SPI了,完整的配置代码可以参考下面。

#define Z_SPI_PORT  GPIOA
#define Z_SPI_SS    GPIO_PIN_4
#define Z_SPI_SCK   GPIO_PIN_5
#define Z_SPI_MISO  GPIO_PIN_6
#define Z_SPI_MOSI  GPIO_PIN_7

void Z_SPI_SetSS(uint8_t val){        //封装一下选中SS
    gpio_bit_write(Z_SPI_PORT, Z_SPI_SS,val);
}

void Z_SPI_Init(void){
    rcu_periph_clock_enable(RCU_GPIOA);    // 使能GPIOA外设时钟
    rcu_periph_clock_enable(RCU_SPI0);     // 使能SPI0外设时钟
    
    //配置引脚复用
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_SCK);
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MISO);
    gpio_af_set(Z_SPI_PORT, GPIO_AF_5, Z_SPI_MOSI);
    //配置引脚模式
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, Z_SPI_SS);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_SCK);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MISO);
    gpio_mode_set(Z_SPI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, Z_SPI_MOSI);
    //配置输出模式
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SS);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_SCK);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MISO);
    gpio_output_options_set(Z_SPI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, Z_SPI_MOSI);
   
    Z_SPI_SetSS(1);        //默认不选中
    
    spi_parameter_struct spi_init_struct;
    spi_init_struct.trans_mode        		= SPI_TRANSMODE_FULLDUPLEX;  // 传输模式全双工
    spi_init_struct.device_mode       		= SPI_MASTER;                // 配置为主机
    spi_init_struct.frame_size         		= SPI_FRAMESIZE_8BIT;        // 8位数据
    spi_init_struct.clock_polarity_phase 	= SPI_CK_PL_LOW_PH_1EDGE;    // SPI模式0  
    spi_init_struct.nss               		= SPI_NSS_SOFT;              // 软件SS
    spi_init_struct.prescale           		= SPI_PSC_8;                 // 8分频
    spi_init_struct.endian            		= SPI_ENDIAN_MSB;            // 高位在前
 
    spi_init(SPI0, &spi_init_struct);
    
    //使能SPI
    spi_enable(SPI0);
    
}

uint8_t Z_SPI_SwapByte(uint8_t data){
    //等待发送缓冲区为空
    while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE)); 
    spi_i2s_data_transmit(SPI0, data);
    //等待接收缓冲区非空
    while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));
    return spi_i2s_data_receive(SPI0);
}

有了SPI,我们就可以直接封装ST7735S的驱动了,具体ST7735S的指令什么的我就不在这边啰嗦了,之前的文章有小小地介绍一下,文章链接在本文的开头。下面就直接把驱动代码贴出来了(需要包含上面的示例代码)。

/*
ST7725S驱动代码
*/
#define Z_ST7735S_RST_GPIO  GPIO_PIN_0
#define Z_ST7735S_DC_GPIO   GPIO_PIN_1
#define Z_ST7735S_PORT      GPIOA
#define Z_ST7735S_WIDTH     128
#define Z_ST7735S_HIGH      160


void Z_ST7735S_SetRST(uint8_t val){
    gpio_bit_write(Z_ST7735S_PORT,Z_ST7735S_RST_GPIO,val);
}

void Z_ST7735S_SetDC(uint8_t val){
    gpio_bit_write(Z_ST7735S_PORT,Z_ST7735S_DC_GPIO,val);
}

//发送指令,需要把DC拉低
void Z_ST7735S_SendCommand(uint8_t command){
    Z_SPI_SetSS(0);
    Z_ST7735S_SetDC(0);
    Z_SPI_SwapByte(command);
    Z_SPI_SetSS(1);
}

//发送数据,需要把DC拉高
void Z_ST7735S_SendData(uint8_t data){
    Z_SPI_SetSS(0);
    Z_ST7735S_SetDC(1);
    Z_SPI_SwapByte(data);
    Z_SPI_SetSS(1);
}

//发送16位的数据
void Z_ST7735S_Send16bitsRGB(uint16_t rgb)
{
    Z_ST7735S_SendData(rgb >> 8);
    Z_ST7735S_SendData(rgb);
}

//初始化ST7735S,其中一段初始化序列厂家会提供
void Z_ST7735S_Init(void){
    Z_SPI_Init();
    
    // 除了上面SPI初始化的GPIO口,还需要额外初始化RST和DC
    if(Z_ST7735S_PORT==GPIOA)  rcu_periph_clock_enable(RCU_GPIOA);
    else if(Z_ST7735S_PORT==GPIOB) rcu_periph_clock_enable(RCU_GPIOB);
    else if(Z_ST7735S_PORT==GPIOC) rcu_periph_clock_enable(RCU_GPIOC);
    
    gpio_mode_set(Z_ST7735S_PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,Z_ST7735S_RST_GPIO);
    gpio_output_options_set(Z_ST7735S_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,Z_ST7735S_RST_GPIO);
    
    gpio_mode_set(Z_ST7735S_PORT,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,Z_ST7735S_DC_GPIO);
    gpio_output_options_set(Z_ST7735S_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,Z_ST7735S_DC_GPIO);
    
    Z_ST7735S_SetRST(0);
    delay_ms(1);
    Z_ST7735S_SetRST(1);
    delay_ms(120);
    
    
    // 厂家提供的固定的初始化代码
    Z_ST7735S_SendCommand(0x11); // Sleep out
    delay_ms(120);               // Delay 120ms
    //------------------------------------ST7735S Frame Rate-----------------------------------------//
    Z_ST7735S_SendCommand(0xB1);
    Z_ST7735S_SendData(0x05);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendCommand(0xB2);
    Z_ST7735S_SendData(0x05);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendCommand(0xB3);
    Z_ST7735S_SendData(0x05);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendData(0x05);
    Z_ST7735S_SendData(0x3C);
    Z_ST7735S_SendData(0x3C);
    //------------------------------------End ST7735S Frame Rate---------------------------------//
    Z_ST7735S_SendCommand(0xB4); // Dot inversion
    Z_ST7735S_SendData(0x03);
    //------------------------------------ST7735S Power Sequence---------------------------------//
    Z_ST7735S_SendCommand(0xC0);
    Z_ST7735S_SendData(0x28);
    Z_ST7735S_SendData(0x08);
    Z_ST7735S_SendData(0x04);
    Z_ST7735S_SendCommand(0xC1);
    Z_ST7735S_SendData(0XC0);
    Z_ST7735S_SendCommand(0xC2);
    Z_ST7735S_SendData(0x0D);
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendCommand(0xC3);
    Z_ST7735S_SendData(0x8D);
    Z_ST7735S_SendData(0x2A);
    Z_ST7735S_SendCommand(0xC4);
    Z_ST7735S_SendData(0x8D);
    Z_ST7735S_SendData(0xEE);
    //---------------------------------End ST7735S Power Sequence-------------------------------------//
    Z_ST7735S_SendCommand(0xC5); // VCOM
    Z_ST7735S_SendData(0x1A);
    Z_ST7735S_SendCommand(0x36); // MX, MY, RGB mode
    Z_ST7735S_SendData(0xC0);
    //------------------------------------ST7735S Gamma Sequence---------------------------------//
    Z_ST7735S_SendCommand(0xE0);
    Z_ST7735S_SendData(0x04);
    Z_ST7735S_SendData(0x22);
    Z_ST7735S_SendData(0x07);
    Z_ST7735S_SendData(0x0A);
    Z_ST7735S_SendData(0x2E);
    Z_ST7735S_SendData(0x30);
    Z_ST7735S_SendData(0x25);
    Z_ST7735S_SendData(0x2A);
    Z_ST7735S_SendData(0x28);
    Z_ST7735S_SendData(0x26);
    Z_ST7735S_SendData(0x2E);
    Z_ST7735S_SendData(0x3A);
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(0x01);
    Z_ST7735S_SendData(0x03);
    Z_ST7735S_SendData(0x13);
    Z_ST7735S_SendCommand(0xE1);
    Z_ST7735S_SendData(0x04);
    Z_ST7735S_SendData(0x16);
    Z_ST7735S_SendData(0x06);
    Z_ST7735S_SendData(0x0D);
    Z_ST7735S_SendData(0x2D);
    Z_ST7735S_SendData(0x26);
    Z_ST7735S_SendData(0x23);
    Z_ST7735S_SendData(0x27);
    Z_ST7735S_SendData(0x27);
    Z_ST7735S_SendData(0x25);
    Z_ST7735S_SendData(0x2D);
    Z_ST7735S_SendData(0x3B);
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(0x01);
    Z_ST7735S_SendData(0x04);
    Z_ST7735S_SendData(0x13);
    //------------------------------------End ST7735S Gamma Sequence-----------------------------//
    Z_ST7735S_SendCommand(0x3A); // 65k mode
    Z_ST7735S_SendData(0x05);
    Z_ST7735S_SendCommand(0x29); // Display on
}

// 指定范围
void Z_ST7735S_SpecifyScope(uint8_t xs, uint8_t xe, uint8_t ys, uint8_t ye)
{
    Z_ST7735S_SendCommand(0x2A); // 指定列范围
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(xs);
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(xe);

    Z_ST7735S_SendCommand(0x2B); // 指定行范围
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(ys);
    Z_ST7735S_SendData(0x00);
    Z_ST7735S_SendData(ye);

    Z_ST7735S_SendCommand(0x2C); // 开始内存写入
}

//将整个屏幕都填充上相同的颜色
void Z_ST7735S_RefreshAll(uint16_t rgb)
{
    Z_ST7735S_SpecifyScope(0, Z_ST7735S_WIDTH, 0, Z_ST7735S_HIGH);
    for (uint16_t j = 0; j < Z_ST7735S_HIGH; ++j)
    {
        for (uint16_t i = 0; i < Z_ST7735S_WIDTH; ++i)
        {
            Z_ST7735S_Send16bitsRGB(rgb);
        }
    }
}

//将指定区域的屏幕填充上相同的颜色
void Z_ST7735S_RefreshArea(uint8_t start_x,uint8_t end_x,uint8_t start_y,uint8_t end_y,uint16_t rgb){
    if(start_x>Z_ST7735S_WIDTH||start_y>Z_ST7735S_HIGH||end_x>Z_ST7735S_WIDTH||end_y>Z_ST7735S_HIGH)    return ;
    Z_ST7735S_SpecifyScope(start_x,end_x,start_y,end_y);
    for (uint16_t j = start_y; j <= end_y; ++j){
        for (uint16_t i = start_x; i <= end_x; ++i){
            Z_ST7735S_Send16bitsRGB(rgb);
        }
    }
}

//将指定区域填充上颜色数组(可以不同)
void Z_ST7735S_DrawArea(uint8_t start_x,uint8_t end_x,uint8_t start_y,uint8_t end_y,uint16_t* rgb){
    if(start_x>Z_ST7735S_WIDTH||start_y>Z_ST7735S_HIGH||end_x>Z_ST7735S_WIDTH||end_y>Z_ST7735S_HIGH)    return ;
    Z_ST7735S_SpecifyScope(start_x,end_x,start_y,end_y);
    for (uint16_t j = start_y; j <= end_y; ++j){
        for (uint16_t i = start_x; i <= end_x; ++i){
            Z_ST7735S_Send16bitsRGB(*rgb);
            rgb++;
        }
    }
}


//const unsigned char number[10][10] = {
//    {0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}, /*"0",0*/
//    {0x00, 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00}, /*"1",1*/
//    {0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x10, 0x20, 0x7E, 0x00}, /*"2",2*/
//    {0x00, 0x00, 0x3C, 0x46, 0x04, 0x0C, 0x02, 0x42, 0x3C, 0x00}, /*"3",3*/
//    {0x00, 0x00, 0x0C, 0x14, 0x24, 0x44, 0x7C, 0x04, 0x0C, 0x00}, /*"4",4*/
//    {0x00, 0x00, 0x3E, 0x40, 0x58, 0x66, 0x02, 0x42, 0x3C, 0x00}, /*"5",5*/
//    {0x00, 0x00, 0x3C, 0x40, 0x58, 0x66, 0x42, 0x42, 0x3C, 0x00}, /*"6",6*/
//    {0x00, 0x00, 0x7E, 0x44, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00}, /*"7",7*/
//    {0x00, 0x00, 0x3C, 0x42, 0x62, 0x3C, 0x42, 0x42, 0x3C, 0x00}, /*"8",8*/
//    {0x00, 0x00, 0x3C, 0x42, 0x42, 0x66, 0x1A, 0x04, 0x78, 0x00}, /*"9",9*/
//};

//void Z_ST7735S_ShowChar(uint8_t x, uint8_t y, uint8_t ch, uint16_t rgb)
//{
//    if (ch >= 10)
//        return;
//    Z_ST7735S_SpecifyScope(x, x + 7, y, y + 9);
//    for (uint8_t i = 0; i < 10; ++i)
//    {
//        uint8_t temp = number[ch][i];
//        for (uint8_t j = 0; j < 8; ++j)
//        {
//            if ((temp & 0x80) != 0)
//                Z_ST7735S_Send16bitsRGB(rgb);
//            else
//                Z_ST7735S_Send16bitsRGB(0x0000);
//            temp <<= 1;
//        }
//    }
//}

接下来小小演示一下。

#include "board.h"
#include "Z_TFT.h"

int main(void){
    
    board_init();
    Z_ST7735S_Init();
    
    while (1){
        for(uint16_t i=0;i<0xFFFF;i+=50){
            Z_ST7735S_RefreshAll(i);
            delay_ms(20);
        }
    }
}

board.h是立创开发板提供的模板,board_init里面是进行一些初始化。

然后我把上面ST7735S的驱动代码封装成Z_TFT.h了,这个代码就是每隔20ms刷新一次屏幕,就是看看能不能正常驱动屏幕的。

https://i-blog.csdnimg.cn/blog_migrate/0c42e6db5d490ddb32550c959bb73dc0.jpeg

可以看的出来是可以正常驱动的。