ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

联盛德 HLK-W806 (四): 软件SPI和硬件SPI驱动ST7735液晶LCD

2021-11-28 09:31:07  阅读:212  来源: 互联网

标签:st7735 HAL W806 void SPI uint16 ST7735


目录

ST7735介绍

ST7735是用于驱动最大162x132像素的TFT驱动芯片, 396(128*3色)x162线输出, 可以直接以SPI协议, 或者8位/9位/16位并行连接外部控制器.
显示数据可以存储在片内的132 x 162 x 18 bits内存中, 显示内存的读写不需要外部时钟驱动.

使用ST7735的128x160 TFT LCD模块

连接

ST7735的LCD模块有128x128, 128x160等不同分辨率, 对外的接线除了VCC和GND外有6根

  • SCL SPI时钟, 对应上位机SPI的SCK
  • SDA SPI数据输入, 对应上位机SPI的MOSI
  • RES 重启, 低电平有效, 工作时处于高电平
  • DC 命令模式和数据模式切换位, 低电平为命令模式, 高电平为数据模式
  • CS 片选信号, 对应上位机SPI的CS
  • BL 背光, 高电平亮, 低电平灭

如果使用软件SPI, IO口可以随便选择, 如果是硬件SPI, 其中的CS, SCK, MOSI 和 MISO(ST7735未使用)只能使用特定的IO口, 根据W806的手册有以下可选项

  • CS: B4, B14
  • SCK: B1, B2, B15, B24
  • MOSI: B5, B17, B26, PA7
  • MISO: B0, B3, B16, B25

对应本测试的连接方式为

  • B10 -> RES, RESET
  • B11 -> DC, CD
  • B14 -> CS, Chip Select
  • B15 -> SCK, SCL, CLK, Clock
  • B16 -> BL, Back Light
  • B17 -> MOSI, SDA
  • GND -> GND
  • 3.3V -> VCC

ST7735的控制

基础通信方法

  • 软件SPI方式
static void ST7735_TransmitByte(uint8_t dat)
{
    uint8_t i;
    ST7735_CS_LOW;
    for (i = 0; i < 8; i++)
    {
        ST7735_SCK_LOW;
        if (dat & 0x80)
        {
            ST7735_MOSI_HIGH;
        }
        else
        {
            ST7735_MOSI_LOW;
        }
        ST7735_SCK_HIGH;
        dat <<= 1;
    }
    ST7735_CS_HIGH;
}
  • 硬件SPI方式
static void ST7735_TransmitByte(uint8_t dat)
{
    ST7735_CS_LOW;
    HAL_SPI_Transmit(&hspi, &dat, 1, 100);
    ST7735_CS_HIGH;
}

使用BUFFER提升刷新速度

在硬件SPI下, 因为接口实现是以批量数据为基础的, 批量写入数据比按单字节或双字节写入效率要高得多, 在代码中可以申请一小段内存增加buffer, 在绘制中通过buffer去调用SPI, 可以充分利用硬件SPI的传输速度.

声明buffer区

static uint8_t st7735_buf[ST7735_BUF_SIZE];
static uint16_t st7735_buf_pt = 0;

写入buffer和清空buffer

static void ST7735_WriteBuff(uint8_t* buff, size_t buff_size)
{
    while (buff_size--)
    {
        st7735_buf[st7735_buf_pt++] = *buff++;
        if (st7735_buf_pt == ST7735_BUF_SIZE)
        {
            ST7735_Transmit(st7735_buf, st7735_buf_pt, HAL_MAX_DELAY);
            st7735_buf_pt = 0;
        }
    }
}

static void ST7735_FlushBuff(void)
{
    if (st7735_buf_pt > 0)
    {
        ST7735_Transmit(st7735_buf, st7735_buf_pt, HAL_MAX_DELAY);
        st7735_buf_pt = 0;
    }
}

在区域填充中使用buffer

void ST7735_Fill(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t color)
{
    uint16_t i,j;
    ST7735_SetAddrWindow(x_start, y_start, x_end - 1, y_end - 1);
    for(i = y_start; i < y_end; i++)
    {
        for( j = x_start; j < x_end; j++)
        {
            ST7735_WriteBuff((uint8_t *)&color, 2);
        }
    }
    ST7735_FlushBuff();
}

测试代码

控制背光

ST7735_BackLight_On();
ST7735_BackLight_Off();

填充色块

ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_RED);

输出字符

ST7735_DrawString(5, y, (const char *)"0123456789ABCDE", Font_6x12, ST7735_YELLOW, ST7735_RED);

输出图片

ST7735_DrawImage(0, 0, 128, 160, (uint16_t *)testimage1);

在主程序中引用st7735.h并初始化就可以调用了

main.c

#include <stdio.h>
#include "wm_hal.h"
#include "st7735.h"
#include "testimg2.h"

void Error_Handler(void);

SPI_HandleTypeDef hspi;

static void SPI_Init(void)
{
    hspi.Instance = SPI;
    hspi.Init.Mode = SPI_MODE_MASTER;
    hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi.Init.NSS = SPI_NSS_SOFT;
    hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    hspi.Init.FirstByte = SPI_LITTLEENDIAN;

    if (HAL_SPI_Init(&hspi) != HAL_OK)
    {
        Error_Handler();
    }
}

int main(void)
{
    uint8_t y = 10;
    SystemClock_Config(CPU_CLK_240M);
    ST7735_GPIO_Init();
    SPI_Init();
    ST7735_Init();
    while(1)
    {
        ST7735_BackLight_On();
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_RED);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_YELLOW);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_GREEN);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_CYAN);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_MAGENTA);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_ORANGE);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_BROWN);
        HAL_Delay(500);
        ST7735_Fill(0, 0, ST7735_WIDTH, ST7735_HEIGHT, ST7735_BLUE);
        HAL_Delay(500);
        y = 10;
        ST7735_DrawString(5, y, (const char *)"0123456789ABCDE", Font_6x12, ST7735_YELLOW, ST7735_RED);
        HAL_Delay(1000);

        ST7735_DrawImage(0, 0, 128, 160, (uint16_t *)testimage1);
        HAL_Delay(1000);
        ST7735_DrawImage(0, 0, 128, 160, (uint16_t *)testimage2);
        HAL_Delay(1000);
        ST7735_BackLight_Off();
        HAL_Delay(1000);
    }
}

另外需要在wm_hal_msp.c中增加SPI的初始化方法

wm_hal_msp.c

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
    __HAL_RCC_SPI_CLK_ENABLE();
    __HAL_AFIO_REMAP_SPI_CS(ST7735_CS_PORT, ST7735_CS_PIN);
    __HAL_AFIO_REMAP_SPI_CLK(ST7735_SCK_PORT, ST7735_SCK_PIN);
    __HAL_AFIO_REMAP_SPI_MOSI(ST7735_MOSI_PORT, ST7735_MOSI_PIN);
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{
    __HAL_RCC_SPI_CLK_DISABLE();
    HAL_GPIO_DeInit(ST7735_CS_PORT, ST7735_CS_PIN);
    HAL_GPIO_DeInit(ST7735_SCK_PORT, ST7735_SCK_PIN);
    HAL_GPIO_DeInit(ST7735_MOSI_PORT, ST7735_MOSI_PIN);
}

测试数据

在128x160的LCD中, 通过以下代码在主进程中测试两幅128x160图片无间断循环刷新

for (uint16_t i = 0; i < 1000; i++)
{
    ST7735_DrawImage(0, 0, 128, 160, (uint16_t *)testimage1);
    ST7735_DrawImage(0, 0, 128, 160, (uint16_t *)testimage2);
}
printf("done");

记录得到的结果为

[2021-11-28 08:06:33.267]
RX:done
[2021-11-28 08:07:12.256]
RX:done
[2021-11-28 08:07:51.232]
RX:done
[2021-11-28 08:08:30.204]
RX:done
[2021-11-28 08:09:09.181]
RX:done
[2021-11-28 08:09:48.166]
RX:done
[2021-11-28 08:10:27.145]
RX:done
[2021-11-28 08:11:06.113]
RX:done
[2021-11-28 08:11:45.145]
RX:done
[2021-11-28 08:12:24.073]
RX:done

可以看到间隔基本上在39秒左右, 根据这个结果计算得全屏刷新率为 2000/39 = 51.2 FPS

相关代码

以上的代码位于Github: https://github.com/IOsetting/wm-sdk-w806/tree/dev/demo/spi/st7735_lcd

标签:st7735,HAL,W806,void,SPI,uint16,ST7735
来源: https://www.cnblogs.com/milton/p/15614304.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有