工控论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 0|回复: 0

STM32根据字符串生成二维码并在OLED显示 附源程序

[复制链接]

188

主题

189

帖子

22

积分

初级会员

Rank: 2

工控币
22
发表于 2020-6-7 16:04:31 | 显示全部楼层 |阅读模式
以前因为某些需要,需要单片机根据字符串自动生成二维码,(而不是把二维码图片取模再用LCD显示图片)在LCD12864中显示了出来,效果图如下:
1.png 2.png

可以看到图片清晰地显示了出来,且用任意扫码工具都能快速扫描出结果。感谢前辈的无私分享。
        好了,回归正题,最近手头有一块0.96寸OLED 屏幕,闲来无事就显示个二维码玩玩。首先移植前辈的二维码库,只需要QR_Encode.c和QR_Encode.h这两个就足够了。移植到任何一个能正常使用的oled驱动例程中,编写打点和画矩形函数,再调用QR_Encode.c中的bool EncodeData(char *lpsSource)函数就会根据你输入的字符串生成二维码数据并保存在全局数组m_byModuleData[MAX_MODULESIZE][MAX_MODULESIZE];中了,二维码的数据都是0或1,显示到屏幕时只需要一个个判断,遇1打点,遇0擦点(二维码正显)或遇1擦点,遇0打点(二维码反显),最后再刷新到oled上就好了。但这样的话得出来的二维码是比较小的,我们需要写算法进行放大。放大的原理是一个点用几个点表示,我用的方法是遇到0就画一个实心的矩形,遇到1就擦除一个实心矩形里面的所有点(反显),效果图如下:

3.png

我们看到,这个反显的二维码是能生成并显示出来了,但是没有打底或没有边框就显得很难看。所以为了好看,需要给它加个边框或打个白底,效果图如下(右)
4.png

此时可以看到右边这个打了白底的边框就显得很好看了。图中左边是没有打底的正显二维码,为何要用反显而不用正显呢?因为正显的除非扫码算法优化得特别好(如QQ、微信等),不然一般的扫码比较难扫描出结果,而反显的一扫就出来了,不信你们可以用浏览器的扫码或多试几个扫码软件看看。下图是正显的二维码
5.png
显示二维码到LCD最重要的是打点函数,可以开辟一个缓存用来存储打点的数据,最后把二维码数据和其他数据如边框或打底的数据都存完进这个缓存后再调用刷新屏幕函数刷新到oled即可。
打点函数如下:
  1. void OLED_DrawPoint(u8 x, u8 y, u8 t)
  2. {
  3.     u8 pos, bx, temp = 0;
  4.     if(x > 127 || y > 63)
  5.     {
  6.         return;//超出范围了.
  7.     }
  8.         pos = 7 - y/8;
  9.         bx = y % 8;
  10.         temp = 1 << (7 - bx);
  11.         t ? (OLED_GRAM[x][pos] |= temp) : (OLED_GRAM[x][pos] &= ~temp);   
  12. }
复制代码
刷新显存函数如下:
  1. void OLED_Refresh_Gram(void)//更新显存到OLED
  2. {
  3.         u8 i, n;                    
  4.         for(i = 0; i < 8; i++)  
  5.         {  
  6.                 WriteCmd(0xb0 + i);    //设置页地址(0~7)
  7.                 WriteCmd(0x00);      //设置显示位置—列低地址
  8.                 WriteCmd(0x10);      //设置显示位置—列高地址   
  9.                 for(n = 0; n < 128; n++)
  10.                 {
  11.                         WriteDat(OLED_GRAM[n]);
  12.                 }
  13.         }   
  14. }
复制代码
下面就是最重要的我封装好了的二维码显示函数:
  1. /**************************************************************************************************************
  2. 功能:在oled上显示二维码
  3. 参数:str->二维码内容;   offset->二维码在X轴上的位置,范围为0-127;  colour=1->二维码正显  colour=0->二维码反显
  4. **************************************************************************************************************/
  5. void OLED_QRcode_Display(char *str,uint8_t offset,uint8_t colour)//二维码的内容和第一个点再X轴的位置
  6. {
  7.         uint32_t i,j,point;
  8.         uint8_t exp = 1;//放大倍数
  9.         uint8_t pos_X,pos_Y;   
  10.     if(colour)
  11.         point = 1;
  12.     else
  13.         point = 0;   

  14.     EncodeData(str);        
  15.         exp = 64 / m_nSymbleSize;           //根据屏幕尺寸自动计算最佳放大倍数
  16.         pos_Y = (64 - exp*m_nSymbleSize)/2;        //这是二维码左下角第一个点的纵坐标
  17.         pos_X = pos_Y + offset;             //这是二维码左下角第一个点的横坐标

  18.     if(point==0)
  19.         OLED_Fill2(pos_X-2,pos_Y-2,pos_X + exp*m_nSymbleSize+2,pos_Y + exp*m_nSymbleSize+2,1);//给反显的二维码填充底色
  20.     //exp*m_nSymbleSize为放大后二维码的边长(二维码是正方形)
  21.         for(i=0;i<m_nSymbleSize;i++)
  22.         {
  23.                 for(j=0;j<m_nSymbleSize;j++)
  24.                 {
  25.                                 if(m_byModuleData[j] == 1)
  26.                                 {
  27.                                         OLED_Fill2(pos_X,pos_Y,pos_X+exp,pos_Y+exp,point);//画矩形并填充
  28.                                 }
  29.                                 if(m_byModuleData[j] == 0)
  30.                                 {
  31.                                         OLED_Fill2(pos_X,pos_Y,pos_X+exp,pos_Y+exp,1-point);//清空矩形区域
  32.                                 }
  33.                                 pos_Y += exp;
  34.                 }
  35.                 pos_X += exp;
  36.                 pos_Y -= m_nSymbleSize*exp;
  37.         }
  38.     OLED_Refresh_Gram();
  39. }
复制代码
调用方法如下:
234421qqxppz9ssbsjxbz3.png



其中,str是二维码的内容,可中英文和数字,若要扫码时自动打开网页,则需要在前面加https:// ;offset是二维码在X轴上的初始横坐标,范围为0-127,可用此调整二维码的横坐标让它居左居中等,纵坐标我现在设定的是自动调整到最大,可以自己修改。colour是正反显选择,0是反显,1是正显。如我要生成一个扫码就自动进入百度网页的居中反显二维码时参数如下:OLED_QRcode_Display("https://baidu.com",63,0);这样就能达到我们想要的效果了。下面是一正一反显二维码图:
6.png

下面是我的硬件平台:STM32F103C8T6核心板和0.96寸oled。移植到其他平台时内存8K以下的慎用,可能内存会爆。。
7.png

下方有完整工程可下载,用的HAL库,STM32Cubemx配置的工程
STM32_IIC_OLED_QR_Code.7z (14.33 MB, 售价: 5 工控币)
回复

使用道具 举报

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

本版积分规则

免责声明: 工控技术网(www.eleok.com)所有内容均为网友自行发布,不代表网站立场。如有版权纠纷,请联系本站删除:1370723259@qq.com

QQ|小黑屋|手机版|工控技术网 |网站地图

GMT+8, 2020-7-3 02:06

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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