二维码显示模块
2017-07-02 by Stavros做了个小模块, 可以把字符串从PC传到模块上存储, 并以二维码显示出来.
原理图如下, MCU用了48脚的stm32f103, 配1.44寸128x128的TFT屏, 存储么, 24C512和W25Q16各上一片. 其实只要24C512就足够了...
USB接口用了HID协议, 从stm32的官方USB例程改改就行, 好处是PC端不需要装驱动了. 程序太长就不贴上来了.
默认例程收发都是以8字节为单位, 这里先改成64字节, 但是64字节的数据包还是不够长, 所以需要做简单的分包处理. 思路也简单, 把第一字节的最高位和次高位作为首包和尾包的标志位, 接收时如果发现是首包, 就把接收指针指向接收缓冲区的起始位置; 然后把后面的63字节依次从USB端点复制到接收缓冲区, 之后接收指针增加63. 如果发现是尾包, 就设一个"接收完成"的标志变量为真.
主程序这边, 得到完整的数据后再调用libqrencode库, 把字符串转换成二维码显示出来, 最后设置"接收完成"的标志变量为假.
PC端程序用python实现, 因为有pywinusb库, 所以很简单, 贴上来:
import pywinusb.hid as hid
import time
# 从设备接收数据
def sample_handler(data):
data = [chr(i) for i in data]
data = ''.join(data[1:])
print(data)
# 向设备发送数据
def hid_send(buffer):
buffer = [i for i in buffer]
header = 0x80 # 首包标志
while len(buffer) > packetsize:
msg = [0x00] + [header] + buffer[:packetsize]
print(msg)
out_report.set_raw_data(msg)
header = 0x00
out_report.send()
print('#')
buffer = buffer[packetsize:] # buffer向后跳packetsize个位置
time.sleep(0.1)
header += 0x40 # 尾包标志
while len(buffer) < packetsize:
buffer.append(0) # 剩余数据不足, 补齐64字节
msg = [0x00] + [header] + buffer
out_report.set_raw_data(msg)
out_report.send()
print('#')
time.sleep(0.1)
# 主程序
flt = hid.HidDeviceFilter(vendor_id = 0x8589) # 按vendor_id查找设备
devices = flt.get_devices()
if devices:
device = devices[0]
print(device)
else:
exit()
device.open()
device.set_raw_data_handler(sample_handler)
out_report = device.find_output_reports()[0]
packetsize = 63 # 每次发送63字节
while True:
str = input().encode('utf8') # 汉字按utf-8处理
hid_send(str)
device.close()
之后问题来了, 发现最多只能生成61x61的二维码.
分析原因, 估计是因为libqrencode库返回的qrcode结构体是用malloc分配内存的, 根据我在前面《写了个取剩余可用堆内存的函数》里的分析, arm-none-eabi-gcc里的malloc分配的内存数量上限只能是2的整数次幂; 偏偏libqrencode库内部还多次使用了malloc, 这样20k ram的stm32f103c8一不小心就只能分配到最多4096字节内存了, 如果要生成65x65的二维码就会分配失败.
解决办法只能是换64脚的stm32f103rc或stm32f103re, 它们的内存分别是48k和64k; 128x128的屏幕能显示的最大二维码是125x125, 总共15625个点, 这样只要能成功分配到16k内存就行了, 估计有戏.
附带的好处是, 这俩的flash空间分别有256k和512k, 但是现在程序空间只用了20k多, 这样可以把多余的空间用来存二维码, 24c512和w25q16都可以省掉了.
ps. @Tariel推荐了一个代替*alloc的内存管理库: The BGET Memory Allocator, 也许用它能解决得更漂亮一点.
--------------------更新-------------------------
用bget代替malloc的结果, 可以生成69x69的二维码了... 确实是改善了一点点.