最近设计了一个项目基于单片机的超市收银设计,与大家分享一下:
一、基本介绍
项目名:超市收银
项目编号:mcuclub-dz-082
单片机类型:STC89C52
具体功能:
1、通过RFID-RC522刷卡模块实现刷卡,三种卡,显示三种商品、单价、数量;
2、通过HX711压力传感器模块实现称重,固定单价,根据重量得出价格;
3、通过三个按键切换“刷卡”,“称重”,“结账”功能,通过白卡刷入,一个LED灯提示结账成功;
4、通过另一个按键进行防盗开关,如果防盗开,则经过的RFID卡都要进行3s蜂鸣器报警
5、通过LCD1602显示屏显示数据
6、通过蓝牙,将购买的商品信息发送到电脑端
二、51实物图
单片机型号:STC89C52
板子为绿色PCB板,两层板,厚度1.2,上下覆铜接地。元器件基本上为插针式,个别降压芯片会使用贴片式。
供电接口:TYPE-C
三、原理图
软件版本:AD2013
电路连线方式:网络标号连线方式
注意:原理图只是画出了模块的引脚图,而并不是模块的内部结构原理图
四、PCB图
由原理图导出,封装很大一部分都是作者自己绘制,不提供封装库,只提供连接好的源文件。中间有一个项目编号,隐藏在单片机底座下,插入单片机后不会看到。
两层板,上下覆铜接地。
五、系统框图
本设计以单片机为核心控制器,加上其他模块一起组成此次设计的整个系统,其中包括中控部分、输入部分和输出部分。中控部分采用了单片机控制器,其主要作用是获取输入部分的数据,经过内部处理,逻辑判断,最终控制输出部分。输入由四部分组成,第一部分是称重模块,通过该模块检测当前商品的重量;第二部分是RFID刷机模块,通过该模块可以获取当前商品;第三部分是按键模块,通过该模块可以切换模块、开启防盗等;第四部分是供电模块,通过该模块可给整个系统进行供电。输出由两个部分组成,第一部分是显示模块,通过该模块可以显示商品的名称、价格和售价;第二部分是声光报警模块,防盗打开,监测到有RFID刷卡时进行声光报警。除此之外,蓝牙模块既作为输入又作为输出,蓝牙模块和手机进行连接,可以将监测的数据传输到用户手机端。具体系统框图如图3.1所示。
六、软件设计流程
七、部分程序展示
软件版本:keil5
逻辑程序和驱动程序分开,分布于main.c和其他.c文件
*******显示函数
*****/
void Display_function(void)
{
switch(flag_mode) //根据不同的模式标志位,显示不同的界面内容
{
case 0: //初始界面,显示“Welcome”
lcd1602_display_str(1,0," Welcome ");
lcd1602_display_str(2,0," ");
break;
case 1: //刷卡界面
lcd1602_display_str(1,0,"Name:"); //显示商品名称
lcd1602_display_str(2,0,"Price:"); //显示商品单价
break;
case 2: //称重界面
lcd1602_display_str(1,0,"Price:10Y/kg "); //显示商品单价
lcd1602_display_str(2,0,"W:"); //显示商品重量
lcd1602_display_str(2,8,"C:"); //显示商品总价
break;case 3: //结账界面
lcd1602_display_str(1,0," Aggregate "); //显示“Aggregate”
break;
case 4: //防盗界面
lcd1602_display_str(1,0," Anti-theft "); //显示“Anti-theft”
break;default:
break;
}
}/****
*******处理函数
*****/
void Manage_function(void)
{
switch(flag_mode)
{
case 1: //刷卡模式
if(RC522_Request(0x52,RF_TP) == MI_OK) //实时检测卡
{
if(RC522_Anticoll(RF_ID) == MI_OK) //防冲撞
{
BEEP = 0;
Delay_function(100);
BEEP = 1;
sprintf(display_buf,"%x%x%x%x",RF_ID[0],RF_ID[1],RF_ID[2],RF_ID[3]);
lcd1602_display_str(1,5,display_buf);
if((RF_ID[0]==0x93) && (RF_ID[1]==0xE8) && (RF_ID[2]==0x45) && (RF_ID[3]==0x90)) //对比卡号
{
num_xuebi++; //雪碧数量+1
sprintf(display_buf,"XueBi *%d ",num_xuebi);
lcd1602_display_str(1,5,display_buf); //显示商品名称及数量
sprintf(display_buf,"%dY ",(num_xuebi*3));
lcd1602_display_str(2,6,display_buf); //显示商品价格
total_money += 3;
Delay_function(1000);
}
if((RF_ID[0]==0xF3) && (RF_ID[1]==0x9B) && (RF_ID[2]==0xE5) && (RF_ID[3]==0xB6)) //对比卡号
{
num_kele++; //可乐数量+1
sprintf(display_buf,"KeLe *%d ",num_kele);
lcd1602_display_str(1,5,display_buf); //显示商品名称及数量
sprintf(display_buf,"%dY ",(num_kele*3));
lcd1602_display_str(2,6,display_buf); //显示商品价格
total_money += 3;
Delay_function(1000);
}
if((RF_ID[0]==0xE3) && (RF_ID[1]==0x30) && (RF_ID[2]==0x75) && (RF_ID[3]==0x92)) //对比卡号
{
num_fenda++; //芬达数量+1
sprintf(display_buf,"FenDa *%d ",num_fenda);
lcd1602_display_str(1,5,display_buf); //显示商品名称及数量
sprintf(display_buf,"%dY ",(num_fenda*4));
lcd1602_display_str(2,6,display_buf); //显示商品价格
total_money += 4;
Delay_function(1000);
}
}
}
break;
case 2: //称重模式
if(flag_weight == 0)
{
weight_maopi = Hx711_Get_Maopi(); //获取毛皮重量
flag_weight = 1;
}
if(flag_weight == 1)
{
weight_value = Hx711_Get_Weight(weight_maopi) / 100;//获取总重量
sprintf(display_buf,"%d.%dkg",weight_value/10,weight_value%10);
lcd1602_display_str(2,2,display_buf); //显示商品重量
money_weight = weight_value;
sprintf(display_buf,"%dY ",money_weight);
lcd1602_display_str(2,10,display_buf); //显示商品价格
if(flag_price == 1)
{
weight_value_old += weight_value;
price_all += money_weight;
flag_price = 0;
}
}
break;
case 3: //结账模式
if(RC522_Request(0x52,RF_TP) == MI_OK) //实时检测卡
{
if(RC522_Anticoll(RF_ID) == MI_OK) //防冲撞
{
if(flag_card == 0) //会员卡只允许刷一次
{
BEEP = 0;
Delay_function(100);
BEEP = 1;
if((RF_ID[0]==0xF2) && (RF_ID[1]==0xFB) && (RF_ID[2]==0xB4) && (RF_ID[3]==0x19)) //对比卡号
{
flag_card = 1; //刷卡成功
}
}
}
}
sprintf(display_buf,"%.2fY ",(flag_card?((total_money+price_all)*0.8):(total_money+price_all)));
lcd1602_display_str(2,5,display_buf); //显示商品总计价格
break;
case 4: //防盗模式,刷卡后报警3秒
if(RC522_Request(0x52,RF_TP) == MI_OK) //实时检测卡
{
if(RC522_Anticoll(RF_ID) == MI_OK) //防冲撞
{
BEEP = 0;
Delay_function(3000);
BEEP = 1;
}
}
break;
default:
break;
}
}