深圳市航顺芯片技术研发有限公司
直播中

淡淡的爱

11年用户 884经验值
私信 关注
[问答]

有什么方法可以在TFT LCD屏幕上显示字符呢

在TFT LCD屏幕上显示字符的前提条件有哪些呢?
有什么方法可以在TFT LCD屏幕上显示字符呢?

回帖(1)

黄伟

2021-11-5 12:02:02
  在屏幕上显示字符我之前就在做好了,之前只是可以显示。这两天把显示部分做了些修改。
  修改如下
  1.加了换行
  2.字体大小大小的适应,如果以后换了字体简单修改后就可以用了
  3.显示内容过多时自动换行
  4.字距 行距的控制
  5.加入了个显示控制结构体,方便做参数修改,
  6.增加了print参数的单独配置函数
  先声明
  开发板 德飞莱STM32系列尼莫M3S
  1.TFTLCD屏幕的配置是引用开发板的汉字显示程序
  2.串口指令是参照“C语言中文网中的51单片机教程”
  3.flash SPI也是借鉴开发板程序做了大量修改来符合自己的程序。。
  在屏幕上显示字符的前提
  1.最重要的当然是要有TFTLCD屏幕啦并且配置好参数,还有有个LCD显存地址设置函数 还有窗口设置函数
  2.还有就是字库了,一般使用点阵字库,网上有字库生成工具,
  3.把字库写到flash芯片。
  4flash 要有个 读取指定个数的函数,
  下面看代码
  在这里插入代码片
  #include “text.h”
  extern struct
  { u16 backC; ///底色
  u16 pen; ///画笔颜色
  }LCD_Colour;
  InitLcdPrintTypedef PrintInit;
  uint32_t CN_PYL;
  uint32_t CH_PYL;
  /*--------------------print参数初始化--------------------*/
  void InitPrint(){
  PrintInit.backC = LCD_Colour.backC; ; //底色
  PrintInit.pen = LCD_Colour.pen; //字体颜色颜色
  PrintInit.Print_X = 1; //起始打印位置 X方向
  PrintInit.Print_Y = 2; //起始打印位置 Y方向
  PrintInit.size_H = 32; //字体大小 高度
  PrintInit.size_L = 32; //字体大小 宽度
  PrintInit.Word_Spacing = 1; //字距
  PrintInit.Line_Spacing = 1; //行距
  PrintInit.Word_Wrap = 1; //自动换行
  //计数中文字符要读取的点阵字节数
  CN_PYL = ((uint32_t)PrintInit.size_H * (uint32_t)PrintInit.size_L)/8;
  //计数英文字符要读取的点阵字节数
  CH_PYL = ((uint32_t)PrintInit.size_H * (uint32_t)PrintInit.size_L)/16;
  }
  /*--------------------print字体颜色配置--------------------*/
  void ConfigPrintColour(uint16_t Print_backC, uint16_t Print_pen) {
  PrintInit.backC = Print_backC;
  PrintInit.pen = Print_pen;
  }
  /*--------------------print起始打印位置--------------------*/
  void ConfigPrintSite(uint16_t Print_X, uint16_t Print_Y) {
  PrintInit.Print_X = Print_X;
  PrintInit.Print_Y = Print_Y;
  }
  /*--------------------print字体大小配置--------------------*/
  void ConfigPrintSize(uint8_t size_H, uint8_t size_L) {
  PrintInit.size_H = size_H;
  PrintInit.size_L = size_L;
  CN_PYL = ((uint32_t)PrintInit.size_H * (uint32_t)PrintInit.size_L) / 8;
  CH_PYL = ((uint32_t)PrintInit.size_H * (uint32_t)PrintInit.size_L) / 16;
  }
  /*--------------------print行距字距配置--------------------*/
  void ConfigPrintSpacing(uint8_t Word_Spacing, uint8_t Line_Spacing) {
  PrintInit.Word_Spacing = Word_Spacing;
  PrintInit.Line_Spacing = Line_Spacing;
  }
  /*--------------------print自动换行配置--------------------*/
  void ConfigPrintWord_Wrap(uint8_t Word_Wrap) {
  PrintInit.Word_Wrap = Word_Wrap;
  }
  /*--------------------打印字体点阵--------------------*/
  void LCD_CharDot(uint8_t *dot, uint8_t c) {
  uint8_t p = 0x01; //像素点控制,
  KS_GRAM; //LCD RAM入口
  /*汉字打印*/
  if (c 》 1) {
  p = 0x80; //这与点阵字体的存储方式有关
  //打印点阵行控制
  for (uint8_t i = PrintInit.size_H; i 》 0; i--) {
  //打印点阵列控制
  for(uint8_t j = PrintInit.size_L / 8; j 》 0; j--){
  while (p) {
  if(*dot&p)
  W_GRAM = PrintInit.pen; //字体打印
  else
  W_GRAM = PrintInit.backC; //底色打印
  p = p 》》 1;
  }
  p = 0x80;
  dot++;
  }
  }
  }
  /*英文打印*/
  else {
  for (uint8_t i = PrintInit.size_H; i 》 0; i--) {
  for(uint8_t j = PrintInit.size_L / 16; j 》 0; j--){
  while (p) {
  if(*dot&p)
  W_GRAM = PrintInit.pen; //字体打印
  else
  W_GRAM = PrintInit.backC; //底色打印
  p = p 《《 1;
  }
  p = 0x01;
  dot++;
  }
  }
  }
  }
  /*-----------------在LCD屏上打印字符串-----------------*/
  void LCD_print(uint8_t *string) {
  uint8_t dot[128]; //临时存储 用来存储从Flash中读出的字符点阵数据
  uint8_t GBK_H, GBK_L; //GBK编码 高字节 和低字节
  uint32_t GBK; //字符点阵在flash中的地址
  uint16_t x = PrintInit.Print_X; //字符打印位置控制 X方向
  uint16_t y = PrintInit.Print_Y; //字符打印位置控制 Y方向
  while (*string!=‘’) {
  GBK_H = *string;
  if(*string==‘n’){
  x = PrintInit.Print_X; y = y + (PrintInit.Line_Spacing + PrintInit.size_H) - 1;
  }
  else{
  /*汉字*/
  if (GBK_H 》 0x80) {
  GBK_L = *(++string);
  GBK_H -= 0x81;
  if (GBK_L 》 0x7f)
  GBK_L -= 0x41;
  else
  GBK_L -= 0x40;
  //计算所打印的字符在Flash字库存储的位置
  GBK = ((uint32_t)190 * GBK_H + GBK_L) * CN_PYL+ (uint32_t)CH_PYL * 96 ;
  //从Flash字库中读取字符点阵存放到dot数组中
  FLASH_Read_Data(dot, GBK, CN_PYL);
  //设置打印窗口
  LCD_Window(x, x + PrintInit.size_L - 1, y, y + PrintInit.size_H - 1);
  LCD_X_Y(x, y); //设置打印起始地址
  LCD_CharDot(dot, 2); //打印字符
  //调整字距字距
  x = x + (PrintInit.size_L - 1 + PrintInit.Word_Spacing);
  //检测本行是否无法显示所有内容,判断是否要自动换
  if ((239 - x 《 PrintInit.size_L || x 》= 239) && PrintInit.Word_Wrap) { 行
  x = PrintInit.Print_X; y = y + (PrintInit.Line_Spacing + PrintInit.size_H) - 1;
  }
  }
  /*英文*/
  else {
  /*---------ASCII码一共有128个可以显示出来的只有96个字库里也只有这96个--------*/
  GBK = (GBK_H-0x20)* CH_PYL; //计算所打印的字符在Flash字库存储的位置
  FLASH_Read_Data(dot, GBK, CH_PYL);
  //ASCII码一共有128个可以显示出来的只有96个字库里也只有这96个
  LCD_Window(x, x + PrintInit.size_L / 2 - 1, y, y + PrintInit.size_H -1);
  LCD_X_Y(x, y);
  LCD_CharDot(dot, 1);
  x = x + (PrintInit.size_L / 2 + PrintInit.Word_Spacing)-1;
  if ((239 - x 《 (PrintInit.size_L/2) || x 》= 239) && PrintInit.Word_Wrap) {
  x = PrintInit.Print_X; y = y + (PrintInit.Line_Spacing + PrintInit.size_H) - 1;
  }
  }
  }
  string++;
  }
  }
  }
  }
  下面是头文件
  #ifndef __TEXT_H
  #define __TEXT_H
  #include “stm32f10x.h”
  #include “tft.h”
  #include “usart.h”
  typedef struct
  {
  uint16_t backC; //底色
  uint16_t pen; //字体颜色颜色
  uint16_t Print_X; //起始打印位置 X方向
  uint16_t Print_Y; //起始打印位置 Y方向
  uint8_t size_H; //字体大小 高度
  uint8_t size_L; //字体大小 宽度
  uint8_t Word_Spacing; //字距
  uint8_t Line_Spacing; //行距
  uint8_t Word_Wrap; //自动换行
  }InitLcdPrintTypedef;
  void InitPrint(); //print参数初始化
  void ConfigPrintColour(uint16_t backC, uint16_t pen); //print字体颜色配置
  void ConfigPrintSite(uint16_t Print_X, uint16_t Print_Y); //print起始打印位置
  void ConfigPrintSize(uint8_t size_H, uint8_t size_L); //print字体大小配置
  void ConfigPrintSpacing(uint8_t Word_Spacing, uint8_t Line_Spacing); //print行距字距配置
  void ConfigPrintWord_Wrap(uint8_t Word_Wrap); //print自动换行配置 1:自动换行 0:不自动换行
  void LCD_CharDot(uint8_t *dot, uint8_t c); //打印字体点阵
  void LCD_print(uint8_t *string); //在LCD屏上打印字符串
  #endif
  下面开始代码讲解
  为了以后方便使用我写了5个print配置函数,因为有的时候不一定全部参数都会配置,所以做了单独配置的函数。
  GBK字库地址的计算:
  GBK汉字的编码方式
  第一个字节为 0x81~0xFE 称为汉字的区码
  第二字节为两部分 1:0x40~0x7E 2:0x80~0xFE 称为汉字的位码 这就是汉字的区位码
  接下来就是怎么把区位码转换成我们下载到Flash中字库的地址,首先我们要弄清楚几个问题
  1.一个汉字的点阵集是多少个字节,如 3232的汉字 3232/8=128字节 英文的话 16*32/8=64字节
  2.字库的点阵集是连续下载到Flash里的(我的字库ASCII和GBK是连着的,我先下载的ASCII接着下载GBK)
  3.ASCII可以在屏幕上显示的只有96个字符
  先判断第一个字节 若小于等于0x80,则编码为ASCII,说明是英文字符 英文字符因为前面32个是控制字符所以 ASCII字库的起始编码为0x20
  uint32_t CH_PYL; //英文字符要读取的点阵字节数
  uint32_t GBK; //字符点阵在flash中的地址
  uint8_t GBK_H, GBK_L; //GBK编码 高字节 和低字节
  uint8_t *string //要显示的字符
  GBK_H = *string;
  if (GBK_H 《=0x80)
  GBK = (GBK_H-0x20)* CH_PYL;
  若第一个字节大于0x80说明编码为GBK第一个字节和第二个字节组成区位码
  第一个字节减去0x81就是我们字库的正确区码
  然后判断第二个字节 如果小于0x7f则减去0x40,如大于0x7f则减去0x41。
  uint32_t CH_PYL; //英文字符要读取的点阵字节数
  uint32_t GBK; //字符点阵在flash中的地址
  uint8_t GBK_H, GBK_L; //GBK编码 高字节 和低字节
  uint8_t *string //要显示的字符
  GBK_H = *string; //第一个字节
  if (GBK_H 》 0x80) {
  GBK_L = *(++string); //第二个字节
  GBK_H -= 0x81;
  if (GBK_L 》 0x7f)
  GBK_L -= 0x41;
  else
  GBK_L -= 0x40;
  GBK = ((uint32_t)190 * GBK_H + GBK_L) * CN_PYL+ (uint32_t)CH_PYL * 96 ; //计算所打印的字符在Flash字库存储的位置
  为什么高位要*190:因为GBK一个区有190个位,为什么减去0x41:因为0x400x7E与0x800xFE空了个0x7f,+ (uint32_t)CH_PYL * 96是为什么:因为GBK字库紧随ASCII其后,ascii在flash的起始地址为0x00
  最后
  我认为这次汉字显示中有难度的是:
  1.怎么把字库下载到flash中 下载ASCII时没问题 但下GBK时非常容易中断,32*32的GBK字库文件有3MB大
  2.字库区位码转换成flash中的地址,我在网上看了好多资料。
  3.这只是我的笔记。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分