项目编号: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-无线条码扫描仪控制系统设计

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐