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.mzph.cn/news/134075.shtml

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

相关文章

ASUS华硕灵耀X2 Duo UX481FA(FL,FZ)_UX4000F工厂模式原装出厂Windows10系统

下载链接&#xff1a;https://pan.baidu.com/s/1sRHKBOyc3zu1v0qw4dSASA?pwd7nb0 提取码&#xff1a;7nb0 带有ASUS RECOVERY恢复功能、自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、MyASUS华硕电脑管家等预装程序所需要工具&#xff1a;16G或以上…

按键精灵中的UI界面操作

1. 按键精灵中UI界面常用的控件 1. 文字框 界面1: {标签页1:{文字框:{名称:"文字框1",显示内容:"显示内容",文字大小:0,高度:0,宽度:0,注释:"文字大小、高度、宽度是可选属性&#xff0c;如需使用默认值&#xff0c;可保持值为0或直接删除此属性&qu…

技术分享 | App常见bug解析

功能Bug 内容显示错误 前端页面展示的内容有误。 这种错误的产生有两种可能 1、前端代码写的文案错误 2、接口返回值错误 功能错误 功能错误是在测试过程中最常见的类型之一&#xff0c;也就是产品的功能没有实现。比如图中的公众号登录不成功的问题。 界面展示错乱 产品…

网络溯源-PSEXEC-简单

题干&#xff1a; 我们的入侵检测系统&#xff08;IDS&#xff09;已发出警报&#xff0c;指示涉及使用PsExec的可疑横向移动活动。为了有效响应此事件&#xff0c;您作为 SOC 分析师的角色是分析存储在 PCAP 文件中的捕获网络流量。 攻击者首次攻击成功的计算机源网络IP地址…

【服务器】Java连接redis及使用Java操作redis、使用场景

一、Java连接redis-No-SQL 1、导入依赖 在你的项目里面导入redis的pom依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version> </dependency> 2、连接redis 连接redis //…

AI:61-基于深度学习的草莓病害识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

高压放大器能够在哪里使用呢

高压放大器是一种重要的电子设备&#xff0c;可以在许多不同的领域和应用中使用。下面西安安泰将详细介绍高压放大器的应用。 医学影像&#xff1a;高压放大器在医学影像领域具有广泛的应用。医学影像设备&#xff08;如X射线机、CT扫描仪等&#xff09;需要高压来产生足够的能…

竞赛选题 深度学习手势识别算法实现 - opencv python

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习手势识别算法实现 - opencv python 该项目较为新颖…

网络的地址簿:Linux DNS服务的全面指南

1 dns 1.1 dns&#xff08;域名解析服务&#xff09;介绍 当访问 www.baidu.com 首先查询/etc/hosts&#xff0c;如果没有再去查询/etc/resolv.conf&#xff0c;还是没有就去查询域名服务器 关于客户端: /etc/resolv.conf ##dns指向文件 nameserver 172.25.254.20测试&…

Oracle(11)Managing Tables

Managing Tables 管理表 目标&#xff1a; 识别存储数据的各种方法概述甲骨文数据类型区分扩展ROWID与限制ROWID勾勒出一行的结构创建常规表和临时表管理表中的存储结构重新组织、截断和删除表删除表中的列 一、基础知识 1、Oracle Built-in Data Types Oracle内置数据类型 2…

竞赛选题 深度学习手势检测与识别算法 - opencv python

文章目录 0 前言1 实现效果2 技术原理2.1 手部检测2.1.1 基于肤色空间的手势检测方法2.1.2 基于运动的手势检测方法2.1.3 基于边缘的手势检测方法2.1.4 基于模板的手势检测方法2.1.5 基于机器学习的手势检测方法 3 手部识别3.1 SSD网络3.2 数据集3.3 最终改进的网络结构 4 最后…

【ARFoundation学习笔记】平面检测

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

socks5代理和https代理有什么不同?各自有哪些优点?

socks5代理和https代理是两种不同的代理服务&#xff0c;它们在实现方式、安全性和协议特点等方面存在差异。下面我们来详细了解一下这两种代理的优点。 一、socks5代理的优点 1. 速度快 socks5代理采用了TCP协议&#xff0c;能够有效地减少网络延迟和数据传输速度慢的问题&…

nn.embedding函数详解(pytorch)

提示&#xff1a;文章附有源码&#xff01;&#xff01;&#xff01; 文章目录 前言一、nn.embedding函数解释二、nn.embedding函数使用方法四、模型训练与预测的权重变化探讨 前言 最近发现prompt工程(如sam模型)&#xff0c;也有transform的detr模型等都使用了nn.Embedding函…

c语言经典算法—二分查找,冒泡,选择,插入,归并,快排,堆排

一、二分查找 1、前提条件&#xff1a;数据有序&#xff0c;随机访问&#xff1b; 2、实现&#xff1a;递归实现&#xff0c;非递归实现 3、注意事项&#xff1a; 循环退出条件:low <high,low high.说明还有一个元素&#xff0c;该元素还要与key进行比较 mid的取值&#xf…

UE5 新特性 Nanite 开启

啥也不说&#xff0c;只能说&#xff0c;真的牛&#xff0c;在自己的项目上&#xff0c;从10几20的帧数&#xff0c;直接彪到了70 适用场景&#xff1a; 大场景&#xff0c;三角面足够多 在Project Setting里面 将这几个勾未true 勾上这个&#xff0c;放入场景即可

【电子通识】USB Logo的标识含义

USB 图标的设计灵感是来自罗马神话中的海神尼普顿(Neptune)&#xff08;也是海王星的名字&#xff09;的武器「三叉戟」&#xff0c;一支强有力的三齿鱼叉。不过&#xff0c;为了避免鱼叉形状的设计暗示人们拿着自己的USB 存储设备到处乱插&#xff08;叉&#xff09;。设计师对…

机器学习模型,超级全面总结!

机器学习是一种通过让计算机自动从数据中学习规律和模式&#xff0c;从而完成特定任务的方法。按照模型类型&#xff0c;机器学习可以分为两大类&#xff1a;监督学习模型和无监督学习模型。 附注&#xff1a;除了以上两大类模型&#xff0c;还有半监督学习和强化学习等其他类…

Texlive安装

下载4.8G的iso文件 解压 或 装载后&#xff0c;以管理员身份运行(.bat)文件。 运行以下两句代码进行Texlive相关升级 tlmgr option repository otan tlmgr update --self --all 运行以下三行代码&#xff0c;检查是否安装成功 latex -v xelatex -v pdflatex -v 如果有异常…

基于单片机的智能扫地机设计

概要 本文主要设计一个简单的智能扫地机。该扫地机的核心控制元器件是stc89c52&#xff0c;具有编写程序简单&#xff0c;成本普遍较低&#xff0c;功能较多&#xff0c;效率特别高等优点&#xff0c;因此在市场上得到很大的应用。除此之外&#xff0c;该扫地机能够自动避开障碍…