当前位置:   article > 正文

STM32+OLED屏显示字符串、汉字、图片(二)_oled显示汉字字库

oled显示汉字字库

上一节初始化了OLED屏,使得它完成了清屏,现在驱动它在屏幕上打印字符串、汉字以及图片。

        1.1   STM32+OLED屏初始化(一) 

        1.2  STM32+OLED屏显示字符串、汉字、图片(二)

        1.3  STM32+OLED屏多级菜单显示(三)

        1.4  STM32+OLED屏(软件IIC+位带+帧缓冲区)刷新速率优化(四) 

1.制作字库

字符集:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

        要想屏幕上显示字符,需要相应的字库,现在先做一个字库。

        打开取模软件pctolcd2002完美版,再点击选项,配置如下所选,点击确定。

        点阵格式:阴码字体亮,阳码字体不亮 

        字符走向:逆向低位在前,顺向高位在前(主要看驱动IC的编码格式)、

        取模方式:指字模图形的扫描方向 

        输出数制:生成字模的数的进制 

        每行显示数据:生成数组的大小,字符的长(页)x字符的宽(如8*16字体,2页*8列 = 16;如12*24字体,3页*12列 = 36;如16*32字体,4页*16列 = 64)

        选择字库字体大小,最好选择8的倍数,因为64行已经分为8页(每页8行),如果不是8的倍数,就会显示到其他页去,操作会变得麻烦一些。

自命名字库名称

        一个8x16的英文字库就完成了,字符在字库中的存取是二维数组Ascii_8*16[95][16];就拿字符 ' A ' 来说,字符 ' A ' 存在Ascii_8*16[33][0] ~ Ascii_8*16[33][16]之间

生成其他大小的字库

        生成12*24的字库,首先要调节字体大小,其次要调节每行显示数据:24/8=3页,3*12=36,所以每行显示数据的点阵设置为36,最后,点击生成字模,复制粘贴到OLED_Fonnt.h文件中

三种大小不同的字库

        字库中存取了三种字体,第一个比较特殊(在网上找的,但不完整),自己尝试着生成,发现自己生成的字体显示不清晰,如果有朋友有完整的,请@我分享我一份,其他两个是自己生成的

2.显示一个字符 

        显示字符串从一个字符开始,字符串只不过是一串字符,完成显示一个字符后再循环多次,就可以完成字符串显示了,字符显示先定义起始光点,再把字库中的数据写入,即可完成。就拿8*16字体来说,8列*16行(2页),所以要写2页(i < 2),字宽写8列(j < 8),第一页设置起始光点写入数据,第二页再设置起光点偏移一位( + i),因为字宽是8,数据再偏移八位( + i*8),完成显示

  1. /**
  2. * @brief OLED显示一个字符
  3. * @param Line 行位置
  4. * @param Column 列位置
  5. * @param Fontsize 字体大小
  6. * @param Char 要显示的一个字符,
  7. * @retval 无
  8. */
  9. void OLED_ShowChar(uint8_t Line, uint8_t Column, uint16_t Fontsize, char Char)
  10. {
  11. uint8_t i, j;
  12. switch(Fontsize) {
  13. case 8: {
  14. OLED_SetCursor(Line, Column);
  15. for (j=0; j<6; j++) {//字宽为6
  16. OLED_Write_Data(Ascii_6x8[Char-' '][j]);
  17. }
  18. break;
  19. }
  20. case 16: {
  21. for(i=0; i<2; i++) {
  22. OLED_SetCursor(Line+i, Column); //循环2次显示上/下半部分内容
  23. for (j=0; j<8; j++) {//字宽为8
  24. OLED_Write_Data(Ascii_8x16[Char-' '][j+i*8]);
  25. }
  26. }
  27. break;
  28. }
  29. case 24: {
  30. for(i=0; i<3; i++) {
  31. OLED_SetCursor(Line+i, Column); //循环3次显示上//下半部分内容
  32. for (j=0; j<12; j++) {//字宽为12
  33. OLED_Write_Data(Ascii_12x24[Char-' '][j+i*12]);
  34. }
  35. }
  36. break;
  37. }
  38. }
  39. }

        6*8字体 ' A ', 8*16字体 ' A ', 12*24字体 ' A '

3.显示字符串

        字符串的显示较为简单,在显示字符的基础上偏移一个字符的字宽,就可以了。如6*8字体的字宽是6,就偏移 + i*6;8*16字体的字宽是8,就偏移 + i*8;12*24字体的字宽是12,就偏移 + i*12

  1. /**
  2. * @brief OLED显示字符串
  3. * @param Line 行位置
  4. * @param Column 列位置
  5. * @param Fontsize 字体大小
  6. * @param String 显示字符串,
  7. * @retval 无
  8. */
  9. #include <string.h>
  10. void OLED_ShowString(uint8_t Line, uint8_t Column, uint16_t Fontsize, const char* String)
  11. {
  12. uint8_t i, len;
  13. len = strlen(String);//算出字符串长度
  14. for(i=0; i<len; i++) {
  15. switch(Fontsize) {
  16. case 8:OLED_ShowChar(Line, Column+i*6, Fontsize, String[i]);
  17. break;
  18. case 16:OLED_ShowChar(Line, Column+i*8, Fontsize, String[i]);
  19. break;
  20. case 24:OLED_ShowChar(Line, Column+i*12, Fontsize, String[i]);
  21. break;
  22. }
  23. }
  24. }

         6*8字体 " ABCD ", 8*16字体 " ABCD ", 12*24字体 " ABCD "

4.显示汉字

        汉字的显示同理,先制作中文字库,但是中文汉字太多了,简单选择几个“ 点个赞吧!”显示即可,首先,制作汉字字库:因为字宽为16*2页 = 32

        加入OLED_Font.h,自定义二维数组名称:

        显示一个汉字,显示汉字和显示字符同理,只不过汉字的字宽是16,所以字宽写16列(j < 16),后续的数据偏移也自然是16位( + i*16);完成显示

  1. /**
  2. * @brief OLED显示汉字
  3. * @param Line 行位置
  4. * @param Column 列位置
  5. * @param Chinese 显示汉字编号
  6. * @retval 无
  7. */
  8. void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t Chinese)
  9. {
  10. uint8_t i, j;
  11. for(i=0; i<2; i++) {
  12. OLED_SetCursor(Line+i, Column); //循环2次显示上/下半部分内容
  13. for (j=0; j<16; j++) {//字宽为16
  14. OLED_Write_Data(Chinese_16x16[Chinese][j+i*16]);
  15. }
  16. }
  17. }

        显示效果:

5.显示图片

        同理,制作图源库,找一张自己喜欢的图片,选择画图工具打开

        设置像素大小,进行裁剪

        另存为BMP单色位图片

        打开取模工具,选择图形模式,再打开刚刚制作的图片,生成字模

        保存到OLED_Font.h中,删除所有的大括号,保存为一维数组

        写法一样,依次取数 

  1. /**
  2. * @brief OLED显示图片
  3. * @param 无
  4. * @retval 无
  5. */
  6. void OLED_ShowImageBMG(void)
  7. {
  8. uint8_t i, j;
  9. for(i=0; i<8; i++) {
  10. OLED_SetCursor(0+i, 0); //循环8次显示8页内容
  11. for (j=0; j<128; j++) {//字宽为8
  12. OLED_Write_Data(ImageBMG64x128[j+i*128]);
  13. }
  14. }
  15. }

显示效果:

6.编写RTC显示时钟

        最后,再编写一个实时时钟完成显示,常规时钟配置就不展示了,直接上最终源码

  1. /**
  2. * @brief OLED显示RTC
  3. * @param 无
  4. * @retval 无
  5. */
  6. void OLED_ShowRTC(void)
  7. {
  8. char buff[50];
  9. RTC_Get_StdTime(RTC_GetCounter());
  10. sprintf(buff,"%0.2d-%0.2d-%0.2d",RTC_CLOCK.hour, RTC_CLOCK.min, RTC_CLOCK.sec);
  11. OLED_ShowString(4, 10, 24, buff);
  12. sprintf(buff,"Date:%0.4d-%0.2d-%0.2d",RTC_CLOCK.year,RTC_CLOCK.mon,RTC_CLOCK.day);
  13. OLED_ShowString(1, 6, 16, buff);
  14. }

        

7.主函数 

main.c函数

  1. //#include "main.c"
  2. int main(void)
  3. {
  4. OLED_Init();
  5. Usart_Init();
  6. printf("OLED显示字符串、汉字、图片\r\n");
  7. // //显示字符串
  8. // OLED_ShowString(0,0,8,"ABCD");
  9. // OLED_ShowString(1,0,16,"ABCD");
  10. // OLED_ShowString(3,0,24,"ABCD");
  11. //
  12. // //显示汉字
  13. // OLED_ShowChinese(3,16*2,0);//
  14. // OLED_ShowChinese(3,16*3,1);//
  15. // OLED_ShowChinese(3,16*4,2);//
  16. // OLED_ShowChinese(3,16*5,3);//
  17. // OLED_ShowChinese(3,16*6,4);// !
  18. // //显示图片
  19. // OLED_ShowImageBMG();
  20. //显示时钟
  21. OLED_ShowRTC();
  22. while (1) {
  23. delay_ms(1000);
  24. }
  25. }

        总结:历经万险终于完了,虽然最终的效果都实现了,但代码并不健壮。问题在于访问光点缺少越界保护,屏幕的范围在64*128之间,可是起始光点设置的范围却没有限制;除此之外,字符串的一部分超出显示范围没有进行换行换页,这些问题可能在今后造成巨大的错误。

源码分享:

链接:https://pan.baidu.com/s/1ZpaEZhR0IvtqoiW-65ATKw?pwd=p08k 
提取码:p08k

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/920070
推荐阅读
相关标签
  

闽ICP备14008679号