本帖最后由 jinglixixi 于 2021-3-10 12:44 编辑
#申请原创# 在S08P-Lite开发板上,配置有一个4MB的W25Q32存储器,可作为字库或图库来使用,其接口电路如图1所示。 图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 执行效果1
图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 执行效果3
图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 分屏显示效果1
图7 分屏显示效果2
图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 读取字库的演示效果
有了以上的基础,我们还可以构建中文字库及图库等。 |