【开源】基于STM32的无线条码扫描仪控制系统设计
本项目设计了一款基于STM32F103C8T6的无线条码扫描仪控制系统,通过GM65二维码模块实现快速识别,支持物品录入与取出两种模式。系统通过OLED显示操作信息,蓝牙模块实现数据无线传输至手机APP,具备库存管理、异常报警等功能。硬件采用STM32最小系统板、OLED显示屏、轻触按键等模块,软件采用任务调度机制实现多任务处理。该系统操作简便、识别精准,可广泛应用于仓储、实验室等场景,提升物品管
项目编号:STM32-T009
项目名称:基于STM32的无线条码扫描仪控制系统设计
【摘要】
本项目设计了一种基于STM32F103C8T6单片机的无线条码扫描仪控制系统,旨在实现物品的智能化录入与管理。系统采用GM65二维码读取模块,支持对预设二维码的高速识别,用户可通过按键切换“录入”与“取出”两种功能模式。在录入模式下,扫码器读取二维码信息,将商品名称、型号与编号等信息录入并显示在OLED屏幕上,完成物品登记;在取出模式下,扫描物品二维码,系统自动比对库存数据,若物品信息存在,则成功完成取出操作;如物品未录入,蜂鸣器发出报警,提示用户操作异常。系统还配备蓝牙模块,将录入与取出的所有记录实时传输至手机APP,实现远程查看与信息同步。该系统具有操作简单、识别准确、记录可追溯等优点,广泛适用于实验室、仓库、办公室等场景的物品管理,提升物品存取效率与信息化水平,具有良好的应用前景与实际价值。
【所用硬件】
1、STM32F103C8T6最小系统板
STM32F103C8T6最小系统板是基于意法半导体(ST)Cortex-M3内核的微控制器开发板,核心芯片为STM32F103C8T6,主频72MHz,具有64KB Flash和20KB SRAM,满足中等复杂度的嵌入式应用需求。该板集成USB、USART、SPI、I2C等通信接口,支持多种外设扩展。最小系统板包含必要的外围电路,如8MHz晶振、复位电路、电源管理(3.3V稳压),并提供GPIO引脚引出,方便连接传感器、显示屏等模块。其低功耗、高性能特性使其广泛应用于智能硬件、工业控制等领域。在本设计中,它作为主控单元,负责数据采集、处理及外设控制,确保电子秤系统的稳定运行。
2、OLED显示模块

OLED(有机发光二极管)显示屏模块是一种自发光显示器件,无需背光,具有高对比度、宽视角和快速响应的特点。本设计采用的OLED模块通常为0.96英寸或1.3英寸,分辨率为128×64像素,支持I2C或SPI通信协议,可直接与STM32等微控制器连接。其工作电压为3.3V~5V,功耗低,适合便携式设备。
3、轻触按键

轻触按键(Tactile Switch)是一种瞬时接触式机械开关,通过按压触发导通,松开后自动复位。其结构简单、体积小巧,通常采用金属弹片或导电橡胶实现触点通断,具有手感清晰、寿命长(可达10万次以上操作)的特点。工作电压和电流范围宽(如12V/50mA),可直接与STM32等微控制器的GPIO引脚连接,需配合上拉/下拉电阻使用以避免信号浮动。
4、GM65二维码读取模块

GM65二维码模块是一款高性能二维条码识读器,体积小巧、集成度高,常用于嵌入式系统中。它采用CMOS影像识别技术,支持多种一维、二维条码的快速解码,具备高速识读和较强的纠错能力,即使在低对比度、模糊或光照不佳的环境下也能稳定识别。该模块通过TTL串口或USB接口与主控设备通信,使用方便,广泛应用于物联网、移动支付、门禁控制、工业自动化等场景,具有响应速度快、识别率高和易于集成的特点。
5、蓝牙模块

HC-05蓝牙模块是一款常用的串口通信蓝牙模块,支持蓝牙2.0协议,采用主从一体设计,可通过AT指令自由配置工作模式。它通过UART接口与单片机或电脑连接,实现无线串口数据传输,使用方便、成本低廉、兼容性好。该模块传输稳定、距离可达10米左右,广泛应用于无线控制、小型物联网设备、智能小车和数据采集系统中,是嵌入式开发与蓝牙通信学习的常见选择。
【系统框架图】

【软件流程图】

【核心代码展示】
#include "app_task.h"
#include "main.h"
#include "m5310a.h"
#include "delay.h"
#include "usart.h"
#include "timer.h"
#include "esp8266.h"
#include "io.h"
#include "led.h"
#include "oled.h"
#include "sim800l.h"
#include "rtc.h"
#include "Encoder.h"
#include "beep.h"
#include "mpu6050.h"
#include "inv_mpu.h"
#include "adc.h"
#include "key.h"
#include "dth11.h"
#include "ds18b20.h"
#include "PAJ7620.h"
#include "max30102.h"
#include "stm32f10x_adc.h"
#include "HCSR04.h"
#include "rfid.h"
#include "redcod.h"
#include "IIC_1602.h"
#include "gps.h"
#include "FPM383C.h"
#include "car.h"
#include "HLW8032.h"
u8 str[100];
USER user;
OLED oled;
TaskControlBlock TaskList[MAX_TASKS] = {0};
uint8_t RegisteredTasks = 0; // 已注册任务数
uint32_t SystemTick = 0; // 系统时间基准
// 任务注册函数
int8_t Task_Register(uint8_t id, uint32_t interval, void (*task_func)(void *), void *param)
{
if (RegisteredTasks >= MAX_TASKS)
return -1;
TaskList[RegisteredTasks].TaskID = id;
TaskList[RegisteredTasks].PollingInterval = interval;
TaskList[RegisteredTasks].TimerCounter = 0;
TaskList[RegisteredTasks].RunFlag = 0;
TaskList[RegisteredTasks].EnableFlag = 1;
TaskList[RegisteredTasks].TaskHook = task_func;
TaskList[RegisteredTasks].TaskParam = param;
TaskList[RegisteredTasks].Delay = 0;
RegisteredTasks++;
return 0;
}
// 任务使能控制
void Task_Enable(uint8_t id, uint8_t enable)
{
for (int i = 0; i < RegisteredTasks; i++)
{
if (TaskList[i].TaskID == id)
{
TaskList[i].EnableFlag = enable;
break;
}
}
}
/**
* @brief LED闪烁任务
*
* @param pt
*/
void Led_Task(void *pt)
{
LED1 = !LED1;
}
/**
* @brief 按键任务
*
* @param pt
*/
void Key_Task(void *pt)
{
switch (KEY_Scan(0))
{
case KEY1_PRICE:
{
if(oled.page == PAGE_HOME)
{
oled.x = 1;
}
};
break;
case KEY2_PRICE:
{
if(oled.page == PAGE_HOME)
{
oled.x = 2;
}
};
break;
case KEY3_PRICE:
{
if(oled.page == PAGE_HOME)
{
if(oled.x == 1)
{
oled.page = PAGE_ENTER;
oled.x=1;
OLED_Clear();
}
else if(oled.x == 2)
{
oled.page = PAGE_EXIT;
oled.x=1;
OLED_Clear();
}
}
};
break;
case KEY4_PRICE:
{
if(oled.page == PAGE_ENTER || oled.page == PAGE_EXIT)
{
oled.x=1;
oled.page = PAGE_HOME;
OLED_Clear();
}
};
break;
}
}
/**
* @brief OLED任务
*
* @param pt
*/
void OLED_Task(void *pt)
{
if (oled.page == PAGE_HOME)
{
/**无线扫描仪 */
OLED_ShowChinese(16,0,5,16,1);
OLED_ShowChinese(32,0,6,16,1);
OLED_ShowChinese(48,0,7,16,1);
OLED_ShowChinese(64,0,8,16,1);
OLED_ShowChinese(80,0,9,16,1);
if(oled.x == 1)
{
/**录入模式 */
OLED_ShowChinese(0,16,10,16,0);
OLED_ShowChinese(16,16,11,16,0);
OLED_ShowChinese(32,16,12,16,0);
OLED_ShowChinese(48,16,13,16,0);
}
else
{
/**录入模式 */
OLED_ShowChinese(0,16,10,16,1);
OLED_ShowChinese(16,16,11,16,1);
OLED_ShowChinese(32,16,12,16,1);
OLED_ShowChinese(48,16,13,16,1);
}
if(oled.x == 2)
{
/**取出模式 */
OLED_ShowChinese(0,32,14,16,0);
OLED_ShowChinese(16,32,15,16,0);
OLED_ShowChinese(32,32,16,16,0);
OLED_ShowChinese(48,32,17,16,0);
}
else
{
/**取出模式 */
OLED_ShowChinese(0,32,14,16,1);
OLED_ShowChinese(16,32,15,16,1);
OLED_ShowChinese(32,32,16,16,1);
OLED_ShowChinese(48,32,17,16,1);
}
}
else if(oled.page == PAGE_ENTER)
{
/**录入模式 */
OLED_ShowChinese(32,0,10,16,1);
OLED_ShowChinese(48,0,11,16,1);
OLED_ShowChinese(64,0,12,16,1);
OLED_ShowChinese(80,0,13,16,1);
/**请刷二维码! */
OLED_ShowChinese(16,32,22,16,1);
OLED_ShowChinese(32,32,23,16,1);
OLED_ShowChinese(48,32,24,16,1);
OLED_ShowChinese(64,32,25,16,1);
OLED_ShowChinese(80,32,26,16,1);
OLED_ShowChinese(96,32,27,16,1);
if(user.enter_flag == 1)
{
user.enter_flag = 0;
OLED_ShowString(0,16," ",16,1);
OLED_ShowString(0,32," ",16,1);
OLED_ShowString(0,48," ",16,1);
/**编号: */
OLED_ShowChinese(0,16,28,16,1);
OLED_ShowChinese(16,16,29,16,1);
OLED_ShowChinese(32,16,30,16,1);
sprintf(str,"%d",user.commodity[user.num-1].number);
OLED_ShowString(48,16,str,16,1);
/**名称: */
OLED_ShowChinese(0,32,31,16,1);
OLED_ShowChinese(16,32,32,16,1);
OLED_ShowChinese(32,32,33,16,1);
sprintf(str,"%s",user.commodity[user.num-1].name);
OLED_ShowString(48,32,str,16,1);
/**型号: */
OLED_ShowChinese(0,48,34,16,1);
OLED_ShowChinese(16,48,35,16,1);
OLED_ShowChinese(32,48,36,16,1);
sprintf(str,"%s",user.commodity[user.num-1].modle);
OLED_ShowString(48,48,str,16,1);
OLED_Refresh();
Delay_ms(3000);
OLED_Clear();
}
}
else if(oled.page == PAGE_EXIT)
{
/**取出模式 */
OLED_ShowChinese(32,0,14,16,1);
OLED_ShowChinese(48,0,15,16,1);
OLED_ShowChinese(64,0,16,16,1);
OLED_ShowChinese(80,0,17,16,1);
/**请刷二维码! */
OLED_ShowChinese(16,32,22,16,1);
OLED_ShowChinese(32,32,23,16,1);
OLED_ShowChinese(48,32,24,16,1);
OLED_ShowChinese(64,32,25,16,1);
OLED_ShowChinese(80,32,26,16,1);
OLED_ShowChinese(96,32,27,16,1);
if(user.exit_flag == 1)
{
user.exit_flag = 0;
OLED_ShowString(0,16," ",16,1);
OLED_ShowString(0,32," ",16,1);
OLED_ShowString(0,48," ",16,1);
/**取出成功! */
OLED_ShowChinese(32,32,37,16,1);
OLED_ShowChinese(48,32,38,16,1);
OLED_ShowChinese(64,32,39,16,1);
OLED_ShowChinese(80,32,40,16,1);
OLED_ShowChinese(96,32,41,16,1);
OLED_Refresh();
Delay_ms(3000);
OLED_Clear();
}
else if(user.exit_flag == 99)
{
user.exit_flag = 0;
OLED_ShowString(0,16," ",16,1);
OLED_ShowString(0,32," ",16,1);
OLED_ShowString(0,48," ",16,1);
/**无此物! */
OLED_ShowChinese(32,32,18,16,1);
OLED_ShowChinese(48,32,19,16,1);
OLED_ShowChinese(64,32,20,16,1);
OLED_ShowChinese(80,32,21,16,1);
OLED_Refresh();
Delay_ms(3000);
OLED_Clear();
}
}
OLED_Refresh();
}
void Task_Init(void)
{
Task_Register(1, 1000, Led_Task, NULL);
Task_Register(2, 1, Key_Task, NULL);
Task_Register(3, 200, OLED_Task, NULL);
}
void Task_Run(void)
{
for (int i = 0; i < RegisteredTasks; i++)
{
if (TaskList[i].RunFlag && TaskList[i].EnableFlag)
{
// 执行任务函数
if (TaskList[i].TaskHook != NULL)
{
TaskList[i].TaskHook(TaskList[i].TaskParam);
}
// 清除运行标志
TaskList[i].RunFlag = 0;
}
}
}
void TaskTime(void)
{
static u32 tick_time = 0;
tick_time++;
// 遍历任务列表更新计数器
for (int i = 0; i < RegisteredTasks; i++)
{
if (TaskList[i].EnableFlag)
{
TaskList[i].TimerCounter++;
// 达到时间间隔时设置运行标志
if (TaskList[i].TimerCounter >= TaskList[i].PollingInterval)
{
TaskList[i].RunFlag = 1;
TaskList[i].TimerCounter = 0;
}
}
}
}
【原理图】

【硬件实物图】

【实物演示】
STM32-T009-无线条码扫描仪控制系统设计
更多推荐



所有评论(0)