基于单片机的条形码识别系统设计

1、基于单片机的条形码识别系统设计

点击链接下载protues仿真设计资料:https://download.csdn.net/download/m0_51061483/92081536

1.1、系统概述

条形码技术是一种经典而成熟的信息自动识别技术,被广泛应用于超市收银、仓储物流、图书管理、工业生产追溯、快递分拣等场景。条形码本质上是一种"编码规则+图形表示"的组合:通过黑白条纹的宽度与排列,将数字或字符映射成可被机器识别的编码信息。典型的一维条形码中,EAN13(European Article Number 13)是最常见的商品条码标准之一,能够表示13位数字,其中包含国家/地区前缀、厂商代码、商品代码以及校验位,具有广泛的现实应用基础。

传统条码识别多采用光电扫描枪实现:扫描枪发射光线照射条码,黑条吸收光、白条反射光,传感器采集反射强度变化后形成高低电平信号,再通过解码算法得到数字信息。然而在教学、实验或系统验证场景中,直接使用真实条码印刷与光电扫描可能会受到光线环境、印刷质量、扫描速度、传感器噪声等因素影响,导致实验可控性较差。因此,本设计采用"发射机模拟条形码编码"的方式:发射机端由单片机生成符合EAN13规则的编码信号,并通过无线/红外/射频/有线方式发送到接收机。接收机端单片机接收到编码信号后进行同步、采样与解码,并将识别得到的13位EAN条码数字显示出来。

为了增强系统可交互性与实验灵活性,本系统还提供"键盘输入编码并自由修改编码值"的功能:用户可在发射端通过键盘输入13位EAN编码(或输入12位自动计算校验位),系统将其转换为EAN13条码序列并发射;接收端则在显示模块上实时显示接收到的编码值,同时可显示校验结果(通过/失败),使用户能够直观观察编码---传输---解码---校验的完整过程。

该系统本质上是一个"数字条码编码与通信识别系统",包含条码编码生成、数据调制发送、接收同步解码、校验验证、键盘输入交互与显示输出等多个模块。系统设计不仅能够帮助掌握EAN13标准编码规则与校验机制,还能综合训练单片机定时控制、外部中断采样、信号调制解调、状态机算法设计、键盘扫描与显示驱动等嵌入式综合能力,具有较强的学习价值与工程意义。


2、系统功能设计

2.1、发射机模拟条形码编码并通过单片机发射

发射机的核心任务是:根据用户输入的EAN13数字,生成对应条形码的"黑白条序列",并将其转换为可传输的数字波形。由于本系统采用"模拟条形码编码"的方式,因此发射机不需要打印或绘制真实条纹,而是直接将条形码的条纹序列用0/1电平(或高/低脉冲)表示。例如:

  • 黑条(Bar)表示逻辑0
  • 白条(Space)表示逻辑1
    或者反过来,这只影响解码逻辑的一致性。

为了使接收端可靠恢复信息,发射机需满足:

1)编码规则严格符合EAN13结构(起始符、左右数据区、中心符、终止符)

2)发射波形具有固定的"基本模块宽度"(即条码最小单位宽度),便于接收端按固定节拍采样

3)提供帧同步机制,确保接收端知道一帧条码数据何时开始、何时结束

4)具备可配置编码值输入接口(键盘输入)

发射机在实现上通常采用定时器产生固定周期(例如1ms、2ms、5ms作为一个模块宽度),在每个模块周期内输出一个高/低电平。整帧输出完成后,可加入帧间隔(空闲段),使接收端更容易分离多次传输。


2.2、接收机接收编码并显示识别结果

接收机的核心任务是:

1)从接收模块获取信号(可能带噪声、抖动、边沿误差)

2)完成信号整形与同步:识别起始符并对齐采样时钟

3)按EAN13规则将条纹序列解码为数字

4)对校验位进行校验

5)将13位数字显示出来,并提示校验是否通过

在显示方面,接收机可使用:

  • LCD1602显示(两行显示13位数字+校验结果)
  • 数码管显示(若位数不足可滚动显示)
  • 串口上位机显示(扩展)

考虑到13位数字较长,LCD1602较适合:第一行显示13位EAN码,第二行显示"OK/ERR"与接收状态(READY/RECV/DECODE)。


2.3、键盘输入编码,自由修改编码值

键盘输入功能主要用于提高系统灵活性,使发射端不再局限于固定编码,而能够实时输入并修改EAN码。键盘形式可采用:

1)矩阵键盘(4×4或4×3)

2)独立按键(0~9 + 功能键)

3)外接串口输入(上位机输入,扩展)

本设计以矩阵键盘为典型实现,具备:

  • 数字键:0~9
  • 功能键:删除、确认、清空、自动校验位计算等

键盘输入逻辑应支持:

  • 输入12位自动计算第13位校验码
  • 或输入完整13位并进行校验提示
  • 输入不足时提示"LEN ERR"
  • 输入过程中可在显示端实时显示当前输入

通过键盘输入机制,用户可以快速测试不同EAN码的编码与识别效果,并验证校验位算法的正确性。


2.4、采用EAN13条码标准编码规则

EAN13条码由以下结构组成:

  • 起始符(Start Guard):101
  • 左侧6位数字编码(Left 6 digits):每位7个模块,共42模块
  • 中间分隔符(Center Guard):01010
  • 右侧6位数字编码(Right 6 digits):每位7模块,共42模块
  • 终止符(End Guard):101

总模块数:3 + 42 + 5 + 42 + 3 = 95模块

因此只要定义一个"模块宽度",例如2ms/模块,则一帧条码数据总时长约95×2ms=190ms(不含帧间隔)。

EAN13左侧6位的编码方式并不固定,它根据第1位数字决定左侧6位采用A/B编码的组合模式(奇偶校验模式)。右侧6位固定采用C编码。

因此EAN13编码过程的关键步骤包括:

1)得到13位数字

2)根据第1位确定左侧6位使用A/B编码模式

3)将第2~7位按A/B编码生成条纹

4)将第8~13位按C编码生成条纹

5)拼接起始符、中心符、终止符形成完整95位模块序列

6)输出脉冲序列

此外,EAN13第13位为校验位,用于检测输入或识别错误,其计算规则为:

  • 从左到右(前12位),奇数位求和×1,偶数位求和×3
  • 总和对10取模,校验位 = (10 - (mod值)) % 10
    校验机制可以有效发现单个数字错误或部分交换错误,是条码系统可靠性的重要保证。

3、电路设计

3.1、系统硬件总体结构

系统由发射机与接收机两部分组成,均以单片机为核心。其主要模块如下:

发射机端模块:

1)单片机最小系统模块(52系列或其他)

2)键盘输入模块(矩阵键盘)

3)显示模块(可选:LCD/数码管显示输入编码)

4)EAN13编码生成模块(软件实现)

5)发射驱动模块(红外/射频/有线输出)

6)电源模块

接收机端模块:

1)单片机最小系统模块

2)接收模块(与发射匹配:红外接收头/射频接收模块/比较器输入)

3)信号整形与滤波模块(施密特触发、RC滤波)

4)解码处理模块(软件实现)

5)显示模块(LCD1602或串口)

6)蜂鸣器提示模块(可选)

7)电源模块

由于题目强调"发射机模拟编码并发送到接收机",因此硬件重点在于发射与接收信号链路的设计。下面对每个模块进行详细说明。


3.2、单片机最小系统模块

发射机与接收机都需要稳定可靠的单片机最小系统。常用选择:

  • STC89C52、AT89S52等52系列
  • STC12系列(带更高性能与更丰富外设)
  • 其他如STM32亦可

最小系统包含:

  • 晶振电路(11.0592MHz或12MHz)
  • 复位电路(上电复位+按键复位)
  • 去耦电容(0.1uF+10uF)
  • 下载接口(ISP)

设计要点:

  • 发射端需要精准时序输出,建议使用定时器产生模块周期
  • 接收端需要捕获边沿并精准采样,建议使用外部中断或定时器输入捕获(51可用INT0/INT1)
  • 强烈建议在接收端输入加施密特触发整形,提高抗干扰能力

3.3、键盘输入模块(发射端)

键盘用于输入和修改EAN编码。推荐采用4×4矩阵键盘:

  • 0~9数字输入
  • A键:确认/发送
  • B键:删除
  • C键:清空
  • D键:切换输入模式(12位自动校验/13位直接输入)

硬件连接方式:

  • 4行输出、4列输入
  • 列输入端上拉电阻(可用内部上拉)
  • 行扫描输出逐行拉低,读取列状态判断按键

设计要点:

  • 必须进行软件消抖(10~20ms)
  • 支持按键长按重复输入(可选)
  • 输入数字应显示在屏幕上,让用户确认无误

3.4、显示模块(发射端可选、接收端必选)

发射端显示模块可用于:

  • 显示当前输入EAN码
  • 显示校验位计算结果
  • 显示"READY/SEND"等状态

接收端显示模块用于:

  • 显示接收并解码后的EAN13数字
  • 显示校验是否通过(OK/ERR)
  • 显示接收状态(WAIT/RECV/DECODE)

显示模块可选:

  • LCD1602:字符显示方便,适合13位数字
  • OLED:显示更清晰
  • 数码管:若仅4位需滚动显示,不如LCD直观

因此推荐接收机采用LCD1602;发射机可选LCD或数码管,若资源有限也可仅接收端显示即可。


3.5、发射驱动模块(条码编码信号发送)

发射模块用于将单片机输出的编码波形发送到接收端。可实现方式较多:

3.5.1、有线发送(最简单可靠)

单片机输出的编码信号通过导线直接送入接收端输入口。优点:

  • 抗干扰强,误码率低
  • 电路简单,便于验证EAN编码与解码算法
    缺点:
  • 不具备无线特性,距离受限

3.5.2、红外发送(常用于遥控)

发射端用红外LED发射调制信号,接收端用红外接收头(如HS0038)接收。优点:

  • 成本低、距离适中
  • 抗可见光干扰能力较好(接收头自带滤波)
    缺点:
  • 红外接收头通常要求38kHz载波调制,需要将条码序列再调制到38kHz载波上
  • 解码更复杂,但更贴近实际通信应用

3.5.3、射频发送(433MHz ASK模块)

使用433MHz发射模块发送编码数据,接收端用433MHz接收模块。优点:

  • 距离远
  • 不需要严格对准
    缺点:
  • 噪声大,需要软件同步与滤波
  • 易受环境干扰,需要协议与校验

为了实现难度适中且符合"模拟条码编码发送"要求,本设计推荐:

  • 教学实验:采用有线发送或433MHz RF模块发送
  • 若要求更高可玩性:采用红外38k调制方式

无论采用哪种方式,核心思想是:将95模块条码序列转换为时间波形输出,并在接收端恢复该序列。


3.6、接收模块与信号整形

接收模块输出信号往往存在:

  • 抖动(边沿漂移)
  • 幅度不稳定
  • 噪声毛刺
  • 翻转延迟

因此需要信号整形:

1)RC滤波(抑制高频毛刺)

2)施密特触发器或带施密特输入的单片机IO(形成干净的数字边沿)

3)必要时采用比较器将模拟信号转换为数字信号

若使用433MHz接收模块,其输出常为带噪声的数字波形,建议加入:

  • 施密特触发器(74HC14)
  • 软件上增加多次采样判决(多数表决)
    以提高可靠性。

3.7、报警与提示模块(可选)

接收端可加入蜂鸣器或指示灯用于提示:

  • 接收完成提示
  • 校验通过提示(短鸣)
  • 校验失败提示(长鸣)
  • 信号异常提示(闪烁)

该模块属于增强交互体验部分,可不影响核心功能实现。


4、程序设计

4.1、软件总体架构与流程

系统软件同样分为发射端程序与接收端程序。

发射端流程:

1)初始化:键盘、显示、定时器、发送IO

2)等待用户输入EAN码

3)用户确认后,若只输入12位则自动计算校验位形成13位

4)生成EAN13条码95模块序列(0/1数组)

5)按模块周期输出波形并发送

6)发送完成后进入空闲间隔,等待下一次发送

接收端流程:

1)初始化:接收IO、外部中断或定时器、显示

2)持续监听起始符并同步采样

3)采样95模块序列并缓存

4)按EAN13解码规则解析为13位数字

5)校验位验证

6)显示数字与校验结果

7)返回监听状态

为了提高可靠性,接收端可设计为"状态机":

  • WAIT_START:等待起始符 101
  • RECV_BITS:接收95位模块序列
  • DECODE:解码
  • SHOW:显示
  • ERROR:错误处理后回到WAIT_START

这样逻辑清晰,便于调试。


4.2、EAN13编码规则模块(发射端)

EAN13编码核心在于"左侧A/B编码表、右侧C编码表、首位决定左侧奇偶模式"。程序需要准备:

1)A编码表(L-code odd parity)

2)B编码表(L-code even parity)

3)C编码表(R-code)

4)首位对应的奇偶模式表(6位模式)

编码过程:

  • 输入13位数字 d[0..12]
  • 根据 d[0] 找到左侧6位奇偶模式,如 ABBAAB
  • d[1..6] 逐位按模式选择A或B表转换成7位条纹
  • d[7..12] 逐位按C表转换成7位条纹
  • 拼接起始符、中心符、终止符得到95位序列

为了便于输出,可将95位序列存入数组 frame[95],每个元素为0/1。


4.3、校验位计算模块(发射端与接收端共用)

校验位计算用于:

  • 发射端:输入12位时自动生成校验位
  • 接收端:接收解码后校验是否正确

校验算法(前12位):

  • 奇数位(1,3,5...11)求和 ×1
  • 偶数位(2,4,6...12)求和 ×3
  • sum = odd_sum + 3*even_sum
  • check = (10 - (sum % 10)) % 10

接收端比较 check 与第13位是否相等即可判断正确性。


4.4、发送波形生成与输出模块(发射端)

发射端将95位序列转换为电平波形输出。关键点:

  • 模块宽度固定(例如2ms)
  • 每2ms输出frame[i]对应电平
  • 输出完成后加入空闲间隔(例如100ms)作为帧分隔

输出方法:

  • 使用定时器中断,每次中断输出下一位
  • 或在主循环中延时输出(不推荐,会影响键盘与显示)

采用定时器中断方式更稳定,也更贴近实际通信系统。


4.5、接收采样与同步模块(接收端)

接收端的难点在于:如何确定模块边界并正确采样95位序列。为了简化实现,可采取以下策略:

1)发射端先发送"前导同步序列"(例如连续16个101010...),接收端通过检测该序列估算模块周期并同步

2)检测到起始符 101 后,在固定间隔内采样后续模块

3)采用多数表决采样:在一个模块周期中采样多次取多数值,提高抗噪声能力

由于题目未明确要求前导码,但在工程实现中加入前导码能大幅提高可靠性,因此建议设计为:

  • 前导码(Preamble):101010...共32模块
  • 正式条码帧:95模块

接收端检测到稳定前导码后进入正式接收,能显著降低起始同步失败概率。


4.6、EAN13解码模块(接收端)

接收端将95模块序列解码为数字,关键步骤:

1)验证起始符、中心符、终止符是否正确

2)提取左侧42模块和右侧42模块,每7模块为一组

3)对左侧6组,分别匹配A表或B表,得到数字并记录其属于A还是B

4)根据6位A/B模式反推首位数字(d0)

5)对右侧6组,匹配C表得到数字

6)组合为13位EAN码

其中第4步是EAN13解码特有的关键:首位数字不直接编码在条纹中,而是通过左侧奇偶模式隐含表示。因此解码端必须根据左侧6位的奇偶模式反查首位。


4.7、显示与键盘交互模块

接收端显示:

  • 第一行显示EAN13数字
  • 第二行显示状态与校验结果(OK/ERR)

发射端显示(可选):

  • 显示正在输入的数字与当前模式(12位/13位)
  • 显示生成校验位与发送状态

键盘模块需包含:

  • 扫描、消抖
  • 输入缓冲区管理(最多13位)
  • 删除、清空、确认逻辑
  • 输入合法性检查(只能输入数字)

5、核心代码示例(关键模块)

5.1、EAN13编码表与奇偶模式表

c 复制代码
// EAN13编码表:每个数字对应7位模块,字符'0'/'1'
const char *EAN_A[10] = {
    "0001101","0011001","0010011","0111101","0100011",
    "0110001","0101111","0111011","0110111","0001011"
};
const char *EAN_B[10] = {
    "0100111","0110011","0011011","0100001","0011101",
    "0111001","0000101","0010001","0001001","0010111"
};
const char *EAN_C[10] = {
    "1110010","1100110","1101100","1000010","1011100",
    "1001110","1010000","1000100","1001000","1110100"
};

// 首位数字决定左侧6位奇偶模式(A=0, B=1)
const char *EAN_PARITY[10] = {
    "000000", // 0: AAAAAA
    "001011", // 1: AABABB
    "001101", // 2: AABBAB
    "001110", // 3: AABBBA
    "010011", // 4: ABAABB
    "011001", // 5: ABBAAB
    "011100", // 6: ABBBAA
    "010101", // 7: ABABAB
    "010110", // 8: ABABBA
    "011010"  // 9: ABBABA
};

5.2、校验位计算函数

c 复制代码
// 输入:12位数字字符串,如 "690123456789"
// 输出:校验位 0~9
u8 EAN13_CalcCheck(const char *d12)
{
    u8 i;
    u16 sum_odd = 0, sum_even = 0;

    for(i = 0; i < 12; i++)
    {
        u8 v = d12[i] - '0';
        if((i % 2) == 0) sum_odd += v;   // 1,3,5...(下标0,2,4...)
        else sum_even += v;             // 2,4,6...
    }

    u16 sum = sum_odd + 3 * sum_even;
    u8 mod = sum % 10;
    return (10 - mod) % 10;
}

5.3、生成95模块条码帧(发射端)

c 复制代码
// 输入:13位EAN字符串,如 "6901234567892"
// 输出:frame[95],每位为0/1
void EAN13_BuildFrame(const char *ean13, u8 frame[95])
{
    u8 pos = 0;
    u8 i;

    // 起始符 101
    frame[pos++] = 1; frame[pos++] = 0; frame[pos++] = 1;

    // 左侧奇偶模式
    u8 first = ean13[0] - '0';
    const char *par = EAN_PARITY[first];

    // 左侧6位:ean13[1..6]
    for(i = 0; i < 6; i++)
    {
        u8 d = ean13[1+i] - '0';
        const char *code = (par[i] == '0') ? EAN_A[d] : EAN_B[d];

        u8 k;
        for(k = 0; k < 7; k++)
            frame[pos++] = (code[k] == '1') ? 1 : 0;
    }

    // 中间符 01010
    frame[pos++] = 0; frame[pos++] = 1; frame[pos++] = 0; frame[pos++] = 1; frame[pos++] = 0;

    // 右侧6位:ean13[7..12](含校验位)
    for(i = 0; i < 6; i++)
    {
        u8 d = ean13[7+i] - '0';
        const char *code = EAN_C[d];

        u8 k;
        for(k = 0; k < 7; k++)
            frame[pos++] = (code[k] == '1') ? 1 : 0;
    }

    // 终止符 101
    frame[pos++] = 1; frame[pos++] = 0; frame[pos++] = 1;
}

5.4、发送模块(定时器中断输出波形)

c 复制代码
// 假设TX引脚输出条码模块(1=高电平 0=低电平)
sbit TX = P1^0;

volatile u8 tx_busy = 0;
volatile u8 tx_idx = 0;
u8 tx_frame[95];

void TX_Start(u8 frame[95])
{
    u8 i;
    for(i=0;i<95;i++) tx_frame[i]=frame[i];

    tx_busy = 1;
    tx_idx = 0;
}

// 定时器中断:每个模块周期触发一次(例如2ms)
void Timer1_ISR(void) interrupt 3
{
    if(tx_busy)
    {
        TX = tx_frame[tx_idx];
        tx_idx++;

        if(tx_idx >= 95)
        {
            TX = 0;
            tx_busy = 0;
        }
    }
}

5.5、接收端帧采样与解码框架(简化示例)

c 复制代码
sbit RX = P3^2;

u8 rx_frame[95];
u8 rx_idx = 0;
bit rx_collecting = 0;

void RX_Reset(void)
{
    rx_idx = 0;
    rx_collecting = 0;
}

// 简化:检测到起始符后按固定周期采样95位
// 实际工程可用外部中断检测边沿 + 定时器对齐采样
void RX_SampleBit(void)
{
    if(rx_collecting)
    {
        rx_frame[rx_idx++] = RX ? 1 : 0;
        if(rx_idx >= 95)
        {
            rx_collecting = 0;
            // Decode_EAN13(rx_frame,...);
        }
    }
}

// 检测起始符101(需要缓存最近3位)
void RX_DetectStart(void)
{
    static u8 sh = 0;

    sh = ((sh << 1) | (RX ? 1 : 0)) & 0x07;

    if(!rx_collecting && sh == 0x05) // 101
    {
        rx_collecting = 1;
        rx_idx = 0;
        rx_frame[rx_idx++] = 1;
        rx_frame[rx_idx++] = 0;
        rx_frame[rx_idx++] = 1;
    }
}

6、系统关键问题与工程优化

6.1、同步与采样精度对识别成功率的决定作用

条码识别的核心困难不是编码表,而是"采样时钟对齐"。若接收端采样点偏移一个模块宽度,就会造成整体错位,解码失败。因此工程中必须考虑:

  • 前导码同步
  • 起始符检测可靠性
  • 模块周期稳定性
  • 多次采样多数表决

在教学系统中,可通过降低传输速率(增大模块宽度),例如5ms/模块,显著降低时序误差,使识别更容易成功。

6.2、信号整形与抗干扰

无线模块(尤其433MHz接收模块)输出噪声较大,若直接接入单片机IO,可能产生大量毛刺导致起始符误触发。建议:

  • 硬件加74HC14施密特触发整形
  • 软件加滤波(例如在模块周期内采样3次取多数)
  • 采用帧校验(起始符/中心符/终止符检查)排除错误帧

6.3、解码容错与错误处理机制

接收端解码应包含严格校验:

  • 起始符、中心符、终止符必须匹配
  • 左侧每组必须能匹配A或B表,否则判为无效
  • 右侧每组必须能匹配C表,否则判为无效
  • 校验位必须通过,否则显示ERR

当出现错误时应:

  • 立即丢弃当前帧并返回WAIT_START
  • 显示"ERR"并可蜂鸣提示
    这样可避免错误数据影响后续帧识别。

6.4、键盘输入的用户体验与校验提示

键盘输入EAN码时,若用户输入12位应自动补齐校验位,并显示:

  • "CHECK=2"
    若用户输入13位,可提示:
  • "CHK OK"或"CHK ERR"
    这样能帮助用户理解EAN13校验机制,也能增强系统可用性。

7、总结

基于单片机的条形码识别系统设计以EAN13标准为核心,采用发射机模拟条形码编码并通过单片机发送到接收机的方式,实现了条码编码生成、信号调制传输、接收同步采样、EAN13解码、校验位验证与显示输出等完整流程。系统支持通过键盘输入编码并自由修改EAN值,使发射端能够灵活发送不同条码数据,接收端能够实时显示接收到的编码并提示校验结果,形成一套可用于教学实验、算法验证与通信识别训练的完整平台。

在电路设计方面,系统包含发射端键盘输入与发射驱动模块、接收端信号整形与显示模块,并强调了同步与抗干扰的重要性;在程序设计方面,系统采用表驱动EAN编码与状态机解码策略,结合定时器完成稳定的模块输出与采样,能够可靠实现EAN13条码识别。通过进一步扩展,可增加真实光电扫描头、上位机串口显示、无线协议封装、数据存储与统计等功能,使系统更贴近实际商品条码识别应用场景。

相关推荐
我先去打把游戏先12 小时前
TCP、TLS、HTTP、HTTPS、MQTT、MQTTS几种网络协议的对比与解释
嵌入式硬件·mcu·物联网·网络协议·tcp/ip·http·aws
IT方大同12 小时前
实时时钟RTC
嵌入式硬件·实时音视频
点灯小铭13 小时前
基于单片机的社区医院小型高压蒸汽灭菌自动控制器设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
youcans_13 小时前
【动手学STM32G4】(3)STM32G431之定时器
stm32·单片机·嵌入式硬件·定时器
悠哉悠哉愿意13 小时前
【嵌入式学习笔记】AD/DA
笔记·单片机·嵌入式硬件·学习
松涛和鸣13 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html
阿凉070213 小时前
新版本JLink安装目录中缺失JLinkDevices.xml添加方法
xml·嵌入式硬件
范纹杉想快点毕业13 小时前
《嵌入式通信与数据管理:从状态机到环形队列的完整实战指南》
单片机·嵌入式硬件
点灯小铭14 小时前
基于单片机的硫化氢、氨气、甲烷、一氧化碳气体多种有害气体检测与声光报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
小李做物联网14 小时前
【单片机毕设】c24基于单片机stm32蓝牙温室大棚物联网毕业设计
stm32·单片机·嵌入式硬件·物联网