如題,在導入程序后運行出現如下圖所示的狀況。求助如何解決
基于STC89C52的IC智能水卡程序設計問題
5887ED4A-FA0C-4D92-8712-F915BC6F54AE.jpeg (1.85 MB, 下載次數: 72)
下載附件
2019-3-30 00:11 上傳
主程序
- #include "reg52.h"
- #include "main.h"
- #include "mfrc522.h"
- #include<intrins.h> //函數處理頭文件
- #include<string.h> //字符串處理頭文件
- #include<stdio.h> // 輸入輸出函數頭文件
- /********************************************************************************************/
- //數值類別
- typedef signed char int8; // 有符號8位整型變量
- typedef unsigned char uint8; // 無符號8位整型變量
- typedef signed int int16; // 有符號16位整型變量
- typedef unsigned int uint16; // 無符號16位整型變量
- /********************************************************************************************/
- // 定義特殊寄存器
- sfr wdt_contr=0xe1; //定義看門狗地址
- sfr isp_data =0xe2; //定義ISP數據寄存器
- sfr isp_addrh=0xe3; //定義ISP地址高8位
- sfr isp_addrl=0xe4; //定義ISP地址低8位
- sfr isp_cmd =0xe5; //定義ISP命令模式寄存器
- sfr isp_trig =0xe6; //定義ISP命令觸發寄存器
- sfr isp_contr=0xe7; //定義ISP控制模式寄存器
- //unsigned char code data1[16] = {0x64,0x00,0x00,0x00,0x1B,0xFF,0xFF,0xFF,0x64,0x00,0x00,0x00,0x01,0xFE,0x01,0xFE};//100
- unsigned char code data1[16] = {0xC8,0x00,0x00,0x00,0x37,0xFF,0xFF,0xFF,0xC8,0x00,0x00,0x00,0x01,0xFE,0x01,0xFE};//200
- //M1卡的某一塊寫為如下格式,則該塊為錢包,可接收扣款和充值命令
- //4字節金額(低字節在前)+4字節金額取反+4字節金額+1字節塊地址+1字節塊地址取反+1字節塊地址+1字節塊地址取反
- unsigned char data2[4] = {0x00,0x00,0x00,0x01};//存值減值金額
- 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[] = {"Total:"};
- unsigned char code dis1[] = {" "};
- unsigned char code dis2[] = {"CardID:"};
- unsigned char code dis3[] = {"Met:"};
- unsigned char code dis4[] = {" Card:"};
-
- unsigned char code dis6[] = {"0123456789ABCDEF"};
- unsigned int tt=0,keyfalg,falg_pro;
- unsigned char mc;
- uint16 tot=0,mon=0,card=0;
- uint8 a=0,b=0,c=0,d=0;
- /********************************************************************************************/
- //EEPROM驅動開始
- /*********************************************************************************
- * 函數名稱:eepromEraseSector (uint16 address)
- * 功 能:EEPROM擦除程序
- * 入口參數:address
- * 出口參數:無
- **********************************************************************************/
- //擦除片內EEPROM的一個扇區
- //擦除只能以扇區為最小單位進行,沒法只擦除一個字節
- //一個扇區是512個字節
- //本函數參數里面的地址落在哪個扇區,則該扇區內數據都將被擦除
- //例如:STC89C51RC片內EEPROM第一扇區開始地址為0x2000,結束地址為0x21ff
- //如果調用 eepromEraseSector(0x2001),則第一扇區內數據都將被擦除
- //擦除成功后,該扇區內各字節都將變為0xff
- void eepromEraseSector (uint16 address)
- {
- uint8 i;
- isp_addrl=address;
- isp_addrh=address>>8;
- isp_contr=0x01;
- isp_contr=isp_contr|0x81; // 0x80 if SYSCLK<40MHz, 0x81 if SYSCLK<20MHz, 0x82 if SYSCLK<10MHz, 0x83 if SYSCLK<5MHz
- isp_cmd=0x03; //送擦除扇區命令
- isp_trig=0x46;
- isp_trig=0xb9; //觸發寄存器
- for(i=0;i<3;i++);
- isp_contr=0x00;
- isp_cmd =0x00;
- isp_trig =0x00;
- isp_addrl=0x0;
- isp_addrh=0x0;
- }
- /**********************************************************************************
- * 函數名稱:eepromWrite(uint16 address, uint8 write_data)
- * 功 能:EEPROM寫程序
- * 入口參數:address,write_data
- * 出口參數:無
- ***********************************************************************************/
- //對STC片內EEPROM的指定地址寫入數據(即,字節編程)。
- //注意:字節編程是指將eeprom的1寫成1或0,將0寫成0,而無法將0寫成1
- //所以,在寫入數據前,一定要用扇區擦除將所有字節變為0xff
- void eepromWrite(uint16 address, uint8 write_data)
- {
- uint8 i;
- isp_data=write_data;
- isp_addrl=address;
- isp_addrh=address>>8;
- isp_contr=0x01;
- isp_contr=isp_contr|0x81; // 0x80 if SYSCLK<40MHz, 0x81 if SYSCLK<20MHz, 0x82 if SYSCLK<10MHz, 0x83 if SYSCLK<5MHz
- isp_cmd=0x02; //送寫數據命令
- isp_trig=0x46;
- isp_trig=0xb9; //觸發寄存器
- for(i=0;i<3;i++);
- isp_contr=0x00;
- isp_cmd =0x00;
- isp_trig =0x00;
- isp_addrl=0x0;
- isp_addrh=0x0;
- }
- /***********************************************************************************
- * 函數名稱:eepromRead(uint16 address)
- * 功 能:EEPROM讀程序
- * 入口參數:address
- * 出口參數:z
- ************************************************************************************/
- //讀取STC單片機內部EEPROM的一個字節
- //主要不同的STC單片機EEPROM起始地址不同
- //例如:STC89c52RC的片內EEPROM起始地址為0x2000
- uint8 eepromRead(uint16 address)
- {
- uint8 i,z;
- isp_addrl=address;
- isp_addrh=address>>8;
- isp_contr=0x01;
- isp_contr=isp_contr|0x81; // 0x80 if SYSCLK<40MHz, 0x81 if SYSCLK<20MHz, 0x82 if SYSCLK<10MHz, 0x83 if SYSCLK<5MHz
- isp_cmd=0x01; //送讀數據命令
- isp_trig=0x46;
- isp_trig=0xb9; //觸發寄存器
- for(i=0;i<3;i++);
- isp_contr=0x00;
- isp_cmd =0x00;
- isp_trig =0x00;
- isp_addrl=0x0;
- isp_addrh=0x0;
- z=isp_data;
- return(z);
- }
- void wreeprom(void){
- a=tot/256;
- b=tot%256;
- c=mon/256;
- d=mon%256;
- eepromEraseSector (0x2000);//擦除eeprom
- eepromWrite(0x2000, a);//寫入eeprom
- eepromWrite(0x2001, b);//寫入eeprom
- eepromWrite(0x2002, c);//寫入eeprom
- eepromWrite(0x2003, d);//寫入eeprom
- }
- //中斷程序
- /*********************************************************************************
- * 函數名稱:int0_1_int()
- * 功 能:外部中斷0/1初始化
- **********************************************************************************/
- void int0_1_int(void) {
- // IT0=1;//下降沿觸發
- // EX0=1;//TF0中斷開
- IT1=1;//下降沿觸發
- EX1=1;//TF1中斷開
- EA=1;//開中斷
- }
- /*********************************************************************************
- * 函數名稱:int1_fun()interrupt2
- * 功 能:外部中斷1服務子程序
- *********************************************************************************/
- void int1_fun()interrupt 2 {
- mc++;
- if (mc>=10){
- mc=0;
- if (mon>0){mon--;tot++;}
- wreeprom();
- }
- }
- void main( )
- {
- unsigned char status;
- int0_1_int();
- InitializeSystem( );//初始化
- PcdReset(); //復位RC522
- PcdAntennaOff(); //關閉天線
- PcdAntennaOn(); //開啟天線
- a=eepromRead(0x2000);//從eeprom讀
- b=eepromRead(0x2001);//從eeprom讀
- c=eepromRead(0x2002);//從eeprom讀
- d=eepromRead(0x2003);//從eeprom讀
- if (a==0xff&b==0xff&c==0xff&d==0xff) {
- // a=0,b=0,c=0,d=0;
- eepromEraseSector (0x2000);//擦除eeprom
- eepromWrite(0x2000, a);//寫入eeprom
- eepromWrite(0x2001, b);//寫入eeprom
- eepromWrite(0x2002, c);//寫入eeprom
- eepromWrite(0x2003, d);}//寫入eeprom
- tot=a*256+b;
- mon=c*256+d;
- while ( 1 )
- {
- if(key1==0){dcf=1;dcfzsd=1;fmq=0;kgbj=0;}else{fmq=1;kgbj=1;}//開蓋檢測到開啟時關閥門、報警
- status = PcdRequest(PICC_REQALL, g_ucTempbuf); //返回卡片類型#define PICC_REQIDL 0x26 尋天線區內未進入休眠狀態
- if (status != MI_OK){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;
- card=0;}//讀不到卡,顯示清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];
- //
- if (key2==0 ){init_k();}//初始化卡
- if (key2!=0 & mon<1000 & card>0){writek();}//寫卡
- readk(); //讀卡
- PcdHalt();//命令卡片進入休眠狀態
- }
- }
- }
- if(key3==0){Delay(40);if (mon>0){mon--;tot++;}
- wreeprom();}//寫入eeprom}
- if(mon>0&key1!=0){dcf=0;dcfzsd=0;}else{dcf=1;dcfzsd=1;}//有余額時開閥
- if(mon<10){kgbj=0;}else{kgbj=1;}//余額低于10時報警燈亮;
- if(mon<10&mon>0){fmq=0;}else{fmq=1;}
- if (falg_pro){LCD1206b();}else{LCD1206a();};//顯示處理
- }
- }
- /////////////////////////////////////////////////////////////////////
- //系統初始化
- /////////////////////////////////////////////////////////////////////
- void InitializeSystem(void)
- {
- P0 = 0xFF;P1 = 0xFF;P2 = 0xFF;P3 = 0xFF;
- fmq=0;
- lcd_init(); // 初始化LCD
- Delay(1);
- fmq=1;
- }
- void Delay(unsigned int time)
- {
- unsigned int i,k ;
- for(i=0;i<255;i++)
- for(k=0;k<time;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;
- }
- lcd_pos(unsigned char pos)
- { //設定顯示位置
- lcd_wcmd(pos | 0x80);
- }
- 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;
- }
- lcd_init(void) //LCD初始化設定
- {
- lcd_wcmd(0x38);Delay(1); //
- lcd_wcmd(0x0c);Delay(1); //
- lcd_wcmd(0x06);Delay(1); //
- lcd_wcmd(0x01);Delay(1); //清除LCD的顯示內容
- }
- LCD1206a()
- {
- unsigned char i;
- TYPE_DATA[0]=0x04;
- lcd_pos(0x00); // 設置顯示位置為第一行的第0個字符
- i = 0;
- switch (TYPE_DATA[0])
- {
- case 0x04:
- lcd_wdat(dis0[0]);
- lcd_wdat(dis0[1]);
- lcd_wdat(dis0[2]);
- lcd_wdat(dis0[3]);
- lcd_wdat(dis0[4]);
- lcd_wdat(dis0[5]);
- break;
- case 0x02:
- lcd_wdat(dis1[0]);
- break;
- case 0x08:
- lcd_wdat(dis2[0]);
- break;
- case 0x44:
- lcd_wdat(dis3[0]);
- break;
- }
- lcd_wdat(dis6[tot/10000]);
- lcd_wdat(dis6[tot%10000/1000]);
- lcd_wdat(dis6[tot%10000%1000/100]);
- lcd_wdat(dis6[tot%10000%1000%100/10]);
- lcd_wdat(dis6[tot%10000%1000%100%10]);
- lcd_wdat(dis1[0]);
- lcd_wdat(dis1[0]);
- lcd_wdat(dis1[0]);
- lcd_wdat(dis1[0]);
- lcd_wdat(dis1[0]);
- lcd_pos(0x40);
- lcd_wdat(dis3[0]);
- lcd_wdat(dis3[1]);
- lcd_wdat(dis3[2]);
- lcd_wdat(dis3[3]);
- lcd_wdat(dis6[mon%10000%1000/100]);
- lcd_wdat(dis6[mon%10000%1000%100/10]);
- lcd_wdat(dis6[mon%10000%1000%100%10]);
- lcd_wdat(dis4[0]);
- lcd_wdat(dis4[1]);
- lcd_wdat(dis4[2]);
- lcd_wdat(dis4[3]);
- lcd_wdat(dis4[4]);
- lcd_wdat(dis4[5]);
- lcd_wdat(dis6[card%10000%1000/100]);
- lcd_wdat(dis6[card%10000%1000%100/10]);
- lcd_wdat(dis6[card%10000%1000%100%10]);
- }
- LCD1206b()
- {
- unsigned char i;
- TYPE_DATA[0]=0x04;
- lcd_pos(0x00); // 設置顯示位置為第一行的第0個字符
- i = 0;
- switch (TYPE_DATA[0])
- {
- case 0x04:
- lcd_wdat(dis2[0]);
- lcd_wdat(dis2[1]);
- lcd_wdat(dis2[2]);
- lcd_wdat(dis2[3]);
- lcd_wdat(dis2[4]);
- lcd_wdat(dis2[5]);
- lcd_wdat(dis2[6]);
- break;
- lcd_wdat(dis2[6]);
- break;
- lcd_wdat(dis2[7]);
- break;
- case 0x02:
- lcd_wdat(dis1[0]);
- break;
- case 0x08:
- lcd_wdat(dis2[0]);
- break;
- case 0x44:
- lcd_wdat(dis3[0]);
- break;
- }
- lcd_wdat(dis6[ID_DATA[0]%100/10]);
- lcd_wdat(dis6[ID_DATA[0]%10]);
- lcd_wdat(dis6[ID_DATA[1]%100/10]);
- lcd_wdat(dis6[ID_DATA[1]%10]);
- lcd_wdat(dis6[ID_DATA[2]%100/10]);
- lcd_wdat(dis6[ID_DATA[2]%10]);
- lcd_wdat(dis6[ID_DATA[3]%100/10]);
- lcd_wdat(dis6[ID_DATA[3]%10]);
- lcd_pos(0x40);
- lcd_wdat(dis3[0]);
- lcd_wdat(dis3[1]);
- lcd_wdat(dis3[2]);
- lcd_wdat(dis3[3]);
- lcd_wdat(dis6[mon%10000%1000/100]);
- lcd_wdat(dis6[mon%10000%1000%100/10]);
- lcd_wdat(dis6[mon%10000%1000%100%10]);
- lcd_wdat(dis4[0]);
- lcd_wdat(dis4[1]);
- lcd_wdat(dis4[2]);
- lcd_wdat(dis4[3]);
- lcd_wdat(dis4[4]);
- lcd_wdat(dis4[5]);
- lcd_wdat(dis6[card%10000%1000/100]);
- lcd_wdat(dis6[card%10000%1000%100/10]);
- lcd_wdat(dis6[card%10000%1000%100%10]);
- }
- 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;
- 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];
- card=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) //驗證密碼
- {
- data2[1]=100/256;data2[0]=100%256;//扣款金額
- status = PcdValue(PICC_DECREMENT,1,data2);//扣款存值命令,錢包地址,金額 低位在前 PICC_INCREMENT 充值
- if (status == MI_OK)
- {
- pro();
- mon=mon+100; //充值金額
- wreeprom();
- }
- status = PcdBakValue(1, 2); //備份錢包 “1”源地址“2”目標地址
- if(status == MI_OK){};
- }
- }
- void init_k()//初始化卡
- {
- unsigned char status;
- if(key2==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();
- }
- }
- }
- }
復制代碼
|