系统组成
主控单元:51单片机(如STC89C52)作为核心控制器,协调各模块工作。
扫描模块:GM65条码扫描头,支持二维码/条形码识别,通过串口(UART)与单片机通信。
显示模块:LCD1602液晶屏,用于显示扫描结果及系统状态(两行16字符)。
辅助电路:电源稳压、按键控制(可选)、蜂鸣器(扫描成功提示)等。
硬件设计
GM65与单片机连接
GM65的
TXD
接单片机RXD
(P3.0),RXD
接单片机TXD
(P3.1),共地处理。模块供电需稳定(5V/3.3V),建议独立电源或添加滤波电容。
LCD1602显示接口
使用并口模式:数据线(D0-D7)接P0口,控制线(RS、RW、EN)接P2口。
或通过I2C转接板(如PCF8574)简化连线,节省IO资源。
其他外设
按键:用于触发扫描或清除显示(可选)。
蜂鸣器:扫描成功时鸣响反馈。
软件流程
初始化
配置串口:设置波特率(如9600bps)、数据格式(8N1)匹配GM65。
初始化LCD1602:清屏、设置显示模式及光标。
扫描与数据处理
触发扫描:GM65设置为自动感应模式(或通过按键触发)。
数据接收:单片机通过串口中断接收GM65发送的条码数据。
数据解析:提取有效信息(如去除帧头帧尾、校验数据完整性)。
结果显示
短文本直接显示(如商品条码数字)。
长文本滚动显示或截取关键字段(如URL二维码显示首尾字符)。
错误提示:显示“Error”或“Invalid Code”等状态
#include <REGX52.H>
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"
#include "string.h"
#include "UART.h"
#include <stdio.h>
#define BUF_SIZE 64
unsigned char KeyNum;
unsigned int Num;
unsigned char len;
char UartBuf[BUF_SIZE]; // 串口接收缓冲区
unsigned char UartCnt = 0; // 接收计数器
unsigned char flag;
void main()
{
// 初始化LCD屏幕
LCD_Init();
// 在LCD上显示"Data:"
LCD_ShowString(1, 1, "Data:");
// 清空第二行,用于后续显示数据
LCD_ShowString(1, 6, " "); // 清空第二行
LCD_ShowString(2, 1, " "); // 清空第二行
// 初始化UART1
Uart1_Init();
while (1)
{
// 获取按键值
KeyNum = Key();
// 当UART缓冲区中有新数据且标志位为1时
if (UartBuf[0] != '\0' && flag == 1) // 有新数据到达
{
// 计算字符串长度
len = strlen(UartBuf);
flag = 0;
// 清空两行显示,为显示新数据做准备
LCD_ShowString(1, 6, " "); // 清空第二行
LCD_ShowString(2, 1, " "); // 清空第二行
// 优先在第一行显示
if (len <= 11) // 第一行剩余空间足够时,直接显示在第一行"Data:"之后显示全部字符
{
// 从第6列开始显示数据
LCD_ShowString(1, 6, UartBuf);
LCD_ShowString(2, 1, " "); // 清空第二行
}
// 第一行剩余空间不足时换到第二行
else if (len <= 27) // 11(第一行剩余)+16(第二行)
{
// 显示前11个字符在第一行"Data:"之后
char firstLinePart[12];
strncpy(firstLinePart, UartBuf, 11);
firstLinePart[11] = '\0';
LCD_ShowString(1, 6, firstLinePart);
// 显示剩余字符在第二行
LCD_ShowString(2, 1, UartBuf + 11);
}
// 超过27字符截断显示
else
{
char displayBuf[28];
strncpy(displayBuf, UartBuf, 27);
displayBuf[27] = '\0';
// 显示前11个字符在第一行"Data:"之后
LCD_ShowString(1, 6, displayBuf);
// 显示剩余16个字符在第二行
LCD_ShowString(2, 1, displayBuf + 11);
}
// 打印UART缓冲区中的数据
printf("UartRoutine: %s\r\n", UartBuf);
len = 0;
// 清空UART缓冲区
memset(UartBuf, '\0', BUF_SIZE); // 清空缓冲区
}
if (KeyNum == 1) // K1按键,Num自增
{
KeyNum = 0;
P3_4=!P3_4; //按键切换模块开启
// printf("hello\r\n");
}
}
}
void UART_Routine() interrupt 4
{
if (RI == 1) // 如果接收标志位为1,接收到了数据
{
if (UartCnt < BUF_SIZE - 1) // 缓冲区未满
{
if (SBUF == '\n' || SBUF == '\r' || SBUF == '\x0d') // 接收到换行符
{
UartBuf[UartCnt] = '\0'; // 字符串结束符
flag = 1;
// len=UartCnt;
UartCnt = 0;
}
else
{
UartBuf[UartCnt++] = SBUF; // 存储接收到的字符
}
}
else // 缓冲区已满
{
UartBuf[BUF_SIZE - 1] = '\0'; // 强制结束字符串
UartCnt = 0;
}
// UART_SendByte(SBUF); // 将收到的数据发回串口
RI = 0; // 接收标志位清0
}
}
单片机定制: