本设计包括两个终端,包括负责水卡充值(可选择金额)的充值终端和每次刷卡扣费两元的付费终端。制作成品时建议两个终端做在一块板子上,用跳帽切换两个51单片机的电源。
主控芯片51单片机
射频模块RC522
射频卡M1卡S50
以下是付费终端的程序,其他详见附件
- #include "reg52.h"
- #include "main.h"
- #include "mfrc522.h"
- #include<intrins.h> //函数处理头文件
- #include<string.h> //字符串处理头文件
- #include<stdio.h> // 输入输出函数头文件
- unsigned char code data1[16] = {0x00,0x00,0x00,0x00,0xff,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0xFE,0x01,0xFE};
- //M1卡的某一块写为如下格式,则该块为钱包,可接收扣款和充值命令
- //4字节金额(低字节在前)+4字节金额取反+4字节金额+1字节块地址+1字节块地址取反+1字节块地址+1字节块地址取反
- unsigned char data2[4] = {0x00,0x00,0x00,0x00};//存值减值金额
- unsigned char code DefaultKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; //密码
- unsigned char TYPE_DATA[2]; //类型
- unsigned char ID_DATA[4]; //ID地址
- unsigned char value_DATA[4]; //卡里面的值
- unsigned char g_ucTempbuf[20]; //卡号
- unsigned char code dis0[] = {"S50"};
- unsigned char code dis1[] = {"S70"};
- unsigned char code dis2[] = {"X"};
- unsigned char code dis3[] = {"44"};
- unsigned char code dis4[] = {"ID:"};
- unsigned char code dis5[] = {"RMB:"};
- unsigned char code dis6[] = {"0123456789ABCDEF"};
- unsigned int tt=0,a=2,b,falg_pro; //falg_pro声音提示标志
- void main( )
- {
- unsigned char status;
- InitializeSystem( ); //初始化
- PcdReset(); //复位RC522
- PcdAntennaOff(); //关闭天线
- PcdAntennaOn(); //开启天线
- data2[1]=a/256;
- data2[0]=a%256;
- while ( 1 )
- {
- status = PcdRequest(PICC_REQALL, g_ucTempbuf); //返回卡片类型#define PICC_REQIDL 0x26 寻天线区内未进入休眠状态
- if(status!= MI_OK) //读不到卡,显示清0;
- {
- TYPE_DATA[0]=0;
- TYPE_DATA[1]=0;
- ID_DATA[0]=0;
- ID_DATA[1]=0;
- ID_DATA[2]=0;
- ID_DATA[3]=0;
- value_DATA[0]=0;
- value_DATA[1]=0;
- value_DATA[2]=0;
- value_DATA[3]=0;
- falg_pro=0;
- b=0;
- }
- if (status == MI_OK)
- {
- TYPE_DATA[0]=g_ucTempbuf[0];
- TYPE_DATA[1]=g_ucTempbuf[1];
- status = PcdAnticoll(g_ucTempbuf); //防冲撞 ,返回卡片ID号 4字节
- if (status == MI_OK)
- {
- status = PcdSelect(g_ucTempbuf); //选定卡片 ,输入卡片ID号
- if (status == MI_OK)
- {
- if(falg_pro==0)//声音提示标志
- {
- falg_pro=1;
- pro();
- }
- ID_DATA[0]=g_ucTempbuf[0];
- ID_DATA[1]=g_ucTempbuf[1];
- ID_DATA[2]=g_ucTempbuf[2];
- ID_DATA[3]=g_ucTempbuf[3];
- init_k();//初始化卡
- writek();//写卡
- readk();
-
- }
- }
- }
- LCD1206();//显示处理
- PcdHalt();//命令卡片进入休眠状态
- }
- }
- /////////////////////////////////////////////////////////////////////
- //系统初始化
- /////////////////////////////////////////////////////////////////////
- void InitializeSystem()
- {
- P0 = 0xFF;
- P1 = 0xFF;
- P2 = 0xFF;
- P3 = 0xFF;
- fmq=0; //fmp喇叭
- fmq=1;
- lcd_init(); // 初始化LCD
- Delay(1);
- }
- void Delay(unsigned int time)
- {
- unsigned int i,k ;
- for(i=0;i<150;i++)
- for(k=0;k<time;k++)
- _nop_();
- }
- void Delay2(unsigned int time2)
- {
- unsigned int i,k ;
- for(i=0;i<5;i++)
- for(k=0;k<time2;k++)
- _nop_();
- }
- ////////////////////////显示处理函数////////////////////////////////
- bit lcd_bz() // 测试LCD忙碌状态
- {
- bit result;
- rs = 0;
- rw = 1;
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- result = (bit)(P0 & 0x80);
- ep = 0;
- return result;
- }
- lcd_wcmd(unsigned char cmd)// 写入指令数据到LCD
- {
- while(lcd_bz());
- rs = 0;
- rw = 0;
- ep = 0;
- _nop_();
- _nop_();
- P0 = cmd;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- return 0;
- }
- lcd_pos(unsigned char pos)
- { //设定显示位置
- lcd_wcmd(pos | 0x80);
- return 0;
- }
- lcd_wdat(unsigned char dat)
- { //写入字符显示数据到LCD
- while(lcd_bz());
- rs = 1;
- rw = 0;
- ep = 0;
- P0 = dat;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 1;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- ep = 0;
- return 0;
- }
- lcd_init() //LCD初始化设定
- {
- lcd_wcmd(0x38); //
- Delay(1);
- lcd_wcmd(0x0c); //
- Delay(1);
- lcd_wcmd(0x06); //
- Delay(1);
- lcd_wcmd(0x01); //清除LCD的显示内容
- Delay(1);
- return 0;
- }
- LCD1206()
- {
- unsigned char i;
- lcd_pos(0x01); // 设置显示位置为第一行的第0个字符
- i = 0;
- switch(TYPE_DATA[0])
- {
- case 0x04:
- lcd_wdat(dis0[0]); //dis0[] = {"S50"};
- lcd_wdat(dis0[1]);
- lcd_wdat(dis0[2]);
- break;
- case 0x02:
- lcd_wdat(dis1[0]); //dis1[] = {"S70"};
- lcd_wdat(dis1[1]);
- lcd_wdat(dis1[2]);
- break;
- case 0x08: //dis2[] = {"X"};
- lcd_wdat(dis2[0]);
- break;
- case 0x44:
- lcd_wdat(dis3[0]); //dis3[] = {"44"};
- lcd_wdat(dis3[1]);
- break;
- }
- lcd_pos(0x05); // 设置显示位置为第一行的第5个字符
- lcd_wdat(dis4[0]); //dis4[] = {"ID:"};
- lcd_wdat(dis4[1]);
- lcd_wdat(dis4[2]);
- lcd_pos(0x08); // 设置显示位置为第一行的第5个字符
- lcd_wdat(dis6[ID_DATA[0]/16]); //dis6[] = {"0123456789ABCDEF"};
- lcd_wdat(dis6[ID_DATA[0]%16]);
- lcd_wdat(dis6[ID_DATA[1]/16]);
- lcd_wdat(dis6[ID_DATA[1]%16]);
- lcd_wdat(dis6[ID_DATA[2]/16]);
- lcd_wdat(dis6[ID_DATA[2]%16]);
- lcd_wdat(dis6[ID_DATA[3]/16]);
- lcd_wdat(dis6[ID_DATA[3]%16]);
- lcd_pos(0x40); // 设置显示位置为第二行第二个字符
- lcd_wdat(dis5[0]); //dis5[] = {"RMB:"};
- lcd_wdat(dis5[1]);
- lcd_wdat(dis5[2]);//
- lcd_wdat(dis5[3]);// 人民币
- lcd_wdat(dis6[0]);
- lcd_wdat(dis6[2]);
-
- lcd_pos(0x47); // 设置显示位置为第二行第二个字符
- lcd_wdat(dis5[0]);
- lcd_wdat(dis5[1]);
- lcd_wdat(dis5[2]);//
- lcd_wdat(dis5[3]);// 人民币
- lcd_pos(0x4b);
- lcd_wdat(dis6[b/10000]);
- lcd_wdat(dis6[b%10000/1000]);
- lcd_wdat(dis6[b%10000%1000/100]);
- lcd_wdat(dis6[b%10000%1000%100/10]);
- lcd_wdat(dis6[b%10000%1000%100%10]);
- return 0;
- }
- void pro()
- {
- fmq=0;
- TMOD=0x11;//设置定时器0为工作方式1
- TH0=(65536-50000)/256;//给定时器装初值 高八位
- TL0=(65536-50000)%256;//给定时器装初值 低八位
- EA=1; //开总中断
- ET0=1; //开定时器0中断
- TR0=1; //启动定时器0
- }
- void time0() interrupt 1// 中断服务子程序 声音时间一致
- {
- TH0=(65536-50000)/256;//给定时器装初值 高八位
- TL0=(65536-50000)%256;//给定时器装初值 低八位
- tt++;
- if(tt==3)
- {
- tt=0;
- fmq=1;
- EA=0; //关总中断
- ET0=0; //关定时器0中断
- TR0=0; //关定时器0
- }
- }
- void readk()//读卡
- {
- unsigned char status;
- status = PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, g_ucTempbuf);//PICC_AUTHENT1A 验证密码模式60A密码 61B密码,“1”块地址,DefaultKey初始密码,g_ucTempbuf ID号
- if (status == MI_OK) //验证密码
- {
- status = PcdRead(1, g_ucTempbuf);//读块地址“1”的数据,返回值存在 g_ucTempbuf
- if (status == MI_OK)
- {
- value_DATA[0]=g_ucTempbuf[0];
- value_DATA[1]=g_ucTempbuf[1];
- value_DATA[2]=g_ucTempbuf[2];
- value_DATA[3]=g_ucTempbuf[3];
- b=value_DATA[0]+value_DATA[1]*256;
- }
- }
- }
- void writek()//写卡 存值或减值
- {
- unsigned char status;
- status = PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, g_ucTempbuf);//PICC_AUTHENT1A 验证密码模式60A密码 61B密码,“1”块地址,DefaultKey初始密码,g_ucTempbuf ID号
- if (status == MI_OK) //验证密码
- {
- if(1) //扣款
- {
- if(b>1)
- {
- status = PcdValue(PICC_DECREMENT,1,data2);//扣款存值命令,钱包地址,金额 低位在前 PICC_INCREMENT 充值
- if (status == MI_OK)
- {
- pro();
- }
- status = PcdBakValue(1, 2); //备份钱包 “1”源地址“2”目标地址
- Delay(1000);
- b=b-2;
- }
- else
- {
- unsigned int x;
- for(x=1;x<4000;x++)
- {
- fmq=1;
- Delay2(1);
- fmq=0;
- }
- }
-
- }
- }
- }
- void init_k()//初始化卡
- {
- unsigned char status;
- if(key1==0) //充值
- {
- status = PcdAuthState(PICC_AUTHENT1A, 1, DefaultKey, g_ucTempbuf);//PICC_AUTHENT1A 验证密码模式60A密码 61B密码,“1”块地址,DefaultKey初始密码,g_ucTempbuf ID号
- if (status == MI_OK) //验证密码
- {
- status = PcdWrite(1, data1);//4字节金额(低字节在前)+4字节金额取反+4字节金额+1字节块地址+1字节块地址取反+1字节块地址+1字节块地址取反
- if (status == MI_OK)
- {
- pro();
- }
- }
- }
- }
复制代码 全部程序51hei下载地址:
注册程序.rar
(90.98 KB, 下载次数: 84)
刷卡程序.rar
(88.79 KB, 下载次数: 106)
|