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条码识别。通过进一步扩展,可增加真实光电扫描头、上位机串口显示、无线协议封装、数据存储与统计等功能,使系统更贴近实际商品条码识别应用场景。