发新帖本帖赏金 10.00元(功能说明)我要提问
返回列表
[LPC]

基于S08P-Lite开发板的字库构建及使用

[复制链接]
597|2
手机看帖
扫描二维码
随时随地手机跟帖
jinglixixi|  楼主 | 2021-3-10 12:32 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2021-3-10 12:44 编辑

#申请原创#
在S08P-Lite开发板上,配置有一个4MB的W25Q32存储器,可作为字库或图库来使用,其接口电路如图1所示。
                              
1.png
图1 W25Q32接口电路


那该如何构建字库和图库呢?
方法主要有2个,一个是用数组做缓冲的中转存储;另一种是使用串行通讯来把文件中的传送给MCU来进行转存。
为了便于说明,这里以数组的形式来进行转储。
具体处理过程如下:
1. 首先将字库的内容存入数组,其形式为:
unsigned  charF8X16[]=
{         
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//sp0
         0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//!1
         0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"2
         0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//#3
         0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$4
          ...  
          0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//|92
         0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//}93
         0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~94
}
即每个字符占用16个字节,共有95个字符。


2. 编组分批转存(原因说明: 使用OLED屏分页显示(按键控制或延时处理)16*2=32   96/32=3屏)
S08P-Lite开发板所使用的MCU为MC9S08PT60,其闪存容量为60KB。
若能把该数组的全部字库存下并进行编译下载,则可以一次性完成转储。
但本人所用的CW似乎有些问题,一旦代码得到16KB,就会在下载后无法运行,故只能分为3次将将字库的内容转存到W25Q32中,即每次数组中的字符数为32个。
分批转存的程序为:
void FlashW25Q32_CREAT(void)
{
   uint8_ti,j,k;
   uint8_t deviceID;
   uint8_treturnResult;
   uint16_ttestResult = 0;
   printf("FlashW25Q32 CREAT: BEGINS\n");
   deviceID = flash_read_deviceid();
   printf("FlashW25Q32 CREAT: read device ID is 0x%x\n",deviceID);
   printf("FlashW25Q32 CREAT: erase flash sector 0\n");  // 4KB=1sector
   returnResult = flash_sector_erase(0);
   for(j=0; j<32; j++)
   {
for (i=0; i<16; i++)
     {
         u8FlashReadBuffer = 0;
         u8FlashWriteBuffer = F8X16[i+j*16];  // 数组转存
     }
     for (i=0; i<16; i++)
     {
        printf(" 0x%x", u8FlashWriteBuffer);  // 写入内容显示验证
     }
     printf("\n");
   returnResult = flash_write_sector(512+j*16, u8FlashWriteBuffer, 16);
   returnResult = flash_read_data(512+j*16, u8FlashReadBuffer, 16);
   for(i=0; i<16; i++)
   {
        printf(" 0x%x", u8FlashReadBuffer);  // 读取内容显示验证
   }
   printf("\n");
}
   printf("FlashW25Q32 CREAT: PASSED\n");
   printf("\n");
   return;
}

由于W25Q32的一个扇区为4KB,而字符库的大小为96*16=1536个字节,所以一个扇区完全可以存放下,因此除了第一次相应进行擦除外,其他2次需将擦除处理的引脚屏蔽。
编译下载后,其执行效果如图2和图3所示,其中单行数据为写入内容,双行数据为读取内容,经核实读写一致。
2.png

图2 执行效果1

3.png

图3 执行效果2


3.整体读取验证
对于分批转存来说,需要进行一次整体读取验证,若是能一次性完成转存则无需该处理。
整体读取验证的函数为:
void FlashW25Q32_Test(void)
{
   uint8_ti,j,k;
   uint8_tdeviceID;
   uint8_treturnResult;
   uint16_ttestResult = 0;
   printf("FlashW25Q32 test: BEGINS\n");
   for(k=0;k<3; k++)
   {
   for(j=0; j<32; j++)
   {
   for(i=0; i<16; i++)
   {
        printf(" 0x%x", u8FlashReadBuffer);
   }
   printf("\n");
   }
   printf("FlashW25Q32 test: PASSED\n");
   printf("\n");
   return;
}

在执行后,其运行效果如图4和图5所示。
4.png

图4 执行效果3

5.png

图5 执行效果4
(注:为了便于处理,最后一行数据为无效数据)

4.以OLED屏来显示验证
我们建立字库的目的是为了OLED屏的显示,为此需要把读取数组字库的程序转换为读取硬字库的函数。
以OLED屏来进行显示验证的函数为:
void FlashW25Q32_oled(void)
{
    uint8_t i,j,k,x,y;
   uint8_treturnResult;
   for(k=0;k<3; k++)
   {
         x=0;
         y=0;
       for (j=0; j<32; j++)
         {
       returnResult =flash_read_data(k*512+j*16, FlashReadBuffer, 16);
       OLED_ShowCharp(x,y,FlashReadBuffer,16);
        if(j==15)
        {
         y=2;
         x=0;
        }
        else
         x=x+8;  
        }
       DelayMS(2000);
   }
}

该函数的功能是从字库中依次读取字模,然后在分屏显示在OLED屏上。
(注:OLED屏每屏可显示的字符数为32,96/32=3,故字符库的内容需用3屏来显示出来。)
读取字库来显示的函数为:
void OLED_ShowCharp(uint8_t x,uint8_ty,uint8_t* chr,uint8_tChar_Size)
{
    unsignedchari=0;
    unsignedchar*c;
    c=chr;
    if(x>Max_Column-1)
    {
     x=0;
     y=y+2;
    }
    if(Char_Size==16)
    {
            OLED_Set_Pos(x,y);
            for(i=0;i<8;i++)
           OLED_WR_Byte(FlashReadBuffer,OLED_DATA);
            OLED_Set_Pos(x,y+1);
            for(i=0;i<8;i++)
           OLED_WR_Byte(FlashReadBuffer[i+8],OLED_DATA);
     }
}

分屏显示的验证效果如图6至图8所示,经审核处理正确。
6.png

图6 分屏显示效果1

7.png

图7 分屏显示效果2

8.png

图8 分屏显示效果3

5. 读字库进行显示
在分屏显示的基础上,我们再将程序改造成符合字符串显示的函数。
字符显示函数为:
void OLED_ShowCharv(uint8_t x,uint8_ty,uint8_tchr,uint8_tChar_Size)
{
    unsignedchari=0,c;
    unsignedintp;
    c=chr-' ';
    p=c*16;
     flash_read_data(p, FlashReadBuffer, 16);
     if(x>Max_Column-1)
    {
     x=0;
     y=y+2;
     }
    if(Char_Size==16)
    {
            OLED_Set_Pos(x,y);
            for(i=0;i<8;i++)
           OLED_WR_Byte(FlashReadBuffer,OLED_DATA);
            OLED_Set_Pos(x,y+1);
            for(i=0;i<8;i++)
            OLED_WR_Byte(FlashReadBuffer[i+8],OLED_DATA);
     }
}

字符串显示函数为:
void OLED_ShowStringV(uint8_t x,uint8_ty,uint8_t*chr,uint8_tChar_Size)
{
   unsignedcharj=0;
   while(chr[j]!='\0')
   {      
            OLED_ShowCharv(x,y,chr[j],Char_Size);
            x+=8;
            if(x>120)
            {
             x=0;
                y+=2;
            }
            j++;
   }
}


实现演示效果的主程序为:
void main(void)
{
   Sys_Init();
   EnableInterrupts;
   MTIM1_Init();
   LED_Init();
   LED_Test();
    PORT_PTAOE_PTAOE2= 1;     //PTA2
    PORT_PTAOE_PTAOE3= 1;     //PTA3
    FlashW25Q32_Init();
   OLED_Init();
   OLED_Clear();
    OLED_ShowStringV(0,0,"MC9S08PT60",16);
    OLED_ShowStringV(0,2,"0.91' OLED",16);
   while(1);
}


经编译下载,其运行效果如图9所示。
9.png

图9 读取字库的演示效果

有了以上的基础,我们还可以构建中文字库及图库等。

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 10.00 元 2021-03-10
理由:恭喜通过原创文章审核!请多多加油哦!

相关帖子

gyh974| | 2021-3-12 10:46 | 显示全部楼层
有完整项目文件就好了,不用看得那么辛苦

使用特权

评论回复
jinglixixi|  楼主 | 2021-3-12 11:28 | 显示全部楼层
本帖最后由 jinglixixi 于 2021-3-12 11:30 编辑
gyh974 发表于 2021-3-12 10:46
有完整项目文件就好了,不用看得那么辛苦

涉及的中间过程比较多,就发一个最后面的吧。

W25Q32.zip

284.62 KB

使用特权

评论回复
发新帖 本帖赏金 10.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

446

主题

2675

帖子

36

粉丝