找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 5951|回復(fù): 5
收起左側(cè)

基于51單片機(jī)的IC卡proteus仿真與源碼

[復(fù)制鏈接]
ID:145007 發(fā)表于 2017-12-23 21:56 | 顯示全部樓層 |閱讀模式
基于51單片機(jī)的IC卡仿真,仿真效果。
1.PNG

單片機(jī)源程序如下:
  1. #include "reg52.h"
  2. #include "lcd.h"

  3. unsigned char Rec_Buffer[4];
  4. #define DELAY_IIC_TIME 60
  5. #define TRUE 1
  6. #define FALSE 0

  7. sbit SCL=P1^0;        //時(shí)鐘線
  8. sbit SDA=P1^1;          //數(shù)據(jù)線

  9. unsigned int money;

  10. bit err_flag;


  11. //PC發(fā)送的命令
  12. #define CardID_Addr         0x00        //卡號(hào) 地址          00~02
  13. #define Password_Addr   0x0a        //密碼                     0a~0d
  14. #define Money_Addr             0x0f        //金額                   0f~10

  15. #define COM_RD_CARD 0x45   //上位機(jī)發(fā)的讀卡命令
  16. #define COM_WR_CARD 0x67        //上位機(jī)發(fā)的寫卡命令
  17. #define COM_ADD_MONEY 0xab        //上位機(jī)發(fā)的充錢命令
  18. #define COM_DEC_MONEY 0x89        //上位機(jī)發(fā)的扣錢命令

  19. #define COM_WR_ERROR  0xdd        //出錯(cuò)

  20. #define FLAG_RD_OK        0x12                //上傳的數(shù)據(jù),表示讀卡完畢
  21. #define FLAG_WR_OK        0x34                 //上傳的數(shù)據(jù),表示寫卡完畢
  22. #define FLAG_RD_ER        0x56                //上傳的數(shù)據(jù),表示讀卡錯(cuò)誤
  23. #define FLAG_WR_ER        0x78                //上傳的數(shù)據(jù),表示寫卡錯(cuò)誤
  24. #define FLAG_NO_MONEY 0x9a                 //卡上金額不足
  25. #define FLAG_FULL_MONEY 0xbc        //卡上金額過多

  26. #define adr_mon_h 0x0f         //錢的高位地址
  27. #define adr_mon_l 0x10

  28. unsigned char Card_num[]={"ID:          "};
  29. unsigned char Money_num[]={"MONEY:    .  "};

  30. bit Check_Acknowledge(void);
  31. void I2C_Start(void);
  32. void I2C_Stop(void);
  33. unsigned char Read_One_Byte(unsigned char);
  34. unsigned char  ReadI2CByte(void);
  35. void Send_0(void);
  36. void Send_1(void);
  37. void WriteI2CByte(unsigned char) ;
  38. void Write_One_Byte(unsigned char,unsigned char);

  39. /********** Function Definition 函數(shù)定義 ************/
  40. void DELAY_IIC(unsigned int t)
  41. {
  42.         while(t!=0)
  43.         t--;
  44. }


  45. void I2C_Start(void)
  46. {
  47.         SDA=1;
  48.         SCL=1;
  49.         DELAY_IIC(DELAY_IIC_TIME);
  50.         SDA=0;
  51.         DELAY_IIC(DELAY_IIC_TIME);
  52.         SCL=0;
  53.         DELAY_IIC(DELAY_IIC_TIME);
  54. }


  55. void I2C_Stop(void)

  56. {
  57.         SDA=0;
  58.         SCL=1;
  59.         DELAY_IIC(DELAY_IIC_TIME);
  60.         SDA=1;
  61.         DELAY_IIC(DELAY_IIC_TIME);
  62.         SCL=0;
  63.         DELAY_IIC(DELAY_IIC_TIME);
  64. }


  65. void Send_0(void)
  66. {
  67.         SDA=0;
  68.         SCL=1;
  69.         DELAY_IIC(DELAY_IIC_TIME);
  70.         SCL=0;
  71.         DELAY_IIC(DELAY_IIC_TIME);
  72. }

  73. void Send_1(void)
  74. {
  75.         SDA=1;
  76.         SCL=1;
  77.         DELAY_IIC(DELAY_IIC_TIME);
  78.         SCL=0;
  79.         DELAY_IIC(DELAY_IIC_TIME);
  80. }


  81. bit Check_Acknowledge(void)
  82. {
  83.         SDA=1;
  84.         SCL=1;
  85.         DELAY_IIC(DELAY_IIC_TIME/2);
  86.         F0=SDA;
  87.         DELAY_IIC(DELAY_IIC_TIME/2);
  88.         SCL=0;
  89.         DELAY_IIC(DELAY_IIC_TIME);
  90.         if(F0==1)
  91.                 return FALSE;
  92.         return TRUE;
  93. }

  94. void WriteI2CByte(unsigned char b)
  95. {
  96.         char i;
  97.         for(i=0;i<8;i++)
  98.                 if((b<<i)&0x80)
  99.                         Send_1();
  100.         else          
  101.                 Send_0();
  102. }

  103. unsigned char ReadI2CByte(void)
  104. {
  105.         unsigned char b=0,i;
  106.         for(i=0;i<8;i++)
  107.         {
  108.                 SDA=1;
  109.                 SCL=1;
  110.                 DELAY_IIC(10);
  111.                 F0=SDA;
  112.                 DELAY_IIC(10);
  113.                 SCL=0;
  114.                 if(F0==1)
  115.                 {
  116.                         b=b<<1;
  117.                         b=b|0x01;
  118.                 }
  119.                 else
  120.                         b=b<<1;
  121.         }
  122.         return b;
  123. }

  124. /**********以下為讀寫24c02的函數(shù)**********/
  125. void Write_One_Byte(unsigned char addr,unsigned char thedata)
  126. {
  127.         bit acktemp=1;
  128.         I2C_Start();
  129.         WriteI2CByte(0xa0);
  130.         acktemp=Check_Acknowledge();
  131.         WriteI2CByte(addr);
  132.         acktemp=Check_Acknowledge();
  133.         WriteI2CByte(thedata);
  134.         acktemp=Check_Acknowledge();
  135.         I2C_Stop();
  136. }       

  137. unsigned char Read_One_Byte(unsigned char addr)
  138. {
  139.         bit acktemp=1;
  140.         unsigned char mydata;
  141.         I2C_Start();
  142.         WriteI2CByte(0xa0);
  143.         acktemp=Check_Acknowledge();
  144.         WriteI2CByte(addr);
  145.         acktemp=Check_Acknowledge();
  146.         I2C_Start();
  147.         WriteI2CByte(0xa1);
  148.         acktemp=Check_Acknowledge();
  149.         mydata=ReadI2CByte();
  150.         acktemp=Check_Acknowledge();
  151.         return mydata;
  152.         I2C_Stop();
  153. }

  154. char Num2Char(unsigned char ch)
  155. {
  156.         if(ch<=9)
  157.                 return (ch+'0');
  158.         else return (ch-10+'a');
  159. }

  160. void System_Init(void)
  161. {
  162.         TMOD=0x21;                //串行口初始化
  163.         TH1=0xfd;TL1=0xfd;        //設(shè)定波特率  9600  
  164.         PCON=0x00;
  165.         TR1=1;                        //啟動(dòng)T1
  166.         SCON=0x50;        //串行口工作在方式1,并允許接收       
  167.           EA=1;                           
  168.         ES=1;       
  169. }

  170. void main(void)
  171. {
  172.         System_Init();                 //初始化
  173.         LCD_Init();

  174.         while(1)
  175.         {
  176.         //////////////此代碼用來測(cè)試IIC讀寫/////////////////
  177. #ifdef _IIC_DUBG                 
  178.                  Write_One_Byte(0,2); //ADD0 寫入數(shù)據(jù)2
  179.                  Write_One_Byte(1,7); //ADD1 寫入數(shù)據(jù)3
  180.                  LCD_Wr_Char(0,0,Read_One_Byte(0)+'0');         //讀取24C02 并在LM016顯示
  181.                  LCD_Wr_Char(1,0,Read_One_Byte(1)+'0');                 
  182. #endif                 
  183.         //////////////////IIC測(cè)試結(jié)束//////////////////////////
  184.                   Money_num[6]=((money/10000)%10)+'0';
  185.                   Money_num[7]=((money/1000)%10)+'0';
  186.                   Money_num[8]=((money/100)%10)+'0';
  187.                   Money_num[9]=((money/10)%10)+'0';
  188.                   Money_num[11]=(money%10)+'0';

  189.                 LCD_Wr_String(0,0,Card_num);
  190.                 LCD_Wr_String(0,1,Money_num);
  191.         }

  192. }

  193. //IC卡讀和寫子程序,中斷       
  194. void rxdata(void) interrupt 4 using 0
  195. {
  196.         unsigned char i,j;
  197.         unsigned char rdbuf[20]; //讀取卡中的數(shù)據(jù)緩沖
  198.         unsigned char RxBuf[20];  //讀取串口數(shù)據(jù)緩沖
  199.         EA=0;
  200.         for(i=0;i<2;i++) ////讀取命令,第一個(gè)字節(jié)為命令字節(jié),第二個(gè)字節(jié)為在第二個(gè)字節(jié)之后還有多少個(gè)字節(jié)          
  201.         {
  202.                 while(!RI);
  203.                 RI=0;
  204.                 RxBuf[i]=SBUF;  
  205.         }

  206.         if(RxBuf[1]!=0)          //如果字節(jié)數(shù)不是0,則繼續(xù)讀取剩余的數(shù)據(jù)
  207.         {
  208.                 for(i=0;i<RxBuf[1];i++)
  209.                 {
  210.                         while(!RI);
  211.                         RI=0;
  212.                         RxBuf[2+i]=SBUF;
  213.                 }
  214.         }

  215.         if(RxBuf[0]==COM_RD_CARD) //讀卡命令
  216.         {
  217.                 err_flag=0;
  218.                 rdbuf[0]=Read_One_Byte(CardID_Addr);   //讀卡中的ID號(hào)
  219.                 rdbuf[1]=Read_One_Byte(CardID_Addr+1);
  220.                 rdbuf[2]=Read_One_Byte(CardID_Addr+2);
  221.                 rdbuf[3]=Read_One_Byte(CardID_Addr+3);
  222.                 rdbuf[4]=Read_One_Byte(CardID_Addr+4);

  223.                 rdbuf[5]=Read_One_Byte(Money_Addr);
  224.                 rdbuf[6]=Read_One_Byte(Money_Addr+1);

  225.                 SBUF= COM_RD_CARD; //發(fā)送讀卡命令返回PC

  226.                 while(!TI);
  227.                 TI=0;

  228.                 for(j=0;j<7;j++) //發(fā)送卡數(shù)據(jù)返回PC
  229.                 {
  230.                         SBUF=rdbuf[j];
  231.                         while(!TI);
  232.                         TI=0;
  233.                 }

  234.               Card_num[3]=(rdbuf[0]>>4) +'0';          
  235.                   Card_num[4]=(rdbuf[0]&0x0f) +'0';  
  236.                   Card_num[5]=(rdbuf[1]>>4) + '0';
  237.                   Card_num[6]=(rdbuf[1]&0x0f) + '0';
  238.                   Card_num[7]=(rdbuf[2]>>4) + '0';
  239.                   Card_num[8]=(rdbuf[2]&0x0f) + '0';
  240.                   Card_num[9]=(rdbuf[3]>>4) + '0';
  241.                   Card_num[10]=(rdbuf[3]&0x0f) + '0';
  242.                   Card_num[11]=(rdbuf[4]>>4) + '0';
  243.                   Card_num[12]=(rdbuf[4]&0x0f) + '0';
  244.                        
  245.                   money=rdbuf[5]*256+rdbuf[6];

  246.         }
  247.         else if(RxBuf[0]==COM_WR_CARD) //寫卡命令
  248.         {
  249.                 err_flag=0;
  250.                 Write_One_Byte(CardID_Addr,RxBuf[2]); //寫卡號(hào)
  251.                 Write_One_Byte(CardID_Addr+1,RxBuf[3]);
  252.                 Write_One_Byte(CardID_Addr+2,RxBuf[4]);
  253.                 Write_One_Byte(CardID_Addr+3,RxBuf[5]);
  254.                 Write_One_Byte(CardID_Addr+4,RxBuf[6]);

  255.                 Write_One_Byte(Money_Addr,RxBuf[7]);
  256.                 Write_One_Byte(Money_Addr+1,RxBuf[8]);
  257.                 SBUF=COM_WR_CARD;while(!TI);TI=0;
  258.                 SBUF=COM_WR_CARD;while(!TI);TI=0;
  259.                 SBUF=COM_WR_CARD;while(!TI);TI=0;
  260.                 /*if((Read_One_Byte(CardID_Addr)!=RxBuf[2])
  261.                  ||(Read_One_Byte(CardID_Addr+1)!=RxBuf[3])
  262.                  ||(Read_One_Byte(CardID_Addr+2)!=RxBuf[4])
  263.                  ||(Read_One_Byte(CardID_Addr+3)!=RxBuf[5])
  264.                  ||(Read_One_Byte(CardID_Addr+4)!=RxBuf[6]))
  265.                  err_flag=1;

  266.                 if(!err_flag)
  267.                 {
  268.                         SBUF=COM_WR_CARD;while(!TI);TI=0;
  269.                         SBUF=COM_WR_CARD;while(!TI);TI=0;
  270.                         SBUF=COM_WR_CARD;while(!TI);TI=0;
  271.                         SBUF=COM_WR_CARD;while(!TI);TI=0;
  272.                 }
  273.                 else
  274.                 {
  275.                         SBUF=COM_WR_ERROR;
  276.                         while(!TI);
  277.                         TI=0;
  278.                 } */
  279.         }
  280.         else if(RxBuf[0]==COM_ADD_MONEY) //充錢命令
  281.         {
  282.                 err_flag=0;
  283.                 money=Read_One_Byte(Money_Addr)*256+Read_One_Byte(Money_Addr+1);
  284.                 money += (RxBuf[7]*256 + RxBuf[8]);

  285.                  if( Read_One_Byte(Money_Addr)!=(money/256)
  286.                  || Read_One_Byte(Money_Addr+1)!=(money%256))
  287.                          err_flag=1;

  288. ……………………

  289. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
0003、IC卡讀寫仿真.zip (3.21 MB, 下載次數(shù): 125)




評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:673541 發(fā)表于 2019-12-26 13:51 | 顯示全部樓層
我首先用Proteus8.6版本的按作者的原理圖找到了元件并且連接好了對(duì)應(yīng)的線,然后當(dāng)我右鍵點(diǎn)擊AT89C51的編輯源代碼的時(shí)候,把作者的源代碼輸入進(jìn)去顯示有161處語法錯(cuò)誤,但是當(dāng)我用keil軟件打開作者的代碼就顯示沒有錯(cuò)誤,所以我就想問問作者是不是用keil里面的.hex文件,就是proteus用的是匯編語言編輯源代碼,但是作者用的好像是c'語言代碼,這就在proteus里面顯示有錯(cuò)誤,所以就想問問作者怎么把keil里面的源代碼添加到AT89C51處的編輯源代碼處并且可以讓他仿真成功,也就是說怎么實(shí)現(xiàn)keil和proteus里面的代碼轉(zhuǎn)換,或者怎么把keil里面的代碼添加到proteus里面的AT89C51的編輯源代碼處!

keil運(yùn)行成功

keil運(yùn)行成功

AT89C51編輯源代碼錯(cuò)誤

AT89C51編輯源代碼錯(cuò)誤

proteus里面的原理圖

proteus里面的原理圖
回復(fù)

使用道具 舉報(bào)

ID:236933 發(fā)表于 2020-4-19 20:38 | 顯示全部樓層
經(jīng)過測(cè)試,單片機(jī)沒有往上位機(jī)發(fā)信息
回復(fù)

使用道具 舉報(bào)

ID:732506 發(fā)表于 2020-4-21 05:40 | 顯示全部樓層
proteus 新建工程時(shí)選no firmware,不用編輯源代碼功能,用keil更改源碼,使用keil編譯的hex文件。
回復(fù)

使用道具 舉報(bào)

ID:739064 發(fā)表于 2020-4-29 20:57 | 顯示全部樓層
我想問問 這仿真的結(jié)果顯示MONEY0  那怎么體現(xiàn)扣費(fèi)之類的功能呢
回復(fù)

使用道具 舉報(bào)

ID:1116058 發(fā)表于 2025-2-26 01:30 | 顯示全部樓層
不能下載,也不知道IC卡模塊接口的端口定義
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表