OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3618|回复: 3

基于STM32的简单电子书的实现

[复制链接]

80

主题

103

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
406
金钱
406
注册时间
2018-11-20
在线时间
25 小时
发表于 2019-8-21 16:08:13 | 显示全部楼层 |阅读模式
  今天玩了会液晶屏,原来显示汉字都是也取模软件区模后在液晶屏上显示,显示内容改变以后还需要重新做字模,比较麻烦。这两天有时间,参考网友资料,实现了读取汉字的内码从SD卡的GB2312点阵字库读取点阵在液晶屏上显示,字库的生成软件用的是易木雨的点阵字库生成器。能生成很多种语言的字库。做完了读取显示后,我自己又琢磨了一下,简单的实现了从SD卡中读取txt文档然后再液晶屏上显示txt内容。
  取模过程注意点阵的宽、高和字体大小的关系,宽、高是我们在液晶屏上要显示的像素大小,字体是汉字大小,如果宽、高一定,字体大小太到的话,字在液晶屏上只能显示一部分,可以在左侧的预览区看出来,如果字体在宽高像素点的范围内则可以在液晶上显示完整的字,如果不能显示完整则可以调整宽高或者字体大小。
  国标字有GB2312和GBK编码,GBK完全兼容GB2312包括内码的兼容,A而且GBK字库增加了很多字。汉字都是用的两个字节表示,第一个字节是区号,第二个字节是在区内的相对偏移位置。通过内码来获取字库内的偏移位置,偏移位置与内码和生成字库的宽高都有关系。我生成的GB2312字库是16*16个像素点显示一个汉字,那在字库内的偏移位置:

  1. offset=32* ( (H-0xa1)*94+(L-0xa1) )
复制代码

  H 表示内码的高字节,L表示内码的低字节。GB2312高字节是0xa1~0xfe表示区号,每个区有94个字节所以*94得到区的相对位置,L表示内码低字节也是从0xa1~0xfe,L-0xa1 得到的是在当前区内的偏移位置。 因为每个汉字有16*16=32个自己组成,所以最后乘以32得到在点阵字库中的偏移位置,从这个位置开始取出32个字节的点阵数据然后打点显示就可以把一个汉字显示出来了。

  获取点阵的代码如下

  1.  FATFS fs1; // 挂载SD卡的分区用

  2.   FIL f1; // SD卡中字库的文件描述符

  3.   FIL ftxt; // 要读取的txt文档的文件描述符

  4.   u8 fnGetChinese(u8 *p,u8 *buff) // 形参是要读取的汉字

  5.   {

  6.   u8 res=0;

  7.   u8 H8,L8;

  8.   UINT num;

  9.   H8=*p;

  10.   L8=*(p+1);

  11.   f_mount(&fs1,"",1); // 挂载SD卡

  12.   res=f_open(&f1,ReadPath,FA_OPEN_EXIStiNG|FA_READ); // 打开SD卡下的点阵字库

  13.   IF(res!=0) // 判断点阵字库是否打开成功

  14.   {

  15.   fnShowString(10,120,"open hzk fail",16,RED,WHITE,0);

  16.   printf("res=%x",res);

  17.   return 1;

  18.   }

  19.   else

  20.   {

  21.   fnShowString(10,120,"open ok",16,RED,WHITE,0);

  22.   }

  23.   f_lseek(&f1,32*((H8-0xa0-1)*94+(L8-0xa0-1))); // 在字库文件中做偏移取出32个字节的点阵数据

  24.   res=f_read(&f1,buff,32,&num);

  25.   f_close(&f1); // 读完后关闭点阵字库文件

  26.   f_mount(&fs1,"",NULL); // 卸载SD卡

  27.   return 0;

  28.   }
复制代码

  这个是得到汉字点阵的实现过程,得到点阵数据后就可以在液晶上打点实现汉字的显示,具体的底层驱动不再详细介绍。
  实现了在单片内显示汉字串以后,能不能读取SD卡中的txt文档中的汉字在液晶屏上显示呢?这块是我自己想的,不知道与别人的一样不一样,反正是实现了。
  首先我读取SD卡上txt文档上的一个汉字,然后用串口打印出来,发现,读到的就是汉字的内码,百度了下说windows中txt文档的显示的用GB2312的字库。既然读到直接是内码,那就好办了。汉字内码用的是两个字节,字符用的是一个字节,这个一定要注意,因为在以后显示的过程中要用。

  下面直接贴代码:

  1.  // x,y在液晶屏上的显示位置,我的液晶屏是320*240 ,竖屏显示

  2.   // color 是画笔的颜色,BkColor 是背景颜色

  3.   u8 fnShowTxt( u16 x, u16 y , u16 color ,u16 BkColor )

  4.   {

  5.   u8 res=0; // SD卡函数的返回值

  6.   u8 buff[100]={0}; // 存储从txt文档中读到的100个字节的内码

  7.   u8 bitbuff[32]={0}; // 存储从点阵字库获得的32个字节的点阵数据

  8.   u8 NeiMaH,NeiMaL; // GB2312内码的高位和低位

  9.   u8 CntnuF=1; // 用来 判断是不是读到文档的末尾了,如果读到字节的个数小于100则表示读到末尾了

  10.   u16 offset=0; // 读txt文档的偏移地址

  11.   u8 i=0;

  12.   UINT Hznum,bytenum; // 实际读回的内码字节个数、点阵字节个数

  13.   u16 x0,y0; // 点阵显示的位置

  14.   u8 charCnt=0; // 读取的100个字节内码中有几个字符,如果字符个数是偶数则下次偏移再偏移100,如果是奇数,

  15.   // 则读取的100个字节中的最后一个字节可能是下一个汉字的内码高位字节,则偏移99,下次再把这个字节读上。

  16.   x0=x;

  17.   y0=y;

  18.   f_mount(&fs1,"",1); // 挂载SD卡

  19.   res=f_open(&f1,ReadPath,FA_OPEN_EXISTING|FA_READ); // 打开字库文件

  20.   if(res!=0)

  21.   {

  22.   fnShowString(10,120,"open hzk fail",16,RED,WHITE,0);

  23.   printf("res=%x",res);

  24.   return 1;

  25.   }

  26.   res=f_open(&ftxt,TxtPath,FA_OPEN_EXISTING|FA_READ); // 打开txt文档

  27.   if(res!=0)

  28.   {

  29.   fnShowString(10,120,"open txt fail",16,RED,WHITE,0);

  30.   printf("res=%x",res);

  31.   return 1;

  32.   }

  33.   f_lseek(&ftxt,offset); // 初始化偏移为0从头开始读。

  34.   res=f_read(&ftxt,buff,100,&Hznum); // 每次读100个内码字节

  35.   while(CntnuF) // 循环判断是不是读到文件末尾了

  36.   {

  37.   for(i=0;i

  38.   {

  39.   if(x>220) // 显示位置的判断

  40.   {

  41.   x=x0;

  42.   y+=16;

  43.   }

  44.   if((y>300))

  45.   {

  46.   fnRefreshscreen(WHITE);

  47.   x=x0;

  48.   y=y0;

  49.   }

  50.   if(buff>0x80) // 是不是汉字

  51.   {

  52.   f_lseek(&f1,32*((buff-0xa0-1)*94+(buff[i+1]-0xa0-1))); // 点阵字库内的偏移

  53.   res=f_read(&f1,bitbuff,32,&bytenum);

  54.   fnShowHzk(x,y,bitbuff,color,BkColor);

  55.   x+=16;

  56.   i++; // 这个i++非常重要,因为一个汉字两个字节,除了判断语句i++,

  57.   // 这里需要还要一个

  58.   memset(bitbuff,0,sizeof(bitbuff));

  59.   }

  60.   else // 可能是标点也可能是换行符

  61.   {

  62.   if(buff==0x0D) // 换行标志

  63.   y+=16;

  64.   else

  65.   fnShowChar( x,y,buff,16,color,BkColor,0); // 字符

  66.   x+=8;

  67.   charCnt++; // 字符个数计算,用于判断下一次读txt文档的偏移地址

  68.   }

  69.   }

  70.   // 计算txt文档的偏移地址

  71.   if(Hznum!=100) // 判断是不是读到文档末尾了

  72.   {

  73.   CntnuF=0;

  74.   }

  75.   else // 没有读到末尾继续读

  76.   {

  77.   if(charCnt%2==0) // 字符个数是偶数,100个字节内码里边正好成对出现,地址偏移+100

  78.   offset +=100;

  79.   else

  80.   offset +=99;

  81.   memset(buff,0,sizeof(buff));

  82.   f_lseek(&ftxt,offset); // txt 文档地址偏移

  83.   res=f_read(&ftxt,buff,100,&Hznum); // 读内码数据

  84.   }

  85.   }

  86.   f_close(&f1); // 关闭打开的点阵字库

  87.   f_close(&ftxt); // 关闭打开的txt文档

  88.   f_mount(&fs1,"",NULL); // 卸载磁盘

  89.   return 0;

  90.   }
复制代码

  以上是简单的电子书的实现。
  因为不同的系统有不同的编码这个要注意,比如我再Windows上的汉字拷贝到CSDN网页上就是乱码,这是因为使用的汉字的编码不同,对于不同的编码格式,还需要做内码的对应转换,把其他的格式转换成GB2312或者GBK格式然后调用字库显示。
  其他常用编码格式Unicode、utf-8等的具体介绍和转换成GB编码可以百度。
  SD卡注意事项:
  对一个文件读,必须先打开文件,读完后关闭。
  对一个文件写,必须先打开文件,根据情况确定打开的权限,只读,读、写、创建等,先完后最好调用f_sync()函数,这是一个同步函数,类似于linux中的同步函数。SD卡中的写函数应该是带缓冲(猜的),在关闭之前调用这个函数将缓冲区的内容写入SD卡中,然后关闭文件,否则可能写入失败,不能将内容成功写到文件上。
  文件的打开路径,Windows中的文档可能是隐藏文件类型的,这个一定要注意,隐藏文件类型的a.txt和不隐藏文件类型的a.txt 不是同一个文件,这个一定要非常注意。

找了一些没有找到这方面配套的资料自己又不想弄就给大家分享一些32的资料供大家学习参考

stm32 如何用DMA搬运数据
http://www.makeru.com.cn/live/detail/1484.html?s=45051
( ADC读取光照传感器)
http://www.makeru.com.cn/live/1392_1004.html?s=45051
(stm32串口应用)
http://www.makeru.com.cn/live/1392_1164.html?s=45051
(stm32直流电机驱动)
http://www.makeru.com.cn/live/1392_1218.html?s=45051

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
755
金钱
755
注册时间
2018-12-7
在线时间
131 小时
发表于 2019-8-21 16:24:34 | 显示全部楼层
回复 支持 反对

使用道具 举报

8

主题

56

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
224
金钱
224
注册时间
2019-4-17
在线时间
34 小时
发表于 2020-4-30 14:06:12 | 显示全部楼层
好评   深度好评
回复 支持 反对

使用道具 举报

1

主题

37

帖子

0

精华

高级会员

Rank: 4

积分
977
金钱
977
注册时间
2019-9-1
在线时间
194 小时
发表于 2021-4-1 10:56:42 | 显示全部楼层
多谢分享 学习到了很多
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-26 03:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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