OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 16623|回复: 12

I2C OLED图片及汉字显示方案,包括字库制作及图片处理,图片显示方案可删减

[复制链接]

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2015-6-27 20:34:49 | 显示全部楼层 |阅读模式
用原子哥的开发板也有一段时间了,感觉收货非常,谢谢!
这是我按照汉字制作实验做的,通过字库软件生成字模,放入SD卡再写入W25Q16,W25Q16最后200K大小用于存放图片数据,如果不是W25Q16只需修改配置头文件中的宏即可。

本设计为 I2C  OLED   图片及汉字显示方案
具有移植性强   可删减  等特点
图片显示 相关代码 存放于OLED_BMP 文件中 可通过修改 OLED_BMP_CONFIG.h 头文件中宏的值来设置及删减
图片显示提供了 快速显示图片及慢速显示使能宏    FLASH图片数据允许修改宏  及串口打印宏
慢速显示图片可节约800RAM (速度降低几十MS)  
如果图片数据已经写入FLASH 并不需要串口打印调试  可把这3个宏都设置为0  
Uart.c(串口)、OLED_BMP_Font.c(FLASH图片数据)这两个文件可直接从工程中删去(也可不删去) 工程能正常编译不报错
串口中已构架 int Uart_printf(const char* str,...) 函数 类似  printf   但不能配置   具体内容请看C文件
汉字及I2C OLED 驱动 不再啰嗦   

如果需要移植 
 请修改 SPI底层(SPI.C)  I2C底层(I2C.C) OLED_BMP_CONFIG.h 中数据类型

所用硬件:
 STC15W4K48S4单片机(也可其它STC单片机)   W25Q16    I2C OLED

本设计字库制作采用原子战舰开发板

字库烧写工程:
    
字库文件:

STC15W4K48S4控制工程(也可为其它STC单片机):

以上总合集:

字库烧写.zip

1.12 MB, 下载次数: 3097

字库文件.zip

343.99 KB, 下载次数: 2092

I2C OLED图片及汉字显示方案.zip

1.6 MB, 下载次数: 5671

I2C_OLED_BMP_Config_15_5_22.zip

145.86 KB, 下载次数: 2378

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5781
金钱
5781
注册时间
2013-11-22
在线时间
1212 小时
发表于 2015-6-27 23:01:41 | 显示全部楼层
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
 楼主| 发表于 2015-6-28 08:49:02 | 显示全部楼层
回复【2楼】lycreturn:
---------------------------------
谢谢,相互学习
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
 楼主| 发表于 2015-6-28 10:04:46 | 显示全部楼层
发现一个错误漏洞:
所有的图片显示都是通过查询图片对应的索引,然后再调用显示指定索引图片显示,由于考虑到大小端问题,程序中加入大小端校验及转换,但是在显示指定所有图片需转换条件下,转换错误,错误代码如下:(以低速显示图片函数为例) 

#else    //低速显示图片

BMP_u8  FLASH_BMP_play(BMP_u8 num)  //指定索引  图片显示    返回 0成功  其它失败
{
  BMP_u8   code_buf[8]={0};   //数组数据缓存
  BMP_u16  adress=0;          //偏移地址
  BMP_u8   i=0  ;             //循环计数

  SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+num*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4);  //读取指定图片数据指针结构体
  
  if((BMP_Code.start==0x5A)&&(BMP_Code.end==0XA5))   //是否存在

  if(BMP_Code.MOS_flaot==0x1234)   //无需进行大小端转换    
  {
    for(adress=0;adress<1024;)   //循环写入
   {
     if(adress%128==0)   //是否翻页
     {
        OLED_Set_Pos(0,adress/128);     //设置页地址
      }

      SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8);  //读取FLASH  内数据

     for(i=0;i<8;i++)   //写入数据到 OLED
    {
        OLED_WrDat(code_buf);
    }
     adress += 8;   //地址偏移
    }
    return 0;                                          //返回成功
   } 
else if(BMP_Code.MOS_flaot==0x3412)     //需进行大小端转换    图片索引 及 图片数组数据地址  需转换 
      {
        BMP_Code.bmp_num=((BMP_Code.bmp_num&0xff00)>>8)|((BMP_Code.bmp_num&0x00ff)<<8);  //图片索引大小端转换
 
       for(adress=0;adress<1024;)  //循环写入
      {
         if(adress%128==0)   //是否翻页
        {
            OLED_Set_Pos(0,adress/128);     //设置页地址
         }

       SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8);  //读取FLASH  内数据

      for(i=0;i<8;i++)   //数据 写入OLED
       {
        OLED_WrDat(code_buf);
      } 
      adress += 8;    //地址偏移
    }
    return 0;                                         //返回成功
   }                                           
  }
    return 1;                                            //返回失败
}

#endif

以上红色区域为错误对应,我的想法是根据大小端校验(0X3412),如果需要转换,应该是把读到的数据起始地址转换而不是索引。但考虑到如果图片数量过多(大于255),则索引也会出现大小端问题,所有我在调用显示指定索引图片函数之前,先对索引判断是否需要大小端转换,如果要转换则转换完成后再调用指定索引图片显示。原先指定索引图片显示里对索引进行转换改为对数据起始地址进行转换。

需改后的代码如下:
BMP_u8  FLASH_BMP_ID_play(BMP_u8 *BMP_ID) //显示FLASH中指定ID图片  返回0成功   1失败
{
  BMP_u16 BMP_MAX = FLASH_BMP_Scan();   //当前FLASH 图片总数

#if UART_TEST__EN
Uart_printf(" 输入数组长度为 %d \r\n",strlen(BMP_ID));
#endif

while(BMP_MAX--)     //从后向前轮询
  {
    #if UART_TEST__EN
         Uart_printf(" 当前扫描索引为 %d \r\n",BMP_MAX);
    #endif

    SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+BMP_MAX*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4);  //读取指定索引图片指针数据
    if(strcmp(BMP_Code.bmp_ID,BMP_ID)==0)
   {
      if(BMP_Code.MOS_flaot==0x1234)   //无需进行大小端转换    
      {
        #if UART_TEST__EN
         Uart_printf(" 对应图片的索引为 %d \r\n",BMP_Code.bmp_num);
        #endif

        FLASH_BMP_play(BMP_Code.bmp_num);   //显示指定索引图片
       return 0;
     }
   else if(BMP_Code.MOS_flaot==0x3412)   //需要大小端转换
         {
            BMP_Code.bmp_num=((BMP_Code.bmp_num&0xff00)>>8)|((BMP_Code.bmp_num&0x00ff)<<8);  //图片索引大小端转换

           #if UART_TEST__EN
                Uart_printf(" 对应图片的索引为 %d \r\n",BMP_Code.bmp_num);
          #endif

        FLASH_BMP_play(BMP_Code.bmp_num);       //显示指定索引图片
        return 0;
      }
    }
  }
  #if UART_TEST__EN
       Uart_printf(" 没有找到对应图片! \r\n");
 #endif
 return 1;     //没有找到
}

#else    //低速显示图片

BMP_u8  FLASH_BMP_play(BMP_u8 num)  //指定索引  图片显示    返回 0成功  其它失败
{
  BMP_u8   code_buf[8]={0};   //数组数据缓存
  BMP_u16  adress=0;          //偏移地址
  BMP_u8   i=0  ;             //循环计数

  SPI_Flash_Read((unsigned char*)&BMP_Code,OLED_BMP_START+num*(sizeof(bmp_code_typ)-4),sizeof(bmp_code_typ)-4);  //读取指定图片数据指针结构体
  
  if((BMP_Code.start==0x5A)&&(BMP_Code.end==0XA5))   //是否存在
   { 
       if(BMP_Code.MOS_flaot==0x1234)   //无需进行大小端转换    
       {
         for(adress=0;adress<1024;)   //循环写入
           {
             if(adress%128==0)   //是否翻页
             {
                OLED_Set_Pos(0,adress/128);     //设置页地址
            }

      SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8);  //读取FLASH  内数据

     for(i=0;i<8;i++)   //写入数据到 OLED
     {
        OLED_WrDat(code_buf);
     }
        adress += 8;   //地址偏移
   }
    return 0;                                          //返回成功
 } 
else if(BMP_Code.MOS_flaot==0x3412)     //需进行大小端转换    图片索引 及 图片数组数据地址  需转换 
       {  
          BMP_Code.bmp_aderr = ((BMP_Code.bmp_aderr & 0xff000000) >> 24)\
                                               | ((BMP_Code.bmp_aderr & 0x00ff0000) >>  8)\
                                               | ((BMP_Code.bmp_aderr & 0x0000ff00) <<  8)\
                                               | ((BMP_Code.bmp_aderr & 0x000000ff) << 24);     //数据起始地址进行大小端转换
 
       for(adress=0;adress<1024;)  //循环写入
      {
         if(adress%128==0)   //是否翻页
        {
            OLED_Set_Pos(0,adress/128);     //设置页地址
        }

      SPI_Flash_Read(code_buf,BMP_Code.bmp_aderr+adress,8);  //读取FLASH  内数据

      for(i=0;i<8;i++)   //数据 写入OLED
      {
         OLED_WrDat(code_buf);
      }
      adress += 8;    //地址偏移
    }
    return 0;                                         //返回成功
   }                                           
  }
 return 1;                                           //返回失败
}

#endif

此方案可以直接在OLED_BMP_CONFIG.h中修改宏的值  用于设置
设置宏如下:
//快速显示图片使能    1 快速显示---------------------------------------
#define  LAY_BMP_SPEED            0       //关闭 可节约800多字节 RAM

// 串口调试 使能------------------------------------------------------
#define  UART_TEST__EN              1      //为1时开启串口调试    必须包含串口头文件

// FLASH图片数据修改 使能---------------------------------------------
#define  FLASH_DATA_SET_EN      1       //为1时 允许修改FLASH图片数据

//本次写入FLASH 图片数据个数   必须宏  FLASH_DATA_SET_EN 大于0 有效
#define  BMP_FONT_NUM              3       //当前数组图片个数  请与OLED_BMP_FONT.C 中图片数据个数对应  大于图片数据数量后面写入图片为乱码


#define FLASH_Volume             ((BMP_u32)2)                                                                           //FLASH容量  单位: M
#define FLASH_Sector_SIZE     ((BMP_u32)4096)                                                                     //FLASH扇区大小   单位: 字节
#define BMP_SIZE                    ((BMP_u32)200*1024)                                                             //FLASH给与图片数据字节大小
#define BMP_ALL_Sector          (BMP_SIZE/FLASH_Sector_SIZE)                                              //FLASH给与图片数据扇区数

#define FLASH_ALL_Adress      ((BMP_u32)FLASH_Volume*1024*1024)                                  //FLASH总字节地址
#define OLED_BMP_START      (FLASH_ALL_Adress-BMP_SIZE)                                                //FLASH图片数组指针开始地址   
#define FLASH_START_Sector  (OLED_BMP_START/FLASH_Sector_SIZE)                                //FLASH图片数组指针开始地址对应扇区

#define FLASH_Pointer_MAX    (FLASH_Sector_SIZE/(sizeof(bmp_code_typ)-4))                      //FLASH图片数组指针最大数量           

#define OLED_CODE_Adress   ((BMP_u32)(FLASH_START_Sector+1)*FLASH_Sector_SIZE)   //FLASH图片数组数据写入首地址
#define OLED_CODE_Sector   (FLASH_START_Sector+1)                                                       //FLASH图片数组数据写入首地址对应扇区


如果字库已经写好,所要用的图片也已写好且不需要串口打印状态,则可通过上面3个使能宏来节约ROM和RAM,并可以直接把串口及FLASH数据文件从工程移除

I2C OLED 汉字及图片显示方案最新工程:

I2C OLED图片及汉字显示方案.zip

1.6 MB, 下载次数: 1565

回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-28 10:45:13 | 显示全部楼层
不错,谢谢分享。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
 楼主| 发表于 2015-6-28 12:14:07 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
呵呵,谢谢原子个,一下等级变成两个水晶了,有点激动。。。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-28 22:20:58 | 显示全部楼层
回复【6楼】513393302@qq.com:
---------------------------------
多分享好东西,升的更快
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

2

主题

394

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2115
金钱
2115
注册时间
2012-5-8
在线时间
314 小时
发表于 2015-8-26 10:20:49 | 显示全部楼层
很不错啊!支持!
回复 支持 反对

使用道具 举报

16

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
265
金钱
265
注册时间
2015-11-1
在线时间
34 小时
发表于 2016-3-5 23:43:17 | 显示全部楼层
谢谢分享,正在搞OLEDiic
这是我的小尾巴~
回复 支持 反对

使用道具 举报

0

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
139
金钱
139
注册时间
2013-8-16
在线时间
23 小时
发表于 2016-3-6 18:21:10 | 显示全部楼层
回复 支持 反对

使用道具 举报

2

主题

56

帖子

0

精华

高级会员

Rank: 4

积分
509
金钱
509
注册时间
2015-12-22
在线时间
85 小时
发表于 2016-3-7 17:07:52 | 显示全部楼层
谢谢分享。。。
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2019-8-7
在线时间
1 小时
发表于 2019-8-8 15:34:38 | 显示全部楼层
谢谢楼主的分享
回复 支持 反对

使用道具 举报

0

主题

81

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2014-9-18
在线时间
21 小时
发表于 2020-5-9 18:11:21 | 显示全部楼层

谢谢楼主的分享
回复 支持 反对

使用道具 举报

5

主题

43

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
481
金钱
481
注册时间
2019-7-18
在线时间
83 小时
发表于 2021-1-27 17:40:13 | 显示全部楼层
厉害,下载学习!!!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-12 13:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表