找回密码
 立即注册
楼主: 浦江一水

SPI-TFT(240x240)彩屏@屠龙刀-32G12K128 驱动 | TFT取代OLED12864,ST7789

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2025-10-14 08:37:20

31

主题

371

回帖

4405

积分

荣誉版主

积分
4405
发表于 2025-10-3 21:08:34 | 显示全部楼层
dong*** 发表于 2025-10-3 10:21
你好版主,清屏的一个语句不太明白,“ for (temp = 0; temp < 115200; temp++) LCD_DATA(COLOR[Bcolor]);  ...

  清屏函数实际上就是用一种颜色填满整个显示缓存区, 因为这个是彩色显示屏, 每一个像素是用16位来表示的,RGB格式, 红色R占5位, 绿色G占6位, 蓝色B占6位,  即一个像素占用2个字节,所以共计要用240*240*2个字节来填充.
  另外, 320*340的显示屏, 横屏竖屏的切换, 主要是在初始化函数中实现, 首先要确定显示屏是什么驱动, 要看具体手册描述, 看相关寄存器的定义, 常见的是对地址为0x36的寄存器,要弄清楚各个位的定义, 写入指定的控制字即可.
比如本案例中, ST7789驱动: 初始化函数中的这些语句:
LCD_CMD(0x36);
LCD_DAT(0x00);  //LCD_DAT(0xC0);XY镜像
                          // LCD_DAT(0x00); Memory Data Access Control
注释中已经提示了可能的变化, 其实质是改变内存扫描的方向.
同时要好匹配宽度和高度参数:
本案例中, 初始化函数中的这些语句:
  LCD_CMD(0x2A);
  LCD_DAT(0x00); LCD_DAT(0x00);LCD_DAT(0x00); LCD_DAT(0xF0);  //宽度240
  LCD_CMD(0x2B);
  LCD_DAT(0x00);LCD_DAT(0x00);LCD_DAT(0x01); LCD_DAT(0x40);  //高度320

要注意各种显示屏的定义是不一定相同的.
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:66
  • 最近打卡:2025-10-15 07:28:26

14

主题

29

回帖

430

积分

中级会员

积分
430
发表于 2025-10-4 08:57:43 | 显示全部楼层
浦江*** 发表于 2025-10-3 21:08
清屏函数实际上就是用一种颜色填满整个显示缓存区, 因为这个是彩色显示屏, 每一个像素是用16位来表示的 ...

一、我刚开始也是这样想的,因为双字节所以乘二,但我看见for后面的LCD_DATA(COLOR[Bcolor]); 我就糊涂了,LCD_DATA(COLOR[Bcolor]); 是个双字节函数,(刚才我试过了应该不乘2,也是满屏
二、LCD_CMD(0x36);
       LCD_DAT(0x00);  //LCD_DAT(0xC0);XY镜像
                          // LCD_DAT(0x00); Memory Data Access Control
这个我修改成LCD_DAT(0xC0);他只是改了扫描方向,调转180度,但还是竖屏,手册全是英文看不懂。
三、l=strlen(str);与 L=Len;  这个是怎么来的,也没找到,
最后向你不辞辛苦的解答表示衷心的感谢,祝你国庆节快乐。

点评

1, 这个LCD_DAT()和LCD_DATA()函数都是我自己定义的, 目的是简明, 前者发送8位,单字节数据, 后者是发送16位双字节数据. 搞清楚原理, 适当使用即可. 有时候写源程序比较简练, 属于个人爱好. 是可以灵活变化的. 2, 320  详情 回复 发表于 2025-10-4 16:44
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2025-10-14 08:37:20

31

主题

371

回帖

4405

积分

荣誉版主

积分
4405
发表于 2025-10-4 16:44:21 | 显示全部楼层
dong*** 发表于 2025-10-4 08:57
一、我刚开始也是这样想的,因为双字节所以乘二,但我看见for后面的LCD_DATA(COLOR[Bcolor]); 我就糊涂了 ...

1, 这个LCD_DAT()和LCD_DATA()函数都是我自己定义的, 目的是简明, 前者发送8位,单字节数据, 后者是发送16位双字节数据. 搞清楚原理, 适当使用即可. 有时候写源程序比较简练, 属于个人爱好. 是可以灵活变化的.
2, 320*240显示屏切换横竖问题, 可以提供一下你的显示屏是什么驱动芯片的, 或许能帮你找找看解释一下.
3, 关于l=strlen(str); 这是求一个字符串长度的函数, 它是C语言中的标准函数,不需要自己编写的.它定义在string.h中, 只要在文件开始处加入#include <string.h>就可以使用此函数了.
(注意一下#include "string.h" 和#include <string.h>,虽然都可以,但还是有区别的.)
这里还牵涉到个人的习惯爱好问题.比如, 显示一个16点阵字体的字符串文本,函数咋写?
我的习惯是:
LCD_P16(u16 x,u16 y,char * str,u16 fc,u16 bc);
这里函数名称中P16就是Printf显示16点阵字体的意思, 后面就四个或五个参数: x,y,屏幕坐标,后跟具体字符串, 再就是指定前景色和背景色, 比较简明.(若是单色屏,可再省一个参数,简化为mode, 1或0,正显还是反显)
通常你可能会看到, 显示字符串的函数会这样写(外国人写源码往往如此):
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode,u8 len.....);
这里多了一些参数, 例如设定字体大小,还说明字符串的长度等等.
看似函数很通用, 算法很高级, 其实个人认为没必要的.
单片机编程, 可使用的字体是很少的,8,16,24,32,就那几种就足够用了.你把字体弄成是可以设定的, 实际上进入函数后, 还要增加判断字体大小的合法性, 计算字体的间隔和行距等等,要应对编程者使用不同大小字体的可能性, 反而将函数写得复杂难懂了.
另外再看len参数, C语言中字符串是以0x00为结束符的, 进入函数后只要调用strlen()就可计算出字符串的长度,因此不必要带这个参数来调用显示字符串函数的.  这也是回答了你,我为什么要用l=strlen(str)这样的语句了.
如果用通常的字符串显示函数来编程的话, 每当要显示字符串时, 就要想想,用多大的字体,别搞错了,算算字符串的长度该指定多少(缺少了灵活性)等等, 一是增加了源代码篇幅,二是也并不省心.
当然这是个人观点和习惯, 仅供参考了...
最后,感谢你节日的祝福. 本人乐见爱好单片机的同学. 交流也是快乐的.  愿你实验顺利愉快!
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:66
  • 最近打卡:2025-10-15 07:28:26

14

主题

29

回帖

430

积分

中级会员

积分
430
发表于 2025-10-4 17:09:06 | 显示全部楼层
浦江*** 发表于 2025-10-4 16:44
1, 这个LCD_DAT()和LCD_DATA()函数都是我自己定义的, 目的是简明, 前者发送8位,单字节数据, 后者是发送16 ...

非常感谢你回复,看了你的回复收获颇丰,你写函数的方式感觉非常好,显示字符位置前景后景一次搞定了,很值得借鉴和学习,横屏的命令已经找到了,当时只想搜st7789的中文资料,找了半天也没找到,最后百度直接搜“st7789”横屏命令,找到了,是0x60,已经实现横屏显示了,最后,在此向你表示感谢,
微信图片_20251004171604_2_6.jpg

点评

祝贺你,实验成功,界面很漂亮的. 这套关于显示屏的函数, 基本上是够用的了. 16点阵和24点阵的显示字符串函数, 是可实现中西文混合显示的, 直接将要显示的内容写在引号内即可, 这样源代码的可读性也是很强的.  详情 回复 发表于 2025-10-4 20:11
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2025-10-14 08:37:20

31

主题

371

回帖

4405

积分

荣誉版主

积分
4405
发表于 2025-10-4 20:11:20 | 显示全部楼层
dong*** 发表于 2025-10-4 17:09
非常感谢你回复,看了你的回复收获颇丰,你写函数的方式感觉非常好,显示字符位置前景后景一次搞定了,很 ...

祝贺你,实验成功,界面很漂亮的.
这套关于显示屏的函数, 基本上是够用的了.
16点阵和24点阵的显示字符串函数, 是可实现中西文混合显示的, 直接将要显示的内容写在引号内即可, 这样源代码的可读性也是很强的.
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:66
  • 最近打卡:2025-10-15 07:28:26

14

主题

29

回帖

430

积分

中级会员

积分
430
发表于 2025-10-6 15:08:44 | 显示全部楼层
你好版主,又要麻烦你了根据你的函数我照猫画虎显示大数字函数128*64,背景色时80透明不能正常显示,你帮我看看怎么改合适
///*===================================================================================================
//** 在单色LCD液晶显示屏显示128*64点阵数字串函数
//** 调用参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
//=====================================================================================================*/
void LCD_A128(u16 X,u16 Y, char *str,u8 Fcolor,u8 Bcolor,u8 Len)/* X(0-319) Y(0-479) */
{  
  u8 m,n,C,ZM[8];
  u16 i,j,L,Lw=0;
  L=Len;                             //strlen(str);
  for(j=0;j<L;j++)
  {
                C=str[j];                        /* 逐个显示字符串 */
    for(i=0;i<128;i++)  /* 写24行 */
    {
                        ZM[0]=ASC128[C-48][i*8];    /* 取字模码1 */
                        ZM[1]=ASC128[C-48][i*8+1];  /* 取字模码2 */
                        ZM[2]=ASC128[C-48][i*8+2];  /* 取字模码3 */
                        ZM[3]=ASC128[C-48][i*8+3];  /* 取字模码4 */
                        ZM[4]=ASC128[C-48][i*8+4];  /* 取字模码4 */
                        ZM[5]=ASC128[C-48][i*8+5];  /* 取字模码4 */
                        ZM[6]=ASC128[C-48][i*8+6];  /* 取字模码4 */
                        ZM[7]=ASC128[C-48][i*8+7];  /* 取字模码4 */
                                
                        LCD_MoveTo(X+Lw,Y+i);          /* 定位左上角 */
                        for(m=0;m<8;m++)
                                {        
                                        for(n=0;n<8;n++)
                                        {
                                                if((ZM[m] & 0x80)==0x80)
                                                        LCD_DATA(COLOR[Fcolor]);/* 字模点为1显示前景色 */
                                                else                                           /* 字模点为0显示原底色或背景色 */
                                                { if(Bcolor==80)  LCD_MoveTo(X+Lw+j*64+m*8+n,Y+i);   /* 透明显示模式: 仅地址+1定位 */
                                                         else LCD_DATA(COLOR[Bcolor]);               /* 正常显示模式:背景色 */
                                                }
                                                ZM[m]<<=1;
                                        }
                                }/* 水平16点显示完毕 */
    } Lw=Lw+64; /* 水平坐标位移 */
  }             /* 一位数字显示完毕  */
}

回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:66
  • 最近打卡:2025-10-15 07:28:26

14

主题

29

回帖

430

积分

中级会员

积分
430
发表于 2025-10-6 15:36:46 | 显示全部楼层
你好版主,我刚才发了一遍,没看见在哪里,再发一遍吧,我按你的函数照猫画虎写了一个显示128*64大的数字,其他都正常,只是背景是透明色不能正常显示,想了很长时间不知道怎么改,麻烦给我看看

程序如下;

///*===================================================================================================
//** 在单色LCD液晶显示屏显示128*64点阵数字串函数
//** 调用参数: X列Y行坐标, * str串指针, Fcolor字前景色,Bcolor字背景色,约定:色号80为透明,Len指定长度
//=====================================================================================================*/
void LCD_A128(u16 X,u16 Y, char *str,u8 Fcolor,u8 Bcolor,u8 Len)/* X(0-319) Y(0-479) */
{  
  u8 m,n,C,ZM[8];
  u16 i,j,L,Lw=0;
  L=Len;                             //strlen(str);
  for(j=0;j<L;j++)
  {
                C=str[j];                        /* 逐个显示字符串 */
    for(i=0;i<128;i++)  /* 写24行 */
    {
                        ZM[0]=ASC128[C-48][i*8];    /* 取字模码1 */
                        ZM[1]=ASC128[C-48][i*8+1];  /* 取字模码2 */
                        ZM[2]=ASC128[C-48][i*8+2];  /* 取字模码3 */
                        ZM[3]=ASC128[C-48][i*8+3];  /* 取字模码4 */
                        ZM[4]=ASC128[C-48][i*8+4];  /* 取字模码4 */
                        ZM[5]=ASC128[C-48][i*8+5];  /* 取字模码4 */
                        ZM[6]=ASC128[C-48][i*8+6];  /* 取字模码4 */
                        ZM[7]=ASC128[C-48][i*8+7];  /* 取字模码4 */
                                
                        LCD_MoveTo(X+Lw,Y+i);          /* 定位左上角 */
                        for(m=0;m<8;m++)
                                {        
                                        for(n=0;n<8;n++)
                                        {
                                                if((ZM[m] & 0x80)==0x80)
                                                        LCD_DATA(COLOR[Fcolor]);/* 字模点为1显示前景色 */
                                                else                                           /* 字模点为0显示原底色或背景色 */
                                                { if(Bcolor==80)  LCD_MoveTo(X+Lw+j*64+m*8+n,Y+i);   /* 透明显示模式: 仅地址+1定位 */
                                                         else LCD_DATA(COLOR[Bcolor]);               /* 正常显示模式:背景色 */
                                                }
                                                ZM[m]<<=1;
                                        }
                                }/* 水平16点显示完毕 */
    } Lw=Lw+64; /* 水平坐标位移 */
  }             /* 一位数字显示完毕  */
}
现在这个式子背景色80时只显示前两位,中间一个空格,第三位无法显示,

123.jpg
12.jpg

点评

未经跟踪调试, 仅粗看了一下源程序代码, 基本是无大问题. 这个函数新增了一个约定, 就是当色号为80时, 可实现背景色透明, 以适应某种需要. 根据上述图片看, 当采用80色号时, 字符的间隔变大了, 如果屏幕像素足够大的  详情 回复 发表于 2025-10-7 15:33
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2025-10-14 08:37:20

31

主题

371

回帖

4405

积分

荣誉版主

积分
4405
发表于 2025-10-7 15:33:20 | 显示全部楼层
dong*** 发表于 2025-10-6 15:36
你好版主,我刚才发了一遍,没看见在哪里,再发一遍吧,我按你的函数照猫画虎写了一个显示128*64大的数字, ...

未经跟踪调试, 仅粗看了一下源程序代码, 基本是无大问题.
这个函数新增了一个约定, 就是当色号为80时, 可实现背景色透明, 以适应某种需要.
根据上述图片看, 当采用80色号时, 字符的间隔变大了, 如果屏幕像素足够大的话, 1 2 3 也是能显示的.
现在的问题主要看来是在于红色字体部分...
你新增了一个Lw的变量, 可能是多于的.
当一个字符显示完毕后, 又执行了 Lw=Lw+64;
其实x坐标的右移动作已经包含在j变量之中了, 后面有j*64就是解决位移的.
再执行Lw=Lw+64; 再右移64点, 就使得字符间隔不变大了.
因此我估计可省去Lw变量和Lw=Lw+64;语句..
那么为什么当使用非80色号时, 显示是正常的呢? 因为不需要空移坐标, 只管显示色点,坐标地址是自动递增的,红色部分语句是不执行的. 所以显示正常.

回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:165
  • 最近打卡:2025-10-15 18:17:12

2

主题

45

回帖

773

积分

高级会员

积分
773
发表于 7 天前 | 显示全部楼层
感谢版主提供的例程,已在屠龙刀上验证成功

Screenshot_2025-10-09-19-01-59-595_com.miui.mediaviewer.jpg
Screenshot_2025-10-09-19-02-12-996_com.miui.mediaviewer.jpg
Screenshot_2025-10-09-19-02-22-306_com.miui.mediaviewer.jpg

Screenshot_2025-10-09-19-02-28-689_com.miui.mediaviewer.jpg



另,编程时左边栏确实存在两个STG32.h的情况,是因为

Main.C : #include "STC32G.h"

LCD_7789.H : #include <STC32G.h>

LCD_7789.C : #include <STC32G.h>

这三处引用的写法不同,不影响使用

回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:645
  • 最近打卡:2025-10-14 08:37:20

31

主题

371

回帖

4405

积分

荣誉版主

积分
4405
发表于 7 天前 | 显示全部楼层
ygy*** 发表于 2025-10-9 19:12
感谢版主提供的例程,已在屠龙刀上验证成功

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-16 05:55 , Processed in 0.168723 second(s), 108 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表