ssd1306 oled字模获取的一种方法

ssd1306 oled字模获取的一种方法

  • 前言
    • FontForge
    • XBM格式
    • 转换程序

前言

最近在玩0.91吋的oled显示屏,想显示汉字,最开始的想法是编写一个程序,调用freetype库,从Windows的字库文件中抽取出字模。但是freetype在windows上没有安装成功,所以就下载了一个字体编辑软件FontForge,用它从Windows的字库文件中抽取出字模,导出为XBM格式的图片文件,再编写一个程序,将其转换成oled可用的格式。

FontForge

用这个软件打开Windows的字库文件,找到需要的汉字,导出成X Bitmap文件,导出时Pixel Size填写31,这样导出的是32x32点阵的字模。

XBM格式

导出的图片文件用文本编辑打开:

#define uni6E29_SimHei_width 32
#define uni6E29_SimHei_height 32

static unsigned char uni6E29_SimHei_bits[] = {
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x38, 0xf8, 0xff, 0x03, 
  0x78, 0xf8, 0xff, 0x03, 
  0xe0, 0x18, 0x00, 0x03, 
  0xc0, 0x19, 0x00, 0x03,  
  0x80, 0x18, 0x00, 0x03, 
  0x00, 0xf8, 0xff, 0x03, 
  0x00, 0xf8, 0xff, 0x03, 
  0x0c, 0x18, 0x00, 0x03, 
  0x3c, 0x18, 0x00, 0x03, 
  0x70, 0x18, 0x00, 0x03, 
  0x60, 0xf8, 0xff, 0x03, 
  0x00, 0xf8, 0xff, 0x03,   
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x20, 0x00, 0x00, 0x00, 
  0x60, 0xfc, 0xff, 0x07, 
  0x60, 0xfc, 0xff, 0x07, 
  0x70, 0x8c, 0x31, 0x06, 
  0x30, 0x8c, 0x31, 0x06, 
  0x30, 0x8c, 0x31, 0x06,   
  0x38, 0x8c, 0x31, 0x06, 
  0x18, 0x8c, 0x31, 0x06, 
  0x18, 0x8c, 0x31, 0x06, 
  0x1c, 0x8c, 0x31, 0x06, 
  0x9c, 0xff, 0xff, 0x3f, 
  0x88, 0xff, 0xff, 0x3f, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00
};

这种格式非常适合嵌入到代码中。

转换程序

0.91吋oled用的是SSD1306驱动,我用的显示方式是Vertical addressing mode,需要将上面的点阵进行转换,转换代码如下:

#include 

//32x32 把xbm文件里的数组复制到这里
static unsigned char uni6E29_SimHei_bits[] = {
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x38, 0xf8, 0xff, 0x03, 
  0x78, 0xf8, 0xff, 0x03, 
  0xe0, 0x18, 0x00, 0x03, 
  0xc0, 0x19, 0x00, 0x03, 

  0x80, 0x18, 0x00, 0x03, 
  0x00, 0xf8, 0xff, 0x03, 
  0x00, 0xf8, 0xff, 0x03, 
  0x0c, 0x18, 0x00, 0x03, 
  0x3c, 0x18, 0x00, 0x03, 
  0x70, 0x18, 0x00, 0x03, 
  0x60, 0xf8, 0xff, 0x03, 
  0x00, 0xf8, 0xff, 0x03, 

  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 
  0x20, 0x00, 0x00, 0x00, 
  0x60, 0xfc, 0xff, 0x07, 
  0x60, 0xfc, 0xff, 0x07, 
  0x70, 0x8c, 0x31, 0x06, 
  0x30, 0x8c, 0x31, 0x06, 
  0x30, 0x8c, 0x31, 0x06, 

  0x38, 0x8c, 0x31, 0x06, 
  0x18, 0x8c, 0x31, 0x06, 
  0x18, 0x8c, 0x31, 0x06, 
  0x1c, 0x8c, 0x31, 0x06, 
  0x9c, 0xff, 0xff, 0x3f, 
  0x88, 0xff, 0xff, 0x3f, 
  0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00
};

void xbm2ssd1306_vertical(unsigned char *buf)
{
	int page,col;
	int buf_idx;
	int i;

    printf("\nconst int8_t font [] =\n{\n\t");

	for(col = 0;col<32;col++)
	{
		for(page=0;page<4;page++)
		{
			unsigned char lcd_bit = 0;
			for(i=0;i<8;i++)
			{
				buf_idx = page * 4 * 8 + i *4 + col/8;
				lcd_bit |= (((buf[buf_idx]>>(col % 8))&0x1)<<i);
			}
			printf("0x%02x, ",lcd_bit);
		}
		printf("\n\t");
	}
  printf("\n};\n");
}

void show_xbm(unsigned char *buf)
{
  int i,j;

  for(i = 0;i< 32 *4;i++)
  {
    if(i%4 == 0)
      printf("\n");
    for(j=0;j<8;j++)
    {
      if(buf[i]&(1<<(j)))
        printf("*");
      else
        printf(" ");
    }
  }
  printf("\n");
}

int main(int argc, char **argv)
{
    show_xbm(uni6E29_SimHei_bits);
	xbm2ssd1306_vertical(uni6E29_SimHei_bits);
    return 0;

}

执行上面的代码,打印如下:


   ***     ***************
   ****    ***************
     ***   **           **
      ***  **           **
       *   **           **
           ***************
           ***************
  **       **           **
  ****     **           **
    ***    **           **
     **    ***************
           ***************


     *
     **   *****************
     **   *****************
    ***   **   **   **   **
    **    **   **   **   **
    **    **   **   **   **
   ***    **   **   **   **
   **     **   **   **   **
   **     **   **   **   **
  ***     **   **   **   **
  ***  ***********************
   *   ***********************



const int8_t font [] =
{
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x18, 0x00, 0x18,
        0x30, 0x18, 0x00, 0x3f,
        0x30, 0x30, 0xe0, 0x1f,
        0x70, 0x70, 0xfc, 0x01,
        0xe0, 0x60, 0x38, 0x00,
        0xc0, 0x01, 0x00, 0x30,
        0x80, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0xf8, 0x3f,
        0xf0, 0xff, 0xf8, 0x3f,
        0xf0, 0xff, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0xf0, 0xff, 0x18, 0x30,
        0xf0, 0xff, 0xf8, 0x3f,
        0x00, 0x00, 0xf8, 0x3f,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,

};

打印出来的数组就是转换后的字模。可以拷贝到oled显示代码里

const int8_t wen_font [] =
{
		0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x18, 0x00, 0x18,
        0x30, 0x18, 0x00, 0x3f,
        0x30, 0x30, 0xe0, 0x1f,
        0x70, 0x70, 0xfc, 0x01,
        0xe0, 0x60, 0x38, 0x00,
        0xc0, 0x01, 0x00, 0x30,
        0x80, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0xf8, 0x3f,
        0xf0, 0xff, 0xf8, 0x3f,
        0xf0, 0xff, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0xf8, 0x3f,
        0x30, 0xc6, 0x18, 0x30,
        0x30, 0xc6, 0x18, 0x30,
        0xf0, 0xff, 0x18, 0x30,
        0xf0, 0xff, 0xf8, 0x3f,
        0x00, 0x00, 0xf8, 0x3f,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x30,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,

};
void ICACHE_FLASH_ATTR oled_write_wen(int x)
{
	int i;

	oled_write_cmd(0x20);//Set Memory Addressing Mode
	oled_write_cmd(0x01);//Vertical Addressing Mode

	oled_write_cmd(0x21);//Set Column Address
	oled_write_cmd(x);//Column start address
	oled_write_cmd(32+x);//Column end address

	oled_write_cmd(0x22);//Set Page Address
	oled_write_cmd(0x0);//Page start address
	oled_write_cmd(3);//Page end address

	for(i=0;i<32*4;i++)
		oled_write_data(wen_font[i]);

	oled_write_cmd(0x21);//Set Column Address
	oled_write_cmd(0x0);//Column start address
	oled_write_cmd(127);//Column end address

	oled_write_cmd(0x22);//Set Page Address
	oled_write_cmd(0x0);//Page start address
	oled_write_cmd(3);//Page end address
	return;
}

你可能感兴趣的:(ssd1306 oled字模获取的一种方法)