一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 11838|回复: 12
收起左侧

使用51单片机写spi flash w25x16做中文字库,

[复制链接]
发表于 2013-8-18 13:52 | 显示全部楼层 |阅读模式
前段时间对gb2312和gbk字库严重感兴趣!于是折腾了下!程序已经可以正常写入字库了,使用串口调试助手发送文件功能发送给单片机在写入spi flash ,缺点是由于使用的是采用串口同步写入spi flash 所以受限于flash的速度限制写入速度非常慢,在1T单片机 11.0592M 串口12分频 时只能使用2400波特率通讯,一个GBK字库766080字节写入需要53分钟写完后的读就速度很快在51下可以不在乎延时,不过时间不在乎的话写入效果还是可以的!这个程序只是初步的实现字库写入后期将继续优化写入速度,当然会使用异步写入了,硬件方面使用2.8寸LCD ssd1297作为显示可以指示写入状态,spi flash 使用的是华邦的w25x16 2MB的,单片机stc 1T 的随便一个就可以了,程序编译后code 2809字节,
1.jpeg   

写入中,,,,,,,,,,,,,,,


2.jpeg

写入完成,,,,,,

3.jpg   

验证写入的数据OK

串口软件使用串口调试助手,程序是使用的KEIL 3 编译,spi_flash_1下载到单片机是下载字库的,spi_flash_2下载到单片机是将单片机的GBK字库上传到电脑的,
这个是程序,
spi_flash_1.rar (134.54 KB, 下载次数: 223, 售价: 1 人民币)
spi_flash_2.rar (135.32 KB, 下载次数: 131, 售价: 1 人民币)
串口调试助手V2.2.rar (113.88 KB, 下载次数: 404)
中文字库.rar (545.42 KB, 下载次数: 1128)
字库文件请大家注意了,如果使用在产品上还是使用专用的字库文件,否则会有版权问题的!

懒得写过程了大家去这看吧!
http://www.armdiy.cn/forum.php?mod=viewthread&tid=125&page=1&extra=#pid237

评分

参与人数 1一乐金币 +5 收起 理由
wzhy154957 + 5 很给力!

查看全部评分

发表于 2013-8-18 13:56 | 显示全部楼层
呵呵,刚好正在研究这个,太及时了。
发表于 2013-8-18 14:05 | 显示全部楼层
这杜邦线,连得密密麻麻的。
发表于 2013-8-18 14:30 | 显示全部楼层
一直想学习这方面的知识,太好了。玩路由时还留下不少2M、4M和8M的spi flash
发表于 2013-8-18 19:34 | 显示全部楼层
楼主可否共享些,51 读写 SPI FLASH的例程? 是否可以把它来存放中文字库
读写IIC的多,但是EEPROM的空间一般不大,而SPI FLASH常见的就有1M2M8M等了,存放中文字库就轻松多了.
看不懂时序图..
 楼主| 发表于 2013-8-18 20:11 | 显示全部楼层
两个程序差不多!spi_flash_2是读取spi flash 的例子!将flash的GBK的766080个数据读出来然后发送到电脑串口,w25x16读取数据非常方便简单,可以任意地址任意个字节直接读取,就是写入麻烦些!要注意页还有写入时间控制,也是可以任意地址字节写入的
发表于 2013-8-18 21:30 来自手机 | 显示全部楼层
我来一乐了,那个网站我没法发言……
如果有一个汉字,比如,0xA5C0,我怎么计算出来字模所在的首地址……
头一次搞字库,废话多了点,麻烦楼主多多解释了
发表于 2013-8-19 20:35 | 显示全部楼层
楼主的资料不错,看了下,
读写SPI FLASH才这么几行代码.
楼主的论坛上下东西要金钱啊..
发表于 2013-8-19 20:35 | 显示全部楼层
楼主的资料不错,看了下,
读写SPI FLASH才这么几行代码.
楼主的论坛上下东西要金钱啊..
 楼主| 发表于 2013-8-19 21:04 | 显示全部楼层
wangke2010 发表于 2013-8-18 21:30
我来一乐了,那个网站我没法发言……
如果有一个汉字,比如,0xA5C0,我怎么计算出来字模所在的首地址……
...

汉字在液晶上的显示原理与前面显示字符的是一样的。汉字在液晶上的显示其实就是一些点的显示与不显示,这就相当于我们的笔一样,有笔经过的地方就画出来,没经过的地方就不画。所以要显示汉字,我们首先要知道汉字的点阵数据,这些数据可以由专门的软件来生成。只要知道了一个汉字点阵的生成方法,那么我们在程序里面就可以把这个点阵数据解析成一个汉字。
知道显示了一个汉字,就可以推及整个汉字库了。汉字在电脑里面存储不是以点阵数据的形式存储的(否则那占用的空间就太大了),而是以内码的形式存储的,就是GB2312/GBK等这几种的一种(最常用的是哪个我也不清楚,但是可以肯定是我们装的简体XP,汉字一般都能用GBK码或GB2312码解析),每个汉字对应着一个内码,在知道了内码之后再去字库里面查找这个汉字的点阵数据,然后在液晶上显示出来。这个过程我们是看不到,但是计算机是要去执行的。
单片机要显示汉字也与此类似:汉字内码(GBK/GB2312)->查找点阵库->解析->显示。
所以只要我们有了整个汉字库的点阵,就可以把电脑上的文本信息在单片机上显示出来了。这里我们要解决的最大问题就是制作一个与汉字内码对的上号的汉字点阵库。而且要方便单片机的查找。每个GBK码由2个字节组成,第一个字节为0X81~0XFE,第二个字节分为两部分,一是0X40~0X7E,二是0X80~0XFE。其中与GB2312相同的区域,字完全相同。
我们把第一个字节代表的意义称为区,那么GBK里面总共有126个区(0XFE-0X81+1),每个区内有190个汉字(0XFE-0X80+0X7E-0X40+2),总共就有126*190=23940个汉字。我们的点阵库只要按照这个编码规则从0X8140开始,逐一建立,每个区的点阵大小为每个汉字所用的字节数*190。这样,我们就可以得到在这个字库里面定位汉字的方法:
在stm32中可以这样调用
当GBKL<0X7F时:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2);
当GBKL>0X80时:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2);
其中GBKH、GBKL分别代表GBK的第一个字节和第二个字节(也就是高位和低位),size*2代表汉字字体的大小 比如16*16点阵的字体则为16*2=32 个字节,Hp则为对应汉字点阵数据在字库里面的起始地址。
这样我们只要得到了汉字的GBK码,就可以显示这个汉字了。从而实现汉字在液晶上的显示。
不过在51中只支持8位乘法,且乘法结果不允许超过16位,所以在计算地址的时候可以使用循环加法实现乘法用来计算偏移地址!
以下为我之前写的2.8彩屏中读写SPI FLASH 调用中文字库作为汉字显示的程序,可以正常调用显示,大家可以参考下!

unsigned char data flashGB_16[32];
unsigned char X1,Y1;

void Read_test(unsigned long temp) //从指定地址读SPI_flash数据i个并保存到数据缓存区
{
unsigned char i;
SPI_SCK=1;
SPI_CS=0;       //使能器件
SPI_WriteByte(0x03);         //写读FLASH命令
SPI_Write_add(temp);  //写flash地址
for(i=0;i<255;i++)    //读数据
{   
  flashGB_16=SPI_ReadByte();
}
SPI_CS=1;
}
void Display_hzk1(u8 hz_h,u8 hz_l, uint16 color,uint16 backcolor)//hz_h中文字符高8位 hz_l低8位  color 字体的颜色  backcolor 背景颜色
{
u8 i, j,k,msk;
unsigned long temp32,temp16;
temp32=0;
temp16=0;
if(hz_l<0x7f) temp16=(hz_h-0x81)*190+hz_l-0X40;
  else if(hz_l>0x80) temp16=(hz_h-0x81)*190+hz_l-0X41;
for(k=0;k<32;k++)  
{
  temp32+=temp16;
}
SPI_Write_en();
Read_test(temp32);               
for(i = 0;i < 16;i++)              //字模大小 16*16
{
  msk = flashGB_16[i*2];          //codeGB_16[temp] 当前字符数据组位置  Msk联合体数据i指向组中位置  
  for(j = 0;j < 8;j++)  
  {        
   if((msk & 0x80)) Point(X1 + j, Y1 + i, color);       //如果最高位为1则写入字符颜色形成字符
   else if(backcolor) Point(X1 + j, Y1 + i, backcolor);    //如果最高位为0则写入底色形成空白区域
   msk <<= 1;                //移位一次,依次写入一行8个点数据
  }
  msk = flashGB_16[i*2+1];   
  for(j = 0;j < 8;j++)   
  {        
   if((msk & 0x80)) Point(X1 + 8+j, Y1 + i, color);   
   else if(backcolor) Point(X1 + 8+j, Y1 + i, backcolor);
   msk <<= 1;            
  }
}

X1 += 16;
if(X1 == 240)
{
  Y1 += 16;
  X1 = 0;
  if(Y1 == 240)
   Y1 = 0;
}
}  
   
void display_hz(u8 *buf, u8 x, u8 y, uint16 color, uint16 backcolor)
{
u8 temp_h=0;
u8 temp_l=1;
X1 = x;
Y1 = y;
    while (buf[temp_h])
    {
        Display_hzk1(buf[temp_h],buf[temp_l] ,color, backcolor);
        temp_h +=2;
  temp_l=temp_h+1;
    }
}
void main ()
{
LCD初始化...
用户程序...
display_16x16hzs("中文显示测试!!!",40, 100,0xf800,  0x3f00);//字符,X坐标,Y坐标,字颜色,背景颜色
用户程序...
}

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-19 21:28 , Processed in 0.059633 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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