链接:https://pan.baidu.com/s/1X9x-o6dDWBLpN-aTaMK-lg
提取码:nyfo
文件自取
cc936.c里有两个87k的巨大数组,也就是GBK与Unicode的转换表,通过查表就可以得到转换之后的编码,但是由于数组太大了,每次下载程序都要多花一些时间,有些单片机甚至无法同时使用两个转换表。所以把两个转换表存到外部flash里就十分快乐了。
首先从文件系统fatfs里得到cc936.c,然后把这个c文件添加到自己的工程,再创建一个头文件cc936.h(其实不创建也可以),再把其中一个数组注释掉,修改ff_convert函数,还有另外一个函数我直接删掉了,然后再添加一个把数组写入flash的函数,就可以了。
cc936.h
#ifndef __CC936_H_
#define __CC936_H_
#include <stdio.h>
#include "flash.h"
#include <string.h>
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
void test(void);
#endif
由于这里stm32没办法同时装下两个数组,所以分开存储了
首先是Unicode-GBK的cc936.c,把uni2oem数组注释掉,然后修改添加以下代码,再调用test函数就OK了。
#define FONT_LIB_SIZE 87172
WCHAR ff_convert ( /* Converted code, 0 means conversion error */
WCHAR chr, /* Character code to be converted */
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
)
{
const WCHAR *p;
WCHAR c;
uint8_t temp[2];
int i, n, li, hi;
int temp_addr;
if (chr < 0x80) { /* ASCII */
c = chr;
} else {
if (dir) { /* OEM code to unicode */
temp_addr = FONT_LIB_CC936_OEM2UNI_ADDR;
hi = FONT_LIB_SIZE / 4 - 1;
} else { /* Unicode to OEM code */
temp_addr = FONT_LIB_CC936_UNI2OEM_ADDR;
hi = FONT_LIB_SIZE / 4 - 1;
}
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
SPI_Flash_Read(temp, temp_addr + i*4, 2);
if (chr == (temp[1]<<8 | temp[0])) break;
if (chr > (temp[1]<<8 | temp[0]))
li = i;
else
hi = i;
}
SPI_Flash_Read(temp, temp_addr + i*4 + 2, 2);
c = n ? (temp[1]<<8 | temp[0]) : 0;
}
return c;
}
char temparray[4096];
void test(void)
{
//printf("sizeof uni2oem = %d\r\n", sizeof uni2oem);
printf("sizeof oem2uni = %d\r\n", sizeof oem2uni);
int i = 0;
int j = 0;
for(i = 0; i < sizeof(oem2uni)/4096 + 1; i++)
{
SPI_Flash_Erase_Sector(FONT_LIB_CC936_OEM2UNI_ADDR / 4096 + i);
}
int offset = 0;
int temp_addr = FONT_LIB_CC936_OEM2UNI_ADDR;
for(j = 0; j < sizeof(oem2uni)/4096; j++)
{
memcpy(temparray, oem2uni + offset/2, sizeof(temparray));
SPI_Flash_Write((u8 *)temparray, temp_addr + offset, sizeof(temparray));
offset += sizeof(temparray);
printf("write %d byte\r\n", offset);
}
for(i = 0, j = offset; j < sizeof(oem2uni); j+=2, i+=2)
{
temparray[i + 1] = (oem2uni[(j) / 2] >> 8) & 0xff;
temparray[i] = oem2uni[(j) / 2] & 0xff;
}
SPI_Flash_Write((u8 *)temparray, temp_addr + offset, i);
offset += i;
printf("write %d byte\r\n", offset);
#if 0
uint8_t temp[2];
int temp_addr1;
temp_addr1 = FONT_LIB_CC936_OEM2UNI_ADDR;
for(int i = 0; i < FONT_LIB_SIZE / 2; i++)
{
SPI_Flash_Read(temp, temp_addr1 + (i*2)*2, 2);
if((temp[1]<<8 | temp[0]) == 0xb0a1)
{
printf("%d\r\n", i);
return;
}
}
#endif
printf("\r\ntest: GBK: 0xb0a1\r\nUnicode = ");
printf("%04x\r\n", ff_convert(0xb0a1, 1));
}
然后是GBK-Unicode,把oem2uni数组注释掉,然后修改添加以下代码,再调用test函数就OK了。
#define FONT_LIB_SIZE 87172
WCHAR ff_convert ( /* Converted code, 0 means conversion error */
WCHAR chr, /* Character code to be converted */
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
)
{
const WCHAR *p;
WCHAR c;
uint8_t temp[2];
int i, n, li, hi;
int temp_addr;
if (chr < 0x80) { /* ASCII */
c = chr;
} else {
if (dir) { /* OEM code to unicode */
temp_addr = FONT_LIB_CC936_OEM2UNI_ADDR;
hi = FONT_LIB_SIZE / 4 - 1;
} else { /* Unicode to OEM code */
temp_addr = FONT_LIB_CC936_UNI2OEM_ADDR;
hi = FONT_LIB_SIZE / 4 - 1;
}
li = 0;
for (n = 16; n; n--) {
i = li + (hi - li) / 2;
SPI_Flash_Read(temp, temp_addr + i*4, 2);
if (chr == (temp[1]<<8 | temp[0])) break;
if (chr > (temp[1]<<8 | temp[0]))
li = i;
else
hi = i;
}
SPI_Flash_Read(temp, temp_addr + i*4 + 2, 2);
c = n ? (temp[1]<<8 | temp[0]) : 0;
}
return c;
}
char temparray[4096];
void test(void)
{
printf("sizeof oem2uni = %d\r\n", sizeof uni2oem);
//printf("sizeof uni2oem = %d\r\n", sizeof uni2oem / 4 - 1);
int i = 0;
int j = 0;
for(i = 0; i < sizeof(uni2oem)/4096 + 1; i++)
{
SPI_Flash_Erase_Sector(FONT_LIB_CC936_UNI2OEM_ADDR / 4096 + i);
}
int offset = 0;
int temp_addr = FONT_LIB_CC936_UNI2OEM_ADDR;
for(j = 0; j < sizeof(uni2oem)/4096; j++)
{
memcpy(temparray, uni2oem + offset/2, sizeof(temparray));
SPI_Flash_Write((u8 *)temparray, temp_addr + offset, sizeof(temparray));
offset += sizeof(temparray);
printf("write %d byte\r\n", offset);
}
for(i = 0, j = offset; j < sizeof(uni2oem); j+=2, i+=2)
{
temparray[i + 1] = (uni2oem[(j) / 2] >> 8) & 0xff;
temparray[i] = uni2oem[(j) / 2] & 0xff;
}
SPI_Flash_Write((u8 *)temparray, temp_addr + offset, i);
offset += i;
printf("write %d byte\r\n", offset);
#if 0
uint8_t temp[2];
int temp_addr1;
temp_addr1 = FONT_LIB_CC936_UNI2OEM_ADDR;
for(int i = 0; i < FONT_LIB_SIZE / 2; i++)
{
SPI_Flash_Read(temp, temp_addr1 + (i*2)*2, 2);
if((temp[1]<<8 | temp[0]) == 0x554a)
{
printf("%d\r\n", i);
return;
}
}
#endif
printf("\r\ntest: Unicode: 0x554a\r\nGBK = ");
printf("%04x\r\n", ff_convert(0x554a, 0));
}
里边的存储地址根据实际情况修改,后续就可以在自己的程序里通过ff_convert函数来进行转换了。