关于STM32的二维码源码移植问题(已修正)
1.移植二维码生成程序到项目中
- 从链接: https://fukuchi.org/works/qrencode/.下载源码
- 在工程里面添加源码主文件夹下除 qrenc.c 以外的所有 .h 和 .c 文件
- 创建config.h文件
文件内容如下
#ifndef QRconfigens
#define QRconfigens
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 0
/* Major version number */
#define MAJOR_VERSION 3
/* Micro version number */
#define MICRO_VERSION 0
/* Minor version number */
#define MINOR_VERSION 9
/* Define to the version of this package. */
#define PACKAGE_VERSION "3.9.0"
/* Version number of package */
#define VERSION "3.9.0"
#define LIBQRENCODE_VERSION "3.9.0"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to 'static' if no test programs will be compiled. */
#define __STATIC
#define WITH_TESTS 1
#endif
- 在项目中所有的.c文件中,添加# include “config.h”
- 在MAIN.C中,添加#include “qrencode.h”
2.这里就是要解决的问题:STM32堆栈大小不够?
我已经把这个问题及解决办法提交到github,在最新版中已经被改正。
如果你是下载的最新版文件,可以忽略这个问题。
以下是问题的原因以及解决办法:
参考其他人的移植经验,我发现STM32的堆栈大小至少要扩大8倍才能正常运行一些比较短的字符串。
这样做,很明显会影响其他内存空间的大小。
而且STM32运行起来速度不慢,完全不像是运算速度之类的问题。
所以我决定分析代码,检查其中到底是哪里不兼容,试着去修正它,让STM32正常运行这个程序。
经过我一周的检测,发现了这样一个函数,在split.c中。 (注释是自己加的)
static int Split_splitString(const char *string, QRinput *input,QRencodeMode hint)
{
int length;
QRencodeMode mode;
if(*string == '\0') return 0;//输入字符串空则退出
mode = Split_identifyMode(string, hint);//字符类型判断
if(mode == QR_MODE_NUM)//数字模式移动
length = Split_eatNum(string, input, hint);
else if(mode == QR_MODE_AN)//字符模式移动
length = Split_eatAn(string, input, hint);
else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI)//汉字模式移动
length = Split_eatKanji(string, input, hint);
else
length = Split_eat8(string, input, hint);//8位模式移动
if(length == 0) return 0;
if(length < 0) return -1;
return Split_splitString(&string[length], input, hint);//嵌套调用此函数
}
想必大家都能看出来这个问题,如果嵌套调用函数进行处理的话,电脑可能没什么,但是STM32的堆栈大小是不足够用的。使用长一点的字符串,重复压栈几次,就很容易导致堆栈溢出。
所以我把这个函数修改成了这样:
static int Split_splitString(const char *string, QRinput *input,QRencodeMode hint)
{
int length;
QRencodeMode mode;
while(*string != '\0') //return 0;//字符串空则退出
{
mode = Split_identifyMode(string, hint);//字符类型判断
if(mode == QR_MODE_NUM)
length = Split_eatNum(string, input, hint);//数字模式移动
else if(mode == QR_MODE_AN)
length = Split_eatAn(string, input, hint);//数字字母混合模式移动
else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI)
length = Split_eatKanji(string, input, hint);//汉字模式移动
else
length = Split_eat8(string, input, hint);//8位模式移动
if(length == 0) return 0;
if(length < 0) return -1;
string = &string[length];
}
return 0;
}
取消了嵌套调用,而是改为循环。
经过测试,STM32在使用原来的小堆栈,也可以完美运行。
#define m_EXPAND_DOT 3
void QRcode_draw_Str(const char * QC_DATA)
{
QRcode*qrcode;
u32 i=0,j=0;
qrcode = QRcode_encodeString(QC_DATA, 3,QR_ECLEVEL_M,QR_MODE_8,1);//用输入字符串生成二维码
if(qrcode != NULL)//如果成功生成二维码
{
TFT_COLOR_18_Clear();//清屏
for(i = 0; i < qrcode->width; i++)//高循环
{
for(j = 0; j < qrcode->width; j++)//宽循环
{
if(qrcode->data[i*qrcode->width + j] & 0x01) //判断目前位置颜色
TFT_COLOR_18_draw_block(m_EXPAND_DOT*i,m_EXPAND_DOT*j,m_EXPAND_DOT,m_EXPAND_DOT,0x0000);//画黑块
else
TFT_COLOR_18_draw_block(m_EXPAND_DOT*i,m_EXPAND_DOT*j,m_EXPAND_DOT,m_EXPAND_DOT,0xffff);//画白块
}
}
QRcode_free (qrcode);//释放生成的二维码占用的内存
}
}
例如:
QRcode_draw_Str("http://img.xz7.com/up/2017-9/2017090516331545018.jpg");
如此长的字符串可以直接生成,没有问题。