二维码在今天已经相当普及了,制作二维码也不难,网上有很多制作二维码的网站,输入信息,立即转换出二维码。然而我们要自己根据信息制作出二维码却不那么简单。网上粗略找了下源码,几乎清一色的是java/c#版本的,这对于stm32芯片项目来说没什么大帮助。最终辗转找到Linux上的qrencode软件包,将其移植了过来。
一、初识二维码
a) 二维码可以存储1850个字节的信息,可以存数字、字母、汉子、图像
b) 二维码三个矩形用于定位,矩形样式可以更改,整张图片甚至可以倒转过来
c) 拥有冗余信息,根据容错率可以选择最多50%
d) 因为冗余的关系,二维码中间以及右下角可以放置图案
f) 二维码的算法根据容错率的不同会产生不同的图案
草料二维码:你好
联图网二维码:你好
很显然两个网站的算法是不同的,但包含的信息都一样。用任意扫描端都能扫描出其中的内容
二、移植准备:
a) qrencode-3.4.4.tar.gz作为移植源码 百度盘:http://pan.baidu.com/s/1ntyvf7r
b) stm32f429i-discovery探索板
c) 移植好stemwin的例程 详见官方例程STM32Cube_FW_F4_V1.4.0目录下的\Projects\STM32F429I-Discovery\Applications\STemWin
三、移植过程
a) 用iar打开带stemwin的工程。 新建qrcode工程子目录,并将所有qrencode.tar.gz解压后的.c文件添加进来。
b) 在windows文件夹中打开此工程目录STM32Cube_FW_F4_V1.4.0\Projects\STM32F429I-Discovery\Applications\STemWin\qrcode
复制所有qrencode.tar.gz解压后的.c文件到src文件夹中
复制所有qrencode.tar.gz解压后的.h文件到inc文件夹中
c) 先保存编译一下。报了一大堆错,这是肯定的,源码包用的是linux的LCD库文件,解决方法是在这里将报错的都注释掉就可以了
在main函数中添加最重要的两句二维码库调用
Qrcode中就包含着我们最终需要的二维码信息,其实就是一个图,存着01比特信息
调用fb_qrdisp显示此二维码,这里贴出fb_qrdisp源码,注释掉的是已经修改的部分
<pre name="code" class="cpp">int Fb_QrDisp(int iPenX,int iPenY,QRcode*pQRcode) { T_PixelDatasg_tOriginPixelDatas; T_PixelDatasg_tZoomPixelDatas; //intiZoom; inti; g_tOriginPixelDatas.iWidth= pQRcode->width; g_tOriginPixelDatas.iHeight=pQRcode->width; g_tOriginPixelDatas.iLineBytes=g_tOriginPixelDatas.iWidth; g_tOriginPixelDatas.aucPixelDatas= pQRcode->data; /* if(pQRcode->version <= 1) { iZoom= 2; } else { iZoom= 2; } g_tZoomPixelDatas.iWidth = pQRcode->width*iZoom; g_tZoomPixelDatas.iHeight=pQRcode->width*iZoom; g_tZoomPixelDatas.iLineBytes=g_tZoomPixelDatas.iWidth; g_tZoomPixelDatas.aucPixelDatas= malloc(g_tZoomPixelDatas.iWidth* g_tZoomPixelDatas.iHeight); if(g_tZoomPixelDatas.aucPixelDatas== NULL) { printf("g_tZoomPixelDatas->aucPixelDatasmalloc failed\n"); return-1; } PicZoom(&g_tOriginPixelDatas,&g_tZoomPixelDatas); #if 0 printf("g_tZoomPixelDatas.iWidth=%d,g_tZoomPixelDatas.iHeight=%d\n", g_tZoomPixelDatas.iWidth,g_tZoomPixelDatas.iHeight); for(i=0;i<(g_tZoomPixelDatas.iWidth*g_tZoomPixelDatas.iHeight);i++) { printf("0x%x,",g_tZoomPixelDatas.aucPixelDatas[i]); } printf("\n"); #endif */ Disp_FixelPic(iPenX,iPenY,&g_tZoomPixelDatas); return 0; }
因为stmf429运行起来后内存不够,这里不用申请内存再扩充放大二维码数据的方法,而是直接描点。所以这里注释掉了放大部分
e) 紧接着调用Disp_FixelPic根据qrcode进行描点
</pre><pre name="code" class="cpp"><pre name="code" class="cpp">void Disp_FixelPic(int iPenX,int iPenY,PT_PixelDatas ptPixelDatas) { int i=0,j=0; GUI_SetBkColor(GUI_WHITE); GUI_Clear(); GUI_SetPenSize(1); for(i=0;i<ptPixelDatas->iHeight;i++) { for(j=0;j<ptPixelDatas->iWidth;j++) { if(ptPixelDatas->aucPixelDatas[i*ptPixelDatas->iHeight+j]&0x01) { //lcd_pixel_show(j+iPenX, i+iPenY,0x00); GUI_SetColor(GUI_BLACK); GUI_FillRect(j*8+iPenX, i*8+iPenY,j*8+8+iPenX, i*8+8+iPenY); } else { GUI_SetColor(GUI_WHITE); //lcd_pixel_show(j+iPenX, i+iPenY, 0xffffff); //GUI_DrawPoint(j*8+iPenX, i*8+iPenY); GUI_FillRect(j*8+iPenX, i*8+iPenY,j*8+8+iPenX, i*8+8+iPenY); } } } }
这里注释掉了原lcd描点函数,而是采用了stemwin提供的矩形填充函数
f) 编译运行,能看到LCD显示出二维码。至此移植完毕
移植过程中有一个小问题,因为调用了stemwin的画笔函数,当画笔GUI_SetPenSize(1);的时候,描的是一个点,当GUI_SetPenSize(16);的时候,画的是一个大圆点,而不是一个方点,这里要注意一下不能采用此画笔,而要采用矩形填充函数GUI_FillRect
void Disp_FixelPic(int iPenX,intiPenY,PT_PixelDatas ptPixelDatas)
{
int i=0,j=0;
GUI_SetBkColor(GUI_WHITE);
GUI_Clear();
GUI_SetPenSize(1);
for(i=0;i<ptPixelDatas->iHeight;i++)
{
for(j=0;j<ptPixelDatas->iWidth;j++)
{
if(ptPixelDatas->aucPixelDatas[i*ptPixelDatas->iHeight+j]&0x01)
{
//lcd_pixel_show(j+iPenX,i+iPenY,0x00);
GUI_SetColor(GUI_BLACK);
GUI_FillRect(j*8+iPenX, i*8+iPenY,j*8+8+iPenX, i*8+8+iPenY);
}
else
{
GUI_SetColor(GUI_WHITE);
//lcd_pixel_show(j+iPenX,i+iPenY, 0xffffff);
//GUI_DrawPoint(j*8+iPenX, i*8+iPenY);
GUI_FillRect(j*8+iPenX, i*8+iPenY,j*8+8+iPenX, i*8+8+iPenY);
}
}
}
}