標籤:

二維碼顯示模塊

做了個小模塊, 可以把字元串從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 hidnimport timenn# 從設備接收數據ndef sample_handler(data): n data = [chr(i) for i in data]n data = .join(data[1:])n print(data)nn# 向設備發送數據ndef hid_send(buffer):n buffer = [i for i in buffer]n header = 0x80 # 首包標誌 n while len(buffer) > packetsize:n msg = [0x00] + [header] + buffer[:packetsize]n print(msg)n out_report.set_raw_data(msg)n header = 0x00n out_report.send()n print(#)n buffer = buffer[packetsize:] # buffer向後跳packetsize個位置n time.sleep(0.1)nn header += 0x40 # 尾包標誌n while len(buffer) < packetsize:n buffer.append(0) # 剩餘數據不足, 補齊64位元組n msg = [0x00] + [header] + buffern out_report.set_raw_data(msg)n out_report.send()n print(#)n time.sleep(0.1)nn# 主程序nflt = hid.HidDeviceFilter(vendor_id = 0x8589) # 按vendor_id查找設備ndevices = flt.get_devices()nif devices:n device = devices[0]n print(device)nelse:n exit()nndevice.open()nndevice.set_raw_data_handler(sample_handler)nout_report = device.find_output_reports()[0]nnpacketsize = 63 # 每次發送63位元組nnwhile True:n str = input().encode(utf8) # 漢字按utf-8處理n hid_send(str)nndevice.close()n

之後問題來了, 發現最多只能生成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的二維碼了... 確實是改善了一點點.

推薦閱讀:

學點兒DIY | 逆天神作!自製手機紅外遙控器!超靈敏電路!
想要學習電子方面的知識,想請大家推薦一塊學慣用的開發板?
理工科女生 學電子合適嗎?
含有直流成分的交流信號通過電容,為什麼可以隔直流?
搗鼓時間:如何做一個簡易測謊儀

TAG:DIY | 电子 |