本帖最后由 yinwuqing110 于 2025-1-5 20:10 编辑
一、引言
前段时间在某电子商城上购得一块1.77寸RGB屏,显示驱动芯片是ST7735S,这款显示器驱动芯片比较流行,是由矽创电子股份有限公司生产,非常适合小尺寸屏的集成设计,流行的驱动接口有IIC与SPI两种,笔者这款是采用SPI驱动接口,坛友有采用SPI硬件+DMA方式驱动该类似的TFT屏,本期咱采用GPIO模拟SPI方式来驱动,这种方式移植起来比较方便,不受硬件IO口的局限制。
ST7735S.zip
(3.01 MB)
二、引脚关系图
使用开发板上的IO口与TFT-LCD屏的管脚对应关系
三、实物连接
四、部分驱动代码
lcd_init.h
#ifndef __LCD_INIT_H
#define __LCD_INIT_H
#include "lcd.h"
#include "g32a1xxx_pins.h"
#define USE_HORIZONTAL 1 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160
#else
#define LCD_W 160
#define LCD_H 128
#endif
#define BOARD_LCD_MOSI_GPIO GPIOD
#define BOARD_LCD_PORT_MOSI_BASE PMD
#define BOARD_LCD_GPIO_MOSI_PIN (5U)
#define BOARD_LCD_SCLK_GPIO GPIOD
#define BOARD_LCD_PORT_SCLK_BASE PMD
#define BOARD_LCD_GPIO_SCLK_PIN (1U)
#define BOARD_LCD_CS_GPIO GPIOD
#define BOARD_LCD_PORT_CS_BASE PMD
#define BOARD_LCD_GPIO_CS_PIN (2U)
#define BOARD_LCD_DC_GPIO GPIOD
#define BOARD_LCD_PORT_DC_BASE PMD
#define BOARD_LCD_GPIO_DC_PIN (3U)
#define BOARD_LCD_RES_GPIO GPIOD
#define BOARD_LCD_PORT_RES_BASE PMD
#define BOARD_LCD_GPIO_RES_PIN (8U)
#define BOARD_LCD_BLK_GPIO GPIOD
#define BOARD_LCD_PORT_BLK_BASE PMD
#define BOARD_LCD_GPIO_BLK_PIN (9U)
//-----------------LCD端口定义----------------
#define LCD_SCLK_Clr() PINS_WritePin(BOARD_LCD_SCLK_GPIO,BOARD_LCD_GPIO_SCLK_PIN,0)//SCL SCLK
#define LCD_SCLK_Set() PINS_WritePin(BOARD_LCD_SCLK_GPIO,BOARD_LCD_GPIO_SCLK_PIN,1)
#define LCD_CS_Clr() PINS_WritePin(BOARD_LCD_CS_GPIO,BOARD_LCD_GPIO_CS_PIN,0)//CS
#define LCD_CS_Set() PINS_WritePin(BOARD_LCD_CS_GPIO,BOARD_LCD_GPIO_CS_PIN,1)
#define LCD_MOSI_Clr() PINS_WritePin(BOARD_LCD_MOSI_GPIO,BOARD_LCD_GPIO_MOSI_PIN,0)//SDA MOSI
#define LCD_MOSI_Set() PINS_WritePin(BOARD_LCD_MOSI_GPIO,BOARD_LCD_GPIO_MOSI_PIN,1)
#define LCD_DC_Clr() PINS_WritePin(BOARD_LCD_DC_GPIO,BOARD_LCD_GPIO_DC_PIN,0)//DC
#define LCD_DC_Set() PINS_WritePin(BOARD_LCD_DC_GPIO,BOARD_LCD_GPIO_DC_PIN,1)
#define LCD_RES_Clr() PINS_WritePin(BOARD_LCD_RES_GPIO,BOARD_LCD_GPIO_RES_PIN,0)//RES
#define LCD_RES_Set() PINS_WritePin(BOARD_LCD_RES_GPIO,BOARD_LCD_GPIO_RES_PIN,1)
#define LCD_BLK_Clr() PINS_WritePin(BOARD_LCD_BLK_GPIO,BOARD_LCD_GPIO_BLK_PIN,0)//BLK
#define LCD_BLK_Set() PINS_WritePin(BOARD_LCD_BLK_GPIO,BOARD_LCD_GPIO_BLK_PIN,1)
void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(uint8_t dat);//模拟SPI时序
void LCD_WR_DATA8(uint8_t dat);//写入一个字节
void LCD_WR_DATA(uint16_t dat);//写入两个字节
void LCD_WR_REG(uint8_t dat);//写入一个指令
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2);//设置坐标函数
void LCD_Init(void);//LCD初始化
#endif
lcd_init.c
#include "lcd_init.h"
#include "board.h"
#include "g32a1xxx_clock.h"
#include "osif.h"
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void LCD_Writ_Bus(u8 dat)
{
u8 i;
LCD_CS_Clr();
for(i=0;i<8;i++)
{
LCD_SCLK_Clr();
if(dat&0x80)
{
LCD_MOSI_Set();
}
else
{
LCD_MOSI_Clr();
}
LCD_SCLK_Set();
dat<<=1;
}
LCD_CS_Set();
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA8(u8 dat)
{
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
LCD_Writ_Bus(dat>>8);
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值: 无
******************************************************************************/
void LCD_WR_REG(u8 dat)
{
LCD_DC_Clr();//写命令
LCD_Writ_Bus(dat);
LCD_DC_Set();//写数据
}
/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
y1,y2 设置行的起始和结束地址
返回值: 无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
if(USE_HORIZONTAL==0)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+2);
LCD_WR_DATA(x2+2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+1);
LCD_WR_DATA(y2+1);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==1)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+2);
LCD_WR_DATA(x2+2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+1);
LCD_WR_DATA(y2+1);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==2)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+1);
LCD_WR_DATA(x2+1);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+2);
LCD_WR_DATA(y2+2);
LCD_WR_REG(0x2c);//储存器写
}
else
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+1);
LCD_WR_DATA(x2+1);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+2);
LCD_WR_DATA(y2+2);
LCD_WR_REG(0x2c);//储存器写
}
}
void LCD_Init(void)
{
/* Enable Clock to Port D */
CLOCK_SYS_ConfigModuleClock(PMD_CLK, NULL);
PINS_SetMuxModeSel(BOARD_LCD_PORT_MOSI_BASE, BOARD_LCD_GPIO_MOSI_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(BOARD_LCD_PORT_SCLK_BASE, BOARD_LCD_GPIO_SCLK_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(BOARD_LCD_PORT_CS_BASE, BOARD_LCD_GPIO_CS_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(BOARD_LCD_PORT_DC_BASE, BOARD_LCD_GPIO_DC_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(BOARD_LCD_PORT_RES_BASE, BOARD_LCD_GPIO_RES_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(BOARD_LCD_PORT_BLK_BASE, BOARD_LCD_GPIO_BLK_PIN, PM_MUX_AS_GPIO);
PINS_SetPinIntSel(BOARD_LCD_PORT_MOSI_BASE, BOARD_LCD_GPIO_MOSI_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(BOARD_LCD_PORT_SCLK_BASE, BOARD_LCD_GPIO_SCLK_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(BOARD_LCD_PORT_CS_BASE, BOARD_LCD_GPIO_CS_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(BOARD_LCD_PORT_DC_BASE, BOARD_LCD_GPIO_DC_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(BOARD_LCD_PORT_RES_BASE, BOARD_LCD_GPIO_RES_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(BOARD_LCD_PORT_BLK_BASE, BOARD_LCD_GPIO_BLK_PIN, PM_DMA_INT_DISABLED);
PINS_SetPins(BOARD_LCD_MOSI_GPIO, 1U << BOARD_LCD_GPIO_MOSI_PIN);
PINS_SetPins(BOARD_LCD_SCLK_GPIO, 1U << BOARD_LCD_GPIO_SCLK_PIN);
PINS_SetPins(BOARD_LCD_CS_GPIO, 1U << BOARD_LCD_GPIO_CS_PIN);
PINS_SetPins(BOARD_LCD_DC_GPIO, 1U << BOARD_LCD_GPIO_DC_PIN);
PINS_SetPins(BOARD_LCD_RES_GPIO, 1U << BOARD_LCD_GPIO_RES_PIN);
PINS_SetPins(BOARD_LCD_BLK_GPIO, 1U << BOARD_LCD_GPIO_BLK_PIN);
PINS_SetPinDir(BOARD_LCD_MOSI_GPIO, BOARD_LCD_GPIO_MOSI_PIN, 1U);
PINS_SetPinDir(BOARD_LCD_SCLK_GPIO, BOARD_LCD_GPIO_SCLK_PIN, 1U);
PINS_SetPinDir(BOARD_LCD_CS_GPIO, BOARD_LCD_GPIO_CS_PIN, 1U);
PINS_SetPinDir(BOARD_LCD_DC_GPIO, BOARD_LCD_GPIO_DC_PIN, 1U);
PINS_SetPinDir(BOARD_LCD_RES_GPIO, BOARD_LCD_GPIO_RES_PIN, 1U);
PINS_SetPinDir(BOARD_LCD_BLK_GPIO, BOARD_LCD_GPIO_BLK_PIN, 1U);
LCD_RES_Clr();//复位
OSIF_TimeDelay(10);
LCD_RES_Set();
OSIF_TimeDelay(10);
LCD_BLK_Set();//打开背光
OSIF_TimeDelay(120);
LCD_WR_REG(0x11); //Sleep out
OSIF_TimeDelay(120);
LCD_WR_REG(0xB1);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB2);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB3);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB4);
LCD_WR_DATA8(0x03);
LCD_WR_REG(0xC0);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x08);
LCD_WR_DATA8(0x04);
LCD_WR_REG(0xC1);
LCD_WR_DATA8(0XC0);
LCD_WR_REG(0xC2);
LCD_WR_DATA8(0x0D);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0xC3);
LCD_WR_DATA8(0x8D);
LCD_WR_DATA8(0x2A);
LCD_WR_REG(0xC4);
LCD_WR_DATA8(0x8D);
LCD_WR_DATA8(0xEE);
LCD_WR_REG(0xC5);
LCD_WR_DATA8(0x1A);
LCD_WR_REG(0x36); //MX, MY, RGB mode
if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
else LCD_WR_DATA8(0xA0);
LCD_WR_REG(0xE0);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x22);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x0A);
LCD_WR_DATA8(0x2E);
LCD_WR_DATA8(0x30);
LCD_WR_DATA8(0x25);
LCD_WR_DATA8(0x2A);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x26);
LCD_WR_DATA8(0x2E);
LCD_WR_DATA8(0x3A);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x01);
LCD_WR_DATA8(0x03);
LCD_WR_DATA8(0x13);
LCD_WR_REG(0xE1);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x16);
LCD_WR_DATA8(0x06);
LCD_WR_DATA8(0x0D);
LCD_WR_DATA8(0x2D);
LCD_WR_DATA8(0x26);
LCD_WR_DATA8(0x23);
LCD_WR_DATA8(0x27);
LCD_WR_DATA8(0x27);
LCD_WR_DATA8(0x25);
LCD_WR_DATA8(0x2D);
LCD_WR_DATA8(0x3B);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x01);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x13);
LCD_WR_REG(0x3A); //65k mode
LCD_WR_DATA8(0x05);
LCD_WR_REG(0x29); //Display on
}
main.c
#include "user_config.h"
#include "g32a1xxx_pins.h"
#include "board.h"
#include <stdio.h>
#include "osif.h"
#include "lcd.h"
#include "lcd_init.h"
#include "pic.h"
typedef struct
{
unsigned char Index[2];
unsigned char Msk[32];
}typFNT_GB16;
extern const typFNT_GB16 tfont16[];
#define LED_GPIO GPIOD
#define BLUE_LED_PIN (0U)
#define RED_LED_PIN (15U)
#define GREEN_LED_PIN (16U)
#define WHITE_LED_PIN (~0x00018001)
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Pins module initialization LED light
*/
void PINS_Led_Init()
{
/* Enable Clock to Port D */
CLOCK_SYS_ConfigModuleClock(PMD_CLK, NULL);
/* Set pin mode */
PINS_SetMuxModeSel(LED_RED_PORT_BASE, LED_RED_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(LED_GREEN_PORT_BASE, LED_GREEN_PIN, PM_MUX_AS_GPIO);
PINS_SetMuxModeSel(LED_BLUE_PORT_BASE, LED_BLUE_PIN, PM_MUX_AS_GPIO);
/* Set pin interrupt */
PINS_SetPinIntSel(LED_RED_PORT_BASE, LED_RED_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(LED_GREEN_PORT_BASE, LED_GREEN_PIN, PM_DMA_INT_DISABLED);
PINS_SetPinIntSel(LED_BLUE_PORT_BASE, LED_BLUE_PIN, PM_DMA_INT_DISABLED);
/* GPIO Initialization */
PINS_SetPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN);
PINS_SetPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN);
PINS_SetPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN);
/* Set pin as output */
PINS_SetPinDir(LED_RED_GPIO_BASE, LED_RED_PIN, 1U);
PINS_SetPinDir(LED_GREEN_GPIO_BASE, LED_GREEN_PIN, 1U);
PINS_SetPinDir(LED_BLUE_GPIO_BASE, LED_BLUE_PIN, 1U);
}
void Display_title(void)
{
LCD_Fill(0,0,LCD_W,LCD_H,LIGHTBLUE);
LCD_ShowIntNum(8,10,2025,4,BLUE,GREEN,16);
LCD_ShowChinese(40,10,&tfont16[0],BLUE,GREEN,16,0);
LCD_ShowChinese(56,10,&tfont16[1],BLUE,GREEN,16,0);
LCD_ShowChinese(72,10,&tfont16[2],BLUE,GREEN,16,0);
LCD_ShowChinese(88,10,&tfont16[3],BLUE,GREEN,16,0);
LCD_ShowChinese(104,10,&tfont16[4],BLUE,GREEN,16,0);
LCD_ShowChinese(8,30,&tfont16[5],BLUE,GREEN,16,0);
LCD_ShowChinese(24,30,&tfont16[6],BLUE,GREEN,16,0);
LCD_ShowChinese(40,30,&tfont16[7],BLUE,GREEN,16,0);
LCD_ShowChinese(56,30,&tfont16[8],BLUE,GREEN,16,0);
LCD_ShowString(72,30,"A1465",RED,GREEN,16,0);
LCD_ShowChinese(8,50,&tfont16[9],BLUE,GREEN,16,0);
LCD_ShowChinese(24,50,&tfont16[10],BLUE,GREEN,16,0);
LCD_ShowChinese(40,50,&tfont16[11],BLUE,GREEN,16,0);
LCD_ShowChinese(56,50,&tfont16[12],BLUE,GREEN,16,0);
LCD_ShowChinese(72,50,&tfont16[13],BLUE,GREEN,16,0);
LCD_ShowChinese(88,50,&tfont16[14],BLUE,GREEN,16,0);
LCD_ShowChinese(104,50,&tfont16[15],BLUE,GREEN,16,0);
LCD_ShowString(43,140,"2025-01-05",BLUE,GREEN,16,0);
OSIF_TimeDelay(500);
}
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] Main function
*/
int main(void)
{
/* Initialize clock */
CLOCK_SYS_Init(&g_clockConfig);
/* led init */
PINS_Led_Init();
/* uart init */
COM_Init();
/* Initialize LCD */
LCD_Init();
OSIF_TimeDelay(200U);
LCD_Fill(0,0,LCD_W,LCD_H,YELLOW);
OSIF_TimeDelay(200);
LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
PINS_WritePins(LED_GPIO,WHITE_LED_PIN);
while (1)
{
PINS_ClrPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN);
PINS_SetPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN);
PINS_SetPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN);
OSIF_TimeDelay(200);
PINS_SetPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN);
PINS_ClrPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN);
PINS_SetPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN);
OSIF_TimeDelay(200);
PINS_SetPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN);
PINS_SetPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN);
PINS_ClrPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN);
OSIF_TimeDelay(200);
PINS_SetPins(LED_RED_GPIO_BASE, 1U << LED_RED_PIN);
PINS_SetPins(LED_GREEN_GPIO_BASE, 1U << LED_GREEN_PIN);
PINS_SetPins(LED_BLUE_GPIO_BASE, 1U << LED_BLUE_PIN);
LCD_ShowPicture(0,0,128,160,gImage_1);
OSIF_TimeDelay(800);
Display_title();
}
}
五、画图效果
画图采用“Img2Lcd”工具,轻松实现由图片转C代码的处理,至于中文字符的生成,可借助“PCtoLCD2002”工具,如见以下附件,具体使用方法这里不再赘述。
Image2Lcd 2.9.zip
(506.51 KB)
PCtoLCD2002.zip
(886.17 KB)
使用工具导入图片后设置如下,导出则是C数组,直接调用则行。
屏上画出来的效果如下:
驱动程序点屏效果展现如下:
点屏.zip
(1.16 MB)
|
|