单片机mcu(stm32)计算生成二维码

二维码的标准版本共有40个,从版本1到版本40,每个版本对应不同的尺寸和数据容量。版本越高,二维码的矩阵越大,能存储的信息也越多,但图案也更复杂,需要更高的扫描精度。

二维码版本的基本结构

  • 版本计算公式 :每个版本的模块(黑白小方块)数量为 (4 × 版本号 + 17) × (4 × 版本号 + 17)。例如:
    • 版本1:21 × 21 模块
    • 版本2:25 × 25 模块
    • 版本40:177 × 177 模块

版本的不同直接影响二维码的容量和应用场景。低版本适合简单数据,如短URL;高版本可用于存储大量文本或图像数据。

数据容量与纠错级别

二维码的容量取决于版本和纠错级别(Error Correction Level),纠错级别有四种:L(低,约7%纠错)、M(中,约15%)、Q(高,约25%)、H(最高,约30%)。纠错允许二维码部分损坏仍可读取。

以下是部分版本在不同纠错级别下的最大数据容量示例(以数字模式为例,实际容量因数据类型而异,如数字、字母、汉字等):

版本 尺寸 (模块) L级别容量 (字节) M级别容量 (字节) Q级别容量 (字节) H级别容量 (字节)
1 21×21 41 34 27 17
2 25×25 77 63 48 34
5 37×37 255 202 144 106
10 57×57 652 513 364 288
20 97×97 1,953 1,589 1,153 861
40 177×177 7,089 5,748 4,193 3,057

(数据来源于QR码国际标准ISO/IEC 18004。 实际容量会因编码模式而略有差异,

计算使用的是这个库QR-Code-generator

https://github.com/nayuki/QR-Code-generator/tree/master/c

就用两个文件,qrcodegen.cqrcodegen.h,导入到keil中。

因为我只想显示设备编号,所以用版本1的就可以

看了一下代码对ram占用很低,自己写的部分就用了两个数组,qrcode和tempBuffer,具体长度由qrcodegen_BUFFER_LEN_FOR_VERSION这个宏根据使用的二维码版本计算,版本1的二维码数组长度就57个字节,所以在我测试的stm32f030c8t6(48mhz,64k的flash,9k的ram)上都能算出来。

需要在keil里勾选C99模式

objectivec 复制代码
#include "qrcodegen.h"
void printQr(const uint8_t qrcode[]) {
    int size = qrcodegen_getSize(qrcode);
    int border = 4;
    for (int y = -border; y < size + border; y++) {
        for (int x = -border; x < size + border; x++) {
            vDebug_Printf((qrcodegen_getModule(qrcode, x, y) ? "■■" : "  "), stdout);
        }
        vDebug_Printf("\n", stdout);
    }
    vDebug_Printf("\n", stdout);
}
uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MIN)];
uint8_t tempBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MIN)];
void doBasicDemo(void) {
    const char *text = "123teng567";                // User-supplied text
    bool ok;
    enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW;  // Error correction level
    
    ok = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl,
        qrcodegen_VERSION_MIN, qrcodegen_VERSION_MIN, qrcodegen_Mask_AUTO, true);
    if (ok)
        printQr(qrcode);
}

printQr函数是把生成通过串口打印出来,当然光打印出来肯定是不行的,要在lcd屏幕上显示就得配合lcd屏幕的画点函数了,这里就不多赘述了。

把从串口助手里打印出来的字符复制到notepad++文本编辑器里,

串口助手打印出来的太乱了

复制在notepad里面,ctrl加滚轮,把文字缩到最小。

手机拿远点用微信就能扫出来了,比较难扫出来,因为字符打印出来的图形并不标准,微信还是比其他扫码工具强的。

下面由ai解释代码:

这段代码是一个使用 qrcodegen 库(一个开源的C语言QR码生成库)的简单演示程序。它展示了如何生成一个包含特定文本的QR码,并以ASCII艺术形式(使用■■表示黑色模块,空格表示白色模块)在控制台打印出来。整个代码分为两个主要函数:printQr(用于打印QR码)和doBasicDemo(用于生成QR码并调用打印函数)。

我会逐部分解释代码,包括整体结构、关键变量、函数逻辑和潜在输出。假设你熟悉基本的C语言概念(如数组、循环和函数);如果不是,我会尽量用通俗语言描述。这段代码是"基本演示"(basic demo),适合初学者理解QR码生成的流程。

  1. 头文件和依赖(隐含)

虽然代码中没有显式包含头文件,但从函数名可以推断它依赖于qrcodegen.h(qrcodegen库的头文件)。这个库提供QR码生成的核心功能,如编码文本、计算大小和获取模块。

另外,可能需要stdio.h(用于printf)和库中的其他定义(如qrcodegen_getSize、qrcodegen_getModule等)。

vDebug_Printf 似乎是自定义的打印函数(可能是printf的变体,用于调试);在实际代码中,可以替换为标准printf。

  1. 函数:void printQr(const uint8_t qrcode[])

目的:接收一个已生成的QR码数据数组(qrcode),然后在控制台以文本形式"绘制"QR码。QR码本质上是一个二维网格,黑白模块(像素)组成。

参数:

const uint8_t qrcode[]:一个只读的uint8_t数组,存储QR码的模块数据(每个元素表示一个模块的状态:黑或白)。

逻辑 breakdown:

int size = qrcodegen_getSize(qrcode);:获取QR码的大小(边长)。QR码版本决定大小,例如版本1是21x21模块,最小版本(VERSION_MIN,通常是1)是21模块。

int border = 4;:添加一个4模块宽的白色边框(QR码标准要求至少4模块的安静区,以提高扫描可靠性)。

双重循环:

外循环:for (int y = -border; y < size + border; y++) -- 从上边框(-4)到下边框(size+4),遍历Y轴(行)。

内循环:for (int x = -border; x < size + border; x++) -- 遍历X轴(列)。

对于每个位置(x, y):

调用qrcodegen_getModule(qrcode, x, y):检查该模块是否为黑色(返回true)或白色(false)。

如果黑色,打印"■■"(两个全角方块,模拟一个黑像素);如果白色,打印" "(两个空格)。

每行结束打印"\n"(换行)。

最后添加一个空行"\n",分隔输出。

效果:这会生成一个ASCII艺术风格的QR码,便于在终端查看,而不需要图形库。边框确保QR码不会贴边,提高视觉清晰度。

  1. 全局变量(缓冲区)

uint8_t qrcode[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MIN)];:主缓冲区,用于存储最终生成的QR码数据。大小基于最小版本(VERSION_MIN,通常是1),足够容纳21x21的模块。

uint8_t tempBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MIN)];:临时缓冲区,用于编码过程中的中间计算(库要求提供两个缓冲区)。

  1. 函数:void doBasicDemo(void)

目的:演示QR码生成的核心流程:编码文本、设置参数,然后调用printQr打印。

逻辑 breakdown:

const char *text = "123teng567";:用户提供的文本内容。这里是"123teng567" -- 一个简单的字符串。QR码会将这个文本编码成二进制模块。

bool ok;:用于检查编码是否成功。

enum qrcodegen_Ecc errCorLvl = qrcodegen_Ecc_LOW;:设置错误修正级别(Error Correction Level)。选项有LOW(7%纠错)、MEDIUM(15%)、QUARTILE(25%)、HIGH(30%)。LOW是最基本的,生成的QR码最小,但容错低(如果QR码损坏,扫描可能失败)。

ok = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MIN, qrcodegen_Mask_AUTO, true);:

调用库的核心函数qrcodegen_encodeText:将文本编码成QR码。

参数:

text:输入字符串。

tempBuffer:临时缓冲。

qrcode:输出缓冲(最终QR码数据)。

errCorLvl:纠错级别(LOW)。

版本范围:qrcodegen_VERSION_MIN 到 qrcodegen_VERSION_MIN(强制使用最小版本1,21x21大小)。如果文本太长,会失败;实际中可以设为更高版本如40(177x177)。

qrcodegen_Mask_AUTO:掩码模式自动选择(QR码使用掩码来优化模块分布,提高扫描性;AUTO让库挑选最佳)。

true:安静模式(不输出错误信息?库文档中可能是"boostEcl"或其他标志;假设是启用自动提升纠错)。

如果ok为true,编码成功。

if (ok) printQr(qrcode);:如果成功,调用打印函数输出QR码。

整体执行流程

调用doBasicDemo()(假设在main函数中调用)。

生成QR码数据(编码"123teng567")。

如果成功,打印ASCII QR码。

相关推荐
玩嵌入式的菜鸡3 小时前
stm32bootloader跳到app无法运行问题
stm32·单片机·嵌入式硬件
普中科技3 小时前
【普中51单片机开发攻略--基于普中-2&普中-3&普中-4】-- 第 13 章 独立按键实验
单片机·嵌入式硬件·51单片机·开发板·按键·独立按键·普中科技
点亮一颗LED(从入门到放弃)3 小时前
Linux驱动之中断(9)
linux·运维·单片机
小叶子来了啊3 小时前
13Arduino Flash 存储
单片机·嵌入式硬件
无聊到发博客的菜鸟4 小时前
STM32 RTC时钟不准的问题
stm32·嵌入式·rtc·rtos
点灯小铭4 小时前
基于单片机的温度烟雾与漏电综合火灾报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
boneStudent4 小时前
Day41:四轴飞行器控制系统 (基础)
stm32·单片机·嵌入式硬件
曾浩轩5 小时前
跟着江协科技学STM32之3-3GPIO输入
科技·stm32·嵌入式硬件