找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4910|回复: 4
打印 上一主题 下一主题
收起左侧

基于51单片机的IC卡proteus仿真与源码

[复制链接]
跳转到指定楼层
楼主
ID:145007 发表于 2017-12-23 21:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基于51单片机的IC卡仿真,仿真效果。


单片机源程序如下:
  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;        //时钟线
  8. sbit SDA=P1^1;          //数据线

  9. unsigned int money;

  10. bit err_flag;


  11. //PC发送的命令
  12. #define CardID_Addr         0x00        //卡号 地址          00~02
  13. #define Password_Addr   0x0a        //密码                     0a~0d
  14. #define Money_Addr             0x0f        //金额                   0f~10

  15. #define COM_RD_CARD 0x45   //上位机发的读卡命令
  16. #define COM_WR_CARD 0x67        //上位机发的写卡命令
  17. #define COM_ADD_MONEY 0xab        //上位机发的充钱命令
  18. #define COM_DEC_MONEY 0x89        //上位机发的扣钱命令

  19. #define COM_WR_ERROR  0xdd        //出错

  20. #define FLAG_RD_OK        0x12                //上传的数据,表示读卡完毕
  21. #define FLAG_WR_OK        0x34                 //上传的数据,表示写卡完毕
  22. #define FLAG_RD_ER        0x56                //上传的数据,表示读卡错误
  23. #define FLAG_WR_ER        0x78                //上传的数据,表示写卡错误
  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 函数定义 ************/
  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的函数**********/
  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;        //设定波特率  9600  
  164.         PCON=0x00;
  165.         TR1=1;                        //启动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.         //////////////此代码用来测试IIC读写/////////////////
  177. #ifdef _IIC_DUBG                 
  178.                  Write_One_Byte(0,2); //ADD0 写入数据2
  179.                  Write_One_Byte(1,7); //ADD1 写入数据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测试结束//////////////////////////
  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]; //读取卡中的数据缓冲
  198.         unsigned char RxBuf[20];  //读取串口数据缓冲
  199.         EA=0;
  200.         for(i=0;i<2;i++) ////读取命令,第一个字节为命令字节,第二个字节为在第二个字节之后还有多少个字节          
  201.         {
  202.                 while(!RI);
  203.                 RI=0;
  204.                 RxBuf[i]=SBUF;  
  205.         }

  206.         if(RxBuf[1]!=0)          //如果字节数不是0,则继续读取剩余的数据
  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号
  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; //发送读卡命令返回PC

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

  228.                 for(j=0;j<7;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]); //写卡号
  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. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
0003、IC卡读写仿真.zip (3.21 MB, 下载次数: 125)




评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:673541 发表于 2019-12-26 13:51 | 只看该作者
我首先用Proteus8.6版本的按作者的原理图找到了元件并且连接好了对应的线,然后当我右键点击AT89C51的编辑源代码的时候,把作者的源代码输入进去显示有161处语法错误,但是当我用keil软件打开作者的代码就显示没有错误,所以我就想问问作者是不是用keil里面的.hex文件,就是proteus用的是汇编语言编辑源代码,但是作者用的好像是c'语言代码,这就在proteus里面显示有错误,所以就想问问作者怎么把keil里面的源代码添加到AT89C51处的编辑源代码处并且可以让他仿真成功,也就是说怎么实现keil和proteus里面的代码转换,或者怎么把keil里面的代码添加到proteus里面的AT89C51的编辑源代码处!

51hei图片20191226134248.png (76.29 KB, 下载次数: 26)

AT89C51编辑源代码错误

AT89C51编辑源代码错误

51hei图片20191226134024.png (48.64 KB, 下载次数: 19)

proteus里面的原理图

proteus里面的原理图
回复

使用道具 举报

板凳
ID:236933 发表于 2020-4-19 20:38 | 只看该作者
经过测试,单片机没有往上位机发信息
回复

使用道具 举报

地板
ID:732506 发表于 2020-4-21 05:40 | 只看该作者
proteus 新建工程时选no firmware,不用编辑源代码功能,用keil更改源码,使用keil编译的hex文件。
回复

使用道具 举报

5#
ID:739064 发表于 2020-4-29 20:57 | 只看该作者
我想问问 这仿真的结果显示MONEY0  那怎么体现扣费之类的功能呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表