3线SPI驱动 HX8347 TFT屏

老五家2.8寸屏,3线SPI驱动

前言

      要知道屏幕的驱动芯片都小的惊人,想必是不会打上丝印的。从几百个引脚中判断哪个是哪个,想想就晕。  大佬们都太厉害了,看看PFC就知道屏幕的接线定义。一直好奇这种神技是怎么练成的。也尝试自己来猜定义,但发现实在太难,还是拿来主义,等着引脚定义比较靠谱。

a81c5161c51b4678bbb7adaeaebc35ee.jpg

 

       本文用的屏是2.8寸TFT屏,驱动芯片是HX8347,定义早被大佬识破:

b7696496f63f4e89b69a8e1a48370bc2.png

        定义有了。但不巧[IM3~0]=1100,只能支持3线SPI+RGB。RGB屏不是单片机的强项。好像STM32F7XX和ESP32 S3是支持RGB,但也只是好像,这两都价格不菲,手头也没有。

        还是想办法用3线SPI来驱动吧。


一、源码

HX8347.h

#ifndef USER_HX8347_H_
#define USER_HX8347_H_#define X_MAX_PIXEL 240
#define Y_MAX_PIXEL 320#define RED     0xf800
#define GREEN   0x07e0
#define BLUE    0x001f
#define WHITE   0xffff
#define BLACK   0x0000
#define YELLOW  0xFFE0
#define GRAY0   0xEF7D      //灰色0 3165 00110 001011 00101
#define GRAY1   0x8410          //灰色1      00000 000000 00000
#define GRAY2   0x4208          //灰色2  1111111111011111#define LCD_CS          GPIO_Pin_0  // CS:PA0
#define LCD_SDA         GPIO_Pin_1  // SDA:PA1
#define LCD_SCL         GPIO_Pin_3  // SCL:PA3
#define LCD_RST         GPIO_Pin_4  // RST:PA4#define LCD_SCL_SET GPIO_WriteBit(GPIOA, LCD_SCL,Bit_SET)
#define LCD_SDA_SET GPIO_WriteBit(GPIOA, LCD_SDA,Bit_SET)
#define LCD_CS_SET  GPIO_WriteBit(GPIOA, LCD_CS,Bit_SET)
#define LCD_RST_SET GPIO_WriteBit(GPIOA, LCD_RST,Bit_SET)#define LCD_SCL_CLR GPIO_WriteBit(GPIOA, LCD_SCL,Bit_RESET)
#define LCD_SDA_CLR GPIO_WriteBit(GPIOA, LCD_SDA,Bit_RESET)
#define LCD_CS_CLR  GPIO_WriteBit(GPIOA, LCD_CS,Bit_RESET)
#define LCD_RST_CLR GPIO_WriteBit(GPIOA, LCD_RST,Bit_RESET)void LCD_GPIO_Init(void);
void Lcd_WriteIndex(unsigned char Index);
void Lcd_WriteData(unsigned char Data);
void LCD_WriteData_16Bit(unsigned int Data);
void Lcd_Write_REG(unsigned char Index,unsigned char Data);
void LCD_Init(void);
void Lcd_Clear(unsigned int Color);
void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color);#endif /* USER_HX8347_H_ */

HX8347.c

#include "debug.h"
#include "HX8347.h"void LCD_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure = {0};RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = LCD_SCL|LCD_SDA|LCD_CS|LCD_RST;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
}//向SPI总线传输一个8位数据
void  SPI_WriteData(unsigned char Data)
{unsigned char i=0;for(i=8;i>0;i--){if(Data&0x80)LCD_SDA_SET; //输出数据else LCD_SDA_CLR;LCD_SCL_CLR;LCD_SCL_SET;Data<<=1;}
}//向液晶屏写一个8位指令
void Lcd_WriteIndex(unsigned char Index)
{//SPI 写命令时序开始LCD_CS_CLR;SPI_WriteData(0x70);SPI_WriteData(Index);LCD_CS_SET;
}//向液晶屏写一个8位数据
void Lcd_WriteData(unsigned char Data)
{LCD_CS_CLR;SPI_WriteData(0x72);SPI_WriteData(Data);LCD_CS_SET;
}//向液晶屏写一个16位数据
void LCD_WriteData_16Bit(unsigned int Data)
{LCD_CS_CLR;SPI_WriteData(0x72);SPI_WriteData(Data>>8);SPI_WriteData(Data);LCD_CS_SET;
}void Lcd_Write_REG(unsigned char Index,unsigned char Data)
{Lcd_WriteIndex(Index);Lcd_WriteData(Data);
}void Lcd_Reset(void)
{unsigned int i;LCD_RST_CLR;for(i=0;i<6000;i++);LCD_RST_SET;for(i=0;i<6000;i++);
}//  set region to paint
void LCD_SetWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{//SCLcd_Write_REG(0x02,x1>>8);       // Column address start2Lcd_Write_REG(0x03,(u8)x1);          // Column address start1//ECLcd_Write_REG(0x04,x2>>8);       // Column address end2Lcd_Write_REG(0x05,(u8)x2);          // Column address end1//SPLcd_Write_REG(0x06,y1>>8);       // Row address start2Lcd_Write_REG(0x07,(u8)y1);          // Row address start1//EPLcd_Write_REG(0x08,y2>>8);       // Row address end2Lcd_Write_REG(0x09,(u8)y2);          // Row address end1//写0x22到index register,那么下次send data就会直接被写到graphic ramLcd_WriteIndex(0x22);
}void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{LCD_SetWindow(x1, y1,x2,y2);x2 = x2 - x1 + 1;y2 = y2 - y1 + 1;for(x1 = x2; x1 != 0 ; x1--){for (y1 = y2;y1 != 0 ;y1--){LCD_WriteData_16Bit(color);}}
}void LCD_Init(void)
{LCD_GPIO_Init();Lcd_Reset();Lcd_Write_REG(0x18,0x88);        //UADJ 75HzLcd_Write_REG(0x19,0x01);        //OSC_EN='1', start Osc//Power Voltage SettingLcd_Write_REG(0x1B,0x1E); //VRH=4.60VLcd_Write_REG(0x1C,0x07); //AP Crosstalk    04Lcd_Write_REG(0x1A,0x01); //BT (VGH~15V,VGL~-10V,DDVDH~5V)Lcd_Write_REG(0x24,0x38); //VMH 27Lcd_Write_REG(0x25,0x5F); //VML//VCOM offsetLcd_Write_REG(0x23,0x8C); //for Flicker adjustLcd_Write_REG(0x1F,0x88);// GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0Delay_Ms(5);Lcd_Write_REG(0x1F,0x80);// GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0Delay_Ms(5);Lcd_Write_REG(0x1F,0x90);// GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0Delay_Ms(5);Lcd_Write_REG(0x1F,0xD0);// GAS=1, VOMG=10, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0Delay_Ms(5);//Display ON SettingLcd_Write_REG(0x28,0x38);   //GON=1, DTE=1, D=1000Delay_Ms(40);Lcd_Write_REG(0x28,0x3C);   //GON=1, DTE=1, D=1100Lcd_Write_REG(0x36,0x09);   //REV, BGRLcd_Write_REG(0x17,0x05);  //16BIT/PIXEL//Gamma 2.2 SettingLcd_Write_REG(0x40,0x00); //Lcd_Write_REG(0x41,0x00); //Lcd_Write_REG(0x42,0x00); //Lcd_Write_REG(0x43,0x11); //Lcd_Write_REG(0x44,0x0e); //Lcd_Write_REG(0x45,0x23); //Lcd_Write_REG(0x46,0x08); //Lcd_Write_REG(0x47,0x53); //Lcd_Write_REG(0x48,0x03); //Lcd_Write_REG(0x49,0x11); //Lcd_Write_REG(0x4A,0x18); //Lcd_Write_REG(0x4B,0x1a); //Lcd_Write_REG(0x4C,0x16); //Lcd_Write_REG(0x50,0x1c); //Lcd_Write_REG(0x51,0x31); //Lcd_Write_REG(0x52,0x2e); //Lcd_Write_REG(0x53,0x3f); //Lcd_Write_REG(0x54,0x3f); //Lcd_Write_REG(0x55,0x3f); //Lcd_Write_REG(0x56,0x2c); //Lcd_Write_REG(0x57,0x77); //Lcd_Write_REG(0x58,0x09); //Lcd_Write_REG(0x59,0x05); //Lcd_Write_REG(0x5A,0x07); //Lcd_Write_REG(0x5B,0x0e); //Lcd_Write_REG(0x5C,0x1c); //Lcd_Write_REG(0x5D,0x88); //Delay_Ms(100);FillRect(0, 160, 239, 239, 0xf800 );
}

二、说明

 

1、LCD初始化是从GITHUB上拷的一段程序,具体是啥意思我也不清楚。试过官方数据手册里的初始化程序,一直不能成功。

2、写寄存器的程序

void Lcd_WriteIndex(unsigned char Index)
{
   LCD_CS_CLR;
   SPI_WriteData(0x70);
   SPI_WriteData(Index);
   LCD_CS_SET;
}

 3、写数据的程序

void Lcd_WriteData(unsigned char Data)
{
   LCD_CS_CLR;
   SPI_WriteData(0x72);
   SPI_WriteData(Data);

   LCD_CS_SET;
}

        上面程序中出现SPI_WriteData(0x70); SPI_WriteData(0x72);统一解释下:

        因为是3线SPI,所以缺少CD(或RS)引线,解决的办法一般是SPI发送数据时第一个bit的值代表CD。这样因为多出了1bit,就需要处理9bit的数据。UC1601就是这样,但是HX8347不是这样。

        下面栽自HX8347的数据手册:

fd17fcefa9e34c62a4180b2c2fa0f32b.png

87780c2fc9a94fe089da65e3175e7d94.png

        大概意思就是在发数据前需要发“01110”[ID][RS][RW],一共是8bit。

        这里ID应该取0。RS取0是写寄存器,取1是写数据。RW取0,表示写。

        所以写寄存器就是:01110000=0x70;写数据就是:01110010=0x72。也因此就有了:

        SPI_WriteData(0x70); SPI_WriteData(0x72);

三、总结

1、主控是沁恒家申请的CH32V307的评估板,开发工具是mountriver。不得不说评估板和开发工具都很完美。评估板留有arduino接口,可以和arduino扩展板链接。mountriver编译很快,下载烧录更快,基本都零点几秒。

2、本源码可以添加到CH32V307的demo中CH32V307EVT\EVT\EXAM\GPIO\GPIO_Toggle例程中运行。

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();

 

    LCD_Init();
    while(1)
    {
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, 0x07c0 );
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, 0x0030 );
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, 0x0000 );
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, 0xf800 );
    }
}

3、如果屏幕没有任何显示,可能需要按下评估板的RESET键。

4、用的是软件模拟3线SPI,所以帧数很低。以后考虑硬件SPI,或再加DMA,但DMA需要SRAM太大。

演示用视频

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/183717.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符型液晶显示器LCD 1602的显示控制(Keil+Proteus)

前言 趁机把LCD 1602的实验完成了&#xff0c;那个电路图有几个地方没弄懂&#xff0c;但是去掉也没有报错&#xff0c;就没管了。 LCD1602_百度百科 (baidu.com)https://baike.baidu.com/item/LCD1602/6014393?frge_ala LCD1602液晶显示屏通过电压来改变填充在两块平行板之…

动态规划专题——背包问题

&#x1f9d1;‍&#x1f4bb; 文章作者&#xff1a;Iareges &#x1f517; 博客主页&#xff1a;https://blog.csdn.net/raelum ⚠️ 转载请注明出处 目录 前言一、01背包1.1 使用滚动数组优化 二、完全背包2.1 使用滚动数组优化 三、多重背包3.1 使用二进制优化 四、分组背包…

混合云中 DevOps 的最佳实践

近年来&#xff0c;出现了各种工具、技术和框架&#xff0c;其目标是增强灵活性、性能和可扩展性。传统的整体方法已被微服务和纳米服务等更加模块化的方法所取代。此外&#xff0c;云计算的兴起导致本地软件被云环境所取代&#xff0c;云环境提供了以前无法提供的广泛优势和功…

Qwt QwtThermo绘制温度计

1.简介 QwtThermo 是一个基于 Qt 框架的类库&#xff0c;用于创建温度计控件。它提供了一些方便的功能来展示和处理温度计相关的数据。 QwtThermo 添加了特定于温度计的功能。 使用 QwtThermo&#xff0c;可以实现以下功能&#xff1a; 设置温度范围&#xff1a;可以通过设置…

【EI会议征稿】第四届智慧城市工程与公共交通国际学术会议(SCEPT 2024)

第四届智慧城市工程与公共交通国际学术会议&#xff08;SCEPT 2024&#xff09; 2024 4th International Conference on Smart City Engineering and Public Transportation 第四届智慧城市工程与公共交通国际学术会议&#xff08;SCEPT 2024&#xff09;将于2024年1月26-28日…

折叠旗舰新战局:华为先行,OPPO接棒

乌云中的曙光&#xff0c;总能带给人希望。 全球智能手机出货量已经连续八个季度下滑&#xff0c;行业里的乌云挥之不散。不过&#xff0c;也能看到高端市场逆势上涨&#xff0c;散发光亮。个中逻辑在于&#xff0c;当前换机周期已经达到了34个月&#xff0c;只有创新产品才能…

【ARFoundation学习笔记】平面检测

写在前面的话 本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏&#xff0c;更多详细内容请阅读原文。 文章目录 平面检测属性可视化平面平面检测的开关控制显示与隐藏已检测平面 平面检测属性 AR中检测平面的原理&#xff1a;AR Fou…

洛谷P1024 [NOIP2001 提高组] 一元三次方程求解(优雅的暴力+二分,干净利落)

P1024 [NOIP2001 提高组] 一元三次方程求解 前言题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题目分析注意事项 代码后话额外测试用例样例输入 #2样例输出 #2 王婆卖瓜 题目来源 前言 没有前言&#xff0c;可能因为作者忘了编辑 题目 题目描述 有形如&…

使用Redis实现缓存及对应问题解决

一、为什么需要Redis作缓存&#xff1f; 在业务场景中&#xff0c;如果有些数据需要极高频的存取&#xff0c;每次都要在mysql中查询的话代价太大&#xff0c;假如有一个存在于客户端和mysql之间的存储空间&#xff0c;每次可以在这空间中进行存取操作&#xff0c;就会减轻mys…

简单工厂模式、工厂方法模式、抽象工厂模式

简介 将实例化代码提取出来&#xff0c;放到一个类中统一管理和维护&#xff0c;达到和主项目依赖关系的解耦&#xff0c;从而提高项目的扩展性和维护性。 工厂模式将复杂的对象创建工作隐藏起来&#xff0c;而仅仅暴露出一个接口供客户使用&#xff0c;具体的创建工作由工厂管…

跨境电商平台Etsy被封?那是因为你没做对这件事!

ETSY是一个在线市场和电商平台&#xff0c;专注于手工艺品、独特商品和创意艺术。它为卖家提供了一个平台来展示和销售自己的手工制品、艺术品、珠宝、家居用品、时尚配饰等各种创意产品。作为一个颇受中国商家青睐的平台&#xff0c;Etsy在账号检测方面也是不亚于亚马逊之严格…

设计模式之工厂模式(Factory)

任何可以产生对象的方法或类&#xff0c;都可以称为工厂。 下面的代码定义了Car这种交通工具: public class Car {public void go() {System.out.println("Car go wuwuwuwuw....");} }然后在main函数里面想要调用调用Car的go方法&#xff0c;就需要new一个car对象&…

音频修复增强软件iZotope RX 10 mac中文特点

iZotope RX 10 mac是一款音频修复和增强软件。 iZotope RX 10 mac主要特点 声音修复&#xff1a;iZotope RX 10可以去除不良噪音、杂音、吱吱声等&#xff0c;使音频变得更加清晰干净。 音频增强&#xff1a;iZotope RX 10支持对音频进行音量调节、均衡器、压缩器、限制器等处…

grdle 的安装与配置 、gradle和jdk版本对应关系

java与gradle对应的版本关系 Java Java Gradle需要Java版本在8到19之间。目前还不支持Java 20及更高版本。 Java 6和Java 7仍然可以用于编译&#xff0c;但已经不适合用于测试。Gradle 9.0不支持Java 6和Java 7的测试。任何完全支持的Java版本都可以用于编译或测试。 然而&…

如何使用VSCode来查看二进制文件

2023年11月6日&#xff0c;周一下午 目录 方法1&#xff1a;安装插件Binary Viewer然后用vscode打开一个二进制文件&#xff0c;并点击右上角的"HEX"方法2&#xff1a;安装插件Binary然后用vscode打开一个二进制文件&#xff0c;并点击右上角的"B" 方法1&…

Docker安装教程

Docker安装教程 安装教程Centos7.6docker镜像源修改docker目录修改 Ubuntu20.04docker镜像源修改docker数据目录修改 安装教程 Centos7.6 &#x1f680;docker支持的Cetnos操作系统版本 CentOS 7 CentOS 8 (stream) CentOS 9 (stream) &#x1f680;支持的CPU ARM/X86_64 查看…

操作系统:文件管理(二)文件系统

一战成硕 4.3 文件系统4.3.1 文件系统结构4.3.2 文件系统布局4.3.3 外存空闲空间管理4.3.4 虚拟文件系统 4.3 文件系统 4.3.1 文件系统结构 4.3.2 文件系统布局 文件系统在磁盘中的结构 文件系统在内存中的结构 内存中的信息用于管理文件系统并通过缓存提高性能&#xff0c;这…

第十一章《搞懂算法:聚类是怎么回事》笔记

聚类是机器学习中一种重要的无监督算法&#xff0c;可以将数据点归结为一系列的特定组合。归为一类的数据点具有相同的特性&#xff0c;而不同类别的数据点则具有各不相同的属性。 11.1 聚类算法介绍 人们将物理或抽象对象的集合分成由类似 的对象组成的多个类的过程被称为聚…

用Java(C语言也可以看)实现冒泡排序和折半查找(详细过程图)+逆序数组

目录 一、冒泡排序 1.冒泡排序介绍 2.排序的思路 3.完整代码 二、折半查找 1.折半查找介绍 2.查找的思路 3.完整代码 三、逆序数组 1.逆序思路 2..完整代码 一、冒泡排序 冒泡排序是众多排序的一种&#xff0c;无论在C语言或者Java中都很常见&#xff0c;后续在数据…

基于Chirp窄带扩频技术的无线混合组网应用,以多角色智能计量插座作为Chirp广域基站,构建边缘计算混合无线网络

随着物联网&#xff08;IoT&#xff09;的不断发展&#xff0c;无线通信技术的需求也在不断增加。Chirp窄带扩频技术是一种具有广泛应用潜力的无线通信技术&#xff0c;它在低功耗、广域覆盖、抗干扰等方面具备独特的优势。本文介绍了如何利用磐启微Chirp技术构建ECWAN无线混合…