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

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

[复制链接]
  • 打卡等级:以坛为家III
  • 打卡总天数:666
  • 最近打卡:2025-11-09 08:24:34

31

主题

377

回帖

4521

积分

荣誉版主

积分
4521
发表于 昨天 11:44 | 显示全部楼层
ygy*** 发表于 2025-11-7 22:06
谢谢浦版,sprintf确实挺好用,不过,在使用中发现,因为我不知道输出的数组的准确长度,LCD_A24((i-2)*60, ...

楼上这位朋友你好!
看了上面实验的源代码和你提出的问题, 有几点交流供参考...

1, 数组的长度在数组的定义时已经明确了, 也可以根据数据类型计算出长度是多少字节的.
   例如,你定义了数组:
unsigned cancode[4][6]={ ...... };

这里有一点小问题, 就是没有说明数据类型, 编译器默认它是无符号整型数了,严谨一点应该要说明:
unsigned int cancode[4][6]={ ...... };

这是可以用sizeof(cancode)函数来计算出它的长度的, 应该是4*6*2=48字节.(每一个数据占两字节,一共24个数据)

2,注意和理解 LCD_A24()和LCD_H24()这两个函数的区别:
  这两个函数是自创编写的,有不同的含义和用法,以适应不同的需要.
  LCD_A24()是显示纯西文字符串的函数, 入口参数中有指定长度(可强制指定长度),
  LCD_H24()是显示中西文混合字符串的函数, 入口参数中无指定长度, 内部有strlen()计算长度函数自动计算.所以不需要指定显示长度.
  为什么 LCD_A24((i-2)*60,80,buffer,15,1,12);会出错呢?
  因为你指定它显示长度是12, 其实前面有一句:
  sprintf(buffer,"0x%02x",cancode[0]);
这就说明buffer这字符串长度是4, 你却让它强制显示12字节,它就只好显示乱码点阵了.
  为什么你说用LCD_H24((i-2)*60,102,buffer,15,1); 就显示是正确的呢?
  (在标准C语言中,字符串是以0x00结尾的,虽然有时与字符数组可转换通用,但还是要注意有所区别.)
  因为buffer这字符串是以0x00结束的,进入LCD_H24()以后, 有strlen()函数自动计算长度,所以显示正确.

3, 写这样的语句 LCD_A24((i-2)*60,80,buffer,15,1,12);还是有一点点小问题的.
   那个x坐标参数(i-2)有可能出现负值,这是要尽量避免的,
   尽管你在程序中用if(i<1)和(i>1)分开处理,用以避免出现负值, 但如果当i==1时呢,就啥也不执行了吗?

4, 上面实验程序, 如果目的是为了用16进制格式显示所定义的数组的话,那么是可以稍稍修改一下的,
   这段显示程序代码可以放在while(1)之前, 不必要反复循环不断地显示.

  我试着来编写一下(没上机仿真运行),供你参考, 可试试看...

  前面增加两个全局变量: (便于跟踪观察)
  unsigned int Row,Col;                           //行列计数器

  在main函数中...
  ...
  LCD_Init();
  LCD_CLS(1);                                      //蓝色清屏

  for(Row=0;Row<4;Row++)                           //循环显示4行
  { for(Col=0;Col<6;Col++)                         //循环显示6列
    { sprintf(buffer,"0x%02X",cancode[Row][Col]);  //格式化显示数据
      LCD_H16(Col*50,Row*24,buffer,15,1);          //每列间隔50像素,每行间隔24像素(限于屏幕像素改用LCD_H16,原理相同)
    }
  }
  while(1)
  {  }

5, 关于数组的定义
   源程序是这样的:
   unsigned cancode[4][6]=
   {
     {0x5f0,4,0xe4,0xff,0x00,0x00},
     {0x5f0,4,0x00,0x00,0x00,0x00},
     {0x3c0,4,0xa0,0xa0,0x03,0x00},
     {0x3c0,4,0x00,0x00,0x00,0x00},
   };
   虽然没有什么错误,但给人感觉是概念有点模糊了.
   一般而言,一个数组中的每个成员,数据类型应该是相同的. (并不是结构定义)
   在定义数组的同时赋值也是可以的, 如果前面不说明类型,编译器只好根据具体数据来默认了.
   因为cancode[0][0]=0x5F0, 这个数据超出了1字节的范围(0--255)了,因此编译器默认所有数据都是两字节无符号整型数,其取值范围是0...65535. sizeof(cancode[0][0])应该是2. 因此后面的4, 实际是0x0004, 占两字节空间. 0xe4实际是0x00E4,都是占两字节空间的....
   整个数组占用48字节空间.
   然而,在后面的语句中,有sprintf(buffer,"0x%02x",cancode[0]);
   这又表明是单字节显示,又让人感觉前面的定义有点浪费空间了.
   虽然0x5F0按单字节也能显示,这是sprintf()函数能容忍,但是突破了格式,且前导零也没有了.

   如果cancode(顾名思义是CAN指令串)数组有其特定用途, 那么是可以这样定义的:

   unsigned char cancode[4][7]=
   {
     { 0x05,0xF0,0x04,0xE4,0xFF,0x00,0x00 },
     { 0x05,0xF0,0x04,0x00,0x00,0x00,0x00 },
     { 0x03,0xC0,0x04,0xA0,0xA0,0x03,0x00 },
     { 0x03,0xC0,0x04,0x00,0x00,0x00,0x00 },
   };
   这样整个数组只占28字节空间. (个人习惯,除0x中的x是小写外,后面都是用大写)
   
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:666
  • 最近打卡:2025-11-09 08:24:34

31

主题

377

回帖

4521

积分

荣誉版主

积分
4521
发表于 昨天 14:48 | 显示全部楼层
谢谢ygyfy坛友的鲜花鼓励.
祝实验顺利愉快!
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:186
  • 最近打卡:2025-11-08 12:18:48

2

主题

48

回帖

867

积分

高级会员

积分
867
发表于 昨天 15:03 | 显示全部楼层
感谢浦版的回复!针对你说的几点,分别说明下:1,这个数组的数据类型原来是uint(写的程序里加了stc.h文件,里面声明了uint,为简单点表示问题不添加别的文件写上了unsigned没注意丢了int),不过这不是我显示乱码的问题;
2,我知道这两个函数是不一样的,因为我用 LCD_A24()一开始搞不清长度应该是多少,数据后面显示乱码(这程序里我要显示的一个数据四个字节我知道,因为我显示四个数据,我以为是16其实应该是4,从12尝试到20都不对)。意外发现LCD_H24()能显示。
我按照LCD_H24()的格式修改下LCD_A24()define函数,不知道对不对,但是能正常显示:

7789.h里
void LCD_A24(unsigned int X,unsigned int Y,char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len); /* 24点阵西文字符串显示 */
改为:
void LCD_A24(unsigned int X,unsigned int Y,char *str,unsigned char Fcolor,unsigned char Bcolor); /* 24点阵西文字符串显示 */

7789.c里
void LCD_A24(unsigned int X,unsigned int Y, char *str,unsigned char Fcolor,unsigned char Bcolor,unsigned char Len)
{  /* X(0-319) Y(0-479) */
  unsigned char n,C;
  unsigned int i,j,L,Lw=0,ZM;
  L=Len;  
改为:
void LCD_A24(unsigned int X,unsigned int Y, char *str,unsigned char Fcolor,unsigned char Bcolor)
{  /* X(0-319) Y(0-479) */
  unsigned char n,C;
  unsigned int i,j,L,Lw=0,ZM;
  L=strlen(str);  

3,当i==1时确实不执行什么,主要是我这个数据,这里都是4(4个数据的意思,明知道的,不需要显示它)

4,这个代码太好用了,显示完全没问题!

5,这个数组是老大众cd机用的数据,每一行第一个数据是can帧id,就是5f0这样,用自制的逻辑分析仪观察和在机子上使用是没问题的,其实是好几组,这只是一部分,因为开始没解决显示hex代码的问题,所以从最少的数据开始实验,这也就是我一开始问的是数组的A[0][0]里面是05f0,我这显示出来是它的十进制1520这个问题的原因。


不知浦版能将屠龙刀板中36-USB-CDC转2组CAN的数据显示到lcd屏幕上吗?

点评

感谢你在本帖的参与回复. 再补充聊聊... 1, 将 LCD_A24()函数减少一个入口参数Len, 如你所改,是完全可以,没有问题的. 相当于LCD_H24()中处理西文部分, 在显示西文字符和数据时,更简单且高效. 只是建议你记得, 这  详情 回复 发表于 昨天 20:19
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:666
  • 最近打卡:2025-11-09 08:24:34

31

主题

377

回帖

4521

积分

荣誉版主

积分
4521
发表于 昨天 20:19 | 显示全部楼层
ygy*** 发表于 2025-11-8 15:03
感谢浦版的回复!针对你说的几点,分别说明下:1,这个数组的数据类型原来是uint(写的程序里加了stc.h文件 ...

感谢你在本帖的参与回复.
再补充聊聊...

1, 将 LCD_A24()函数减少一个入口参数Len, 如你所改,是完全可以,没有问题的. 相当于LCD_H24()中处理西文部分, 在显示西文字符和数据时,更简单且高效.
   只是建议你记得, 这里曾有这么一个带Len参数的LCD_A24()这样写法,其实在实际项目中是有一定用意的. 比如某一个经计算的变量在经过sprintf()格式化后,有可能超出原设想的长度,有可能破坏界面布局. 此时用带Len参数的函数就可强制定宽.

2, 关于屠龙刀板中36-USB-CDC转2组CAN的转发数据, 参照本话题的实例方法, 将CAN报文的缓存16字节,显示在LCD屏幕上, 原理是相同的, 应该是没什么问题吧.
   只是具体编程时, 要结合实际屏幕大小, 考虑字体大小和布局, 比如16字节分两行, 每行显示8个字节, 写好每一字节坐标定位算法, 完成一个合理的界面设计. 显示函数可以放在例如 CDC1_SendData(pdat, 16); 之后即可.
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-11-9 11:28 , Processed in 0.106541 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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