分别使用软件和硬件SPI驱动1.28寸LCD屏幕刷新时间对比(驱动IC为GC9A01)

news2024/11/24 19:40:21

写在前面:
屏幕供应商提供的GC9A01驱动代码过于简陋,使用的话需要修改的东西比较多,还好看到一篇文章,而且博主分享了驱动代码。文章地址

以下软件SPI部分是通过博主分享的驱动代码得来的,稍微改一下就可以用,就不多说了。

使用起来发现使用软件模拟SPI的话,屏幕刷新速度特别慢(RGB565),刷新一张240*240的图片(115200字节,MCU主频使用40MHz),需要1秒多。然后就想着要提高一下刷新速度,先更改一下代码。

因为要操作的信号线除了SPI用到的CLK和MOSI之外,还有片选线CS,数据/寄存器选择线RS,如果直接使用HAL库的GPIO写函数的话会有冗余代码。
在这里插入图片描述
所以直接用宏定义替换HAL_GPIO_WritePin()函数,直接改GPIO寄存器。

#define LCD_RESET_HIGH     LCD_RESET_GPIO_Port->BSRR = (uint32_t)LCD_RESET_Pin;
#define LCD_RESET_LOW      LCD_RESET_GPIO_Port->BRR = (uint32_t)LCD_RESET_Pin;

#define LCD_CS_HIGH        LCD_CS_GPIO_Port->BSRR = (uint32_t)LCD_CS_Pin;
#define LCD_CS_LOW         LCD_CS_GPIO_Port->BRR = (uint32_t)LCD_CS_Pin;

#define LCD_RS_HIGH        LCD_RS_GPIO_Port->BSRR = (uint32_t)LCD_RS_Pin;
#define LCD_RS_LOW         LCD_RS_GPIO_Port->BRR = (uint32_t)LCD_RS_Pin;

#define LCD_TE_HIGH        LCD_TE_GPIO_Port->BSRR = (uint32_t)LCD_TE_Pin;
#define LCD_TE_LOW         LCD_TE_GPIO_Port->BRR = (uint32_t)LCD_TE_Pin;

#define LCD_CLK_HIGH       LCD_CLK_GPIO_Port->BSRR = (uint32_t)LCD_CLK_Pin;
#define LCD_CLK_LOW        LCD_CLK_GPIO_Port->BRR = (uint32_t)LCD_CLK_Pin;

#define LCD_MOSI_HIGH      LCD_MOSI_GPIO_Port->BSRR = (uint32_t)LCD_MOSI_Pin;
#define LCD_MOSI_LOW       LCD_MOSI_GPIO_Port->BRR = (uint32_t)LCD_MOSI_Pin;

修改之后刷新一张图片需要650ms左右,这些时间只是个大概,因为是看串口的时间戳,没有用示波器去抓,只是做个对比。

LCD_ShowPicture()和LCD_WR_DATA8()函数都有for循环,LCD_WR_DATA8()函数是通过移位来发送字节的,那么就改成不移位,直接发送。

void LCD_Writ_Bus_8(uint8_t dat) 
{
	LCD_CLK_LOW;
	if(dat&0x80)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x40)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x20)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x10)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x08)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x04)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x02)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;
	LCD_CLK_LOW;
	if(dat&0x01)
	{
		 LCD_MOSI_HIGH;
	}
	else
	{
		 LCD_MOSI_LOW;
	}
	LCD_CLK_HIGH;	
}

这样下来刷新一张图片大概要350ms左右,相似的也可以一次发送16位,24位等,但是会发现速度基本没有提升。

		LCD_Writ_Bus_16(*(uint16_t*)(pic+i));
		LCD_Writ_Bus_32(*(uint32_t*)(pic+i));

然后就是主频的问题,原本用的40MHz,改为80MHz之后刷新一张图片大概要170ms左右。

之后就想着使用硬件SPI对比一下,SPI初始化好之后改一下原有的发送函数就可以了。

#ifdef HARDWARE_SPI
void LCD_Writ_Bus(uint8_t dat) 
{
	LCD_CS_LOW;
	HAL_SPI_Transmit(&hspi1,&dat,1,0xfff);
	LCD_CS_HIGH;
}
#else
void LCD_Writ_Bus(uint8_t dat) 
{	
	uint8_t i;
	LCD_CS_LOW;
	for(i=0;i<8;i++)
	{			  
		LCD_CLK_LOW;
		if(dat&0x80)
		{
		   LCD_MOSI_HIGH;
		}
		else
		{
		   LCD_MOSI_LOW;
		}
		LCD_CLK_HIGH;
		dat<<=1;
	}	
  LCD_CS_HIGH;
}
#endif

在显示图片函数里面将原有的两个for循环改为HAL_SPI_Transmit()函数,需要注意一下长度的问题,一共有240*240*2(115200)个字节需要发送,但是HAL_SPI_Transmit()函数参数中大小的类型为uint16_t,所以要分两次发送,另外就是要设置一下片选线CS状态。

void LCD_ShowPicture_Fast(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[])
{
	uint32_t i,j;
	uint32_t k=0;
	LCD_Address_Set(x,y,x+length-1,y+width-1);
	LCD_CS_LOW;
	HAL_SPI_Transmit(&hspi1,(uint8_t *)pic,57600,0xfff);
	HAL_SPI_Transmit(&hspi1,(uint8_t *)(pic+57600),57600,0xfff);
	LCD_CS_HIGH;
}

之所以可以这么写,是因为手册中有一个连续写内存命令。
在这里插入图片描述
命令描述大概就是在写内存开始命令和连续写命令之后,会根据设置的范围自动换行或者换列,超出范围的数据会被忽略,所以就可以直接用HAL_SPI_Transmit()函数发送。在设置好显示区域之后,需要设置0x2C或者0x3C寄存器,后面直接跟数据就可以。

改为硬件SPI之后,刷新一张图片大概需要60ms左右(MCU主频使用40MHz),这么一对比的话还是直接用硬件SPI吧。

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

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

相关文章

jconsole工具监测jvm

背景 本篇文章为了记录如何使用jconsole工具。 jconsole工具使用环境是windows&#xff0c;监控服务端在linux上。 如何启动jconsole 找到你本地jdk的目录&#xff0c;进入bin目录&#xff0c;找到jconsole.exe程序双击启动即可 本地进程 如果是想调试本地程序的话&#xf…

23、iOS逆向防护

一、ptrace 1.1 、ptrace概述 ptrace: process trace,提供一个进程监察和控制另一个进程.并且可以读取和改变被控制进程的内存和寄存器里面的数据.它就可以用来实现断点调试和系统调用跟踪. App可以被lldb动态调试,因为App被设备中的debugserver附加,它会跟踪我们的应用进程…

Java阶段二Day08

Java阶段二Day08 文章目录 Java阶段二Day08DML语言-数据操作语言INSERTUPDATEDELETE 数据类型整数类型浮点类型字符类型日期类型 约束条件主键约束&#xff08;PRIMARY KEY&#xff09;非空约束&#xff08;NOT NULL&#xff09;唯一性约束&#xff08;UNIQUE&#xff09;检查约…

安科瑞:列头柜、监控系统、触摸屏的数据中心机房配电方案

摘要 安科瑞精密配电系统是安科瑞针对数据中心集中监控要求提供的多回路监控装置&#xff0c;监控多回路电参量并可对各种故障进行告警。主要适用于各类列头柜、精密配电柜、电源分配柜、UPS输出柜等末端配电设备的监控。在阐述数据中心机房机柜配电目标要求的基础上&#xff…

Redis分布式缓存方案

分布式缓存 单节点Redis问题 数据丢失&#xff1a;数据持久化并发能力弱&#xff1a;搭建主从集群&#xff0c;实现读写分离故障恢复问题&#xff1a;哨兵实现健康检测&#xff0c;自动恢复存储能力&#xff1a;搭建分片集群&#xff0c;利用插槽机制实现动态扩容 Redis持久…

Windows逆向安全(一)之基础知识(十八)

指针作为参数 代码 #include "stdafx.h" void function(int num){num52; } void function2(int* num){*num52; } int main(int argc, char* argv[]) {int num610;function(num);printf("%d\n",num);function2(&num);printf("%d\n",num);re…

KVM NAT 模型

目录 NAT原理 virbr0-nic作用 关于kvm中的网桥和virbr0-nic网卡需注意以下几点&#xff1a; NAT原理 virbr0-nic作用 在kvm中每次通过kvm创建一个网桥都会自动在该网桥下创建两个接口&#xff0c;与网桥同名的virbr0接口代表这个虚拟网桥&#xff0c;可以通过它来配置网桥…

vue2的生命周期

生命周期就是记录数据的状态。对数据进行操作 刚开始 new Vue() 创建了一个实例对象 beforeCreate() 数据还没有创建出来 created() 数据创建出来了&#xff0c;可以访问 判断有没有el 或 template 后 将模板编译成渲染函数 beforeMount() 数据还没有挂在到页面上面 mou…

引入tiff.js报错

当我们安装引入tiff.js时&#xff0c;会遇到这些问题&#xff0c;相关命令以及错误&#xff1a; 1、安装tiff依赖 npm install tiff.js 2、引入tiff import Tiff from tiff.js 3、错误展示&#xff1a; 这个错误是因为没有在vue.config.js以及webpack.base.conf.js(在build文…

C4D的GPU渲染器Octane和Redshift的渲染对比

对CG圈创作人员来说&#xff0c;除制作软件外渲染器是平时接触最多的一类软件&#xff0c;用渲染器进行渲染的过程&#xff0c;就是把制作软件里的预览效果变到融合材质、光照、物理特性的最终效果的这个过程&#xff0c;这是CG制作中最重要的一步&#xff0c;关乎着最终效果的…

头歌--shell脚本入门 变量、字符串--第3关:shell 字符串

任务描述 本关带领大家熟悉 shell 的变量并掌握其使用。 相关知识 字符串概念 字符串是 shell 编程中最常用最有用的数据类型&#xff08;除了数字和字符串&#xff0c;也没啥其它类型好用了&#xff09;&#xff0c;字符串可以用单引号&#xff0c;也可以用双引号&#xff…

数据库系统概论--期末复习

目录 一.绪论 一.数据库系统概述 二.数据模型 三.数据库系统的结构 四.数据库系统的组成 二.关系数据库 一.关系数据结构及形式化定义 二.关系操作 三.关系的完整性 四.关系代数 三.SQL语言 一.数据定义 二.数据查询 三.数据更新 四.视图 四.数据库安全性 1.不安…

Access Token 访问令牌 如何获取?

一、引用 三方库导入时&#xff0c;通常需要输入账号和令牌进行鉴权。账号为指定平台的 HTTP 克隆账号&#xff0c;访问令牌即 Access Token&#xff0c;本文介绍如何获取常见三方代码平台的Access Token。 Access Token 通常在代码平台的个人账号设置内进行管理和配置&#xf…

给konva加个刻度尺

给konva加个刻度尺 最近在用konva做一些&#xff0c;一开始写了不少辅助函数。帮助自己给物体定位 &#xff0c;现在贡献出来给大家用。 给图层增加刻度尺 顾名思义就是加个刻度显示&#xff0c;效果如下&#xff1a; 代码&#xff1a; 第一个参数时layer&#xff0c;第二个…

居民配电所远程监控解决方案

一、项目背景 随着城市建设提速发展、能源利用日益提高、环保节能成为了城市发展的新趋势&#xff0c;配电站逐渐成为企业和居民生活中不可或缺的组成部分。居民的生活用电需求也日益增大。如果没有及时处理好用电安全很容易出现电力中断等情况发生。因此及时高效地为用电客户…

区域LIS源码,基于云计算B/S架构医学实验室检验系统源码

基于B/S架构的医学实验室检验系统源码&#xff0c;整个系统的运行基于WEB层面&#xff0c;只需要在对应的工作台安装一个浏览器软件有外网即可访问。全套系统采用云部署模式&#xff0c;部署一套可支持多家医院检验科共同使用。 采用.Net Core新的技术框架、DEV报表、前端js封…

CASS方格网法土石方量计算

1、打开软件&#xff0c;在“绘图处理”-“展野外测点点号”&#xff0c;默认比例尺为1:500&#xff0c;如下&#xff1a; 2、打开后&#xff0c;在命令行输入pl&#xff0c;绘制范围线&#xff0c;将所有点大致圈起来&#xff0c;如下&#xff1a; 展点结果 范围线绘制结果 3…

【软件测试面试】性能测试常问面试题?不备这些真不敢去面了...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 性能测试的应用领…

给图片加颜色边框怎么弄,3种好用方法

给图片加颜色边框怎么弄&#xff1f;图片是我们每个人平时都必不可少的文件之一&#xff0c;尤其是在工作中的使用&#xff0c;不同的使用场景对于图片的要求也是不一样的&#xff0c;这就要求我们具有一定的图片处理技能&#xff0c;现在任何事情都离不开电脑&#xff0c;所以…

操作系统原理 —— 进程状态切换具体做了哪些事情?(八)

什么是进程控制&#xff1f; 进程控制的主要功能是&#xff1a;对系统中的所有进程实施有效的管理&#xff0c;它具有创建新进程、撤销已有进程、实现进程状态转换等功能。 简单来说&#xff0c;就是进程控制就是要现实进程状态的转换。 那如何实现进程的控制呢&#xff1f;…