极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 117457|回复: 50

arduino控制RFID模块,EEPROM存储卡号,可读卡识别,1602液晶显示(8月9日更新)

  [复制链接]
发表于 2012-8-1 21:42:23 | 显示全部楼层 |阅读模式
本帖最后由 cnkids 于 2012-8-8 14:46 编辑

8月9日更新:我对不起人民,一觉起来,我又更新了程序。先贴个实物图吧。。


这次只改了读卡识别的,加了个液晶显示,就不用电脑的串口监视器了,设置好,通电就能用:
  1. #include <LiquidCrystal.h>
  2. #include <EEPROM.h>
  3. #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
  4. #define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

  5. LiquidCrystal lcd(12, 11, 10, 9, 8, 7, 6);
  6. int backLight = 13;
  7. const int ENPin = 2;     // the number of the EN pin
  8. int ENState = 1;  //default EN state was HIGH

  9. void setup()
  10. {
  11.   Serial.begin(9600);
  12.   pinMode(ENPin, INPUT);
  13.   pinMode(backLight, OUTPUT);
  14.   digitalWrite(backLight, HIGH);
  15.   lcd.begin(16,2);
  16.   lcd.clear();
  17. }
  18. void loop()
  19. {
  20.   unsigned long ID = 0;    //define a string variable
  21.   unsigned long IDR = 0;
  22.   for(ENState = digitalRead(ENPin) ; ENState == LOW && Serial.available() > 0; ) // read the state of the EN value,check if the EN is LOW,the output the data.
  23.   {        
  24.     ID = ID * 10 + int(Serial.read()-'0'); //read the number from IDcard
  25.     delay(2);                        
  26.   }
  27.   if(ID != 0)             //if comdata gets the IDcard number,show it
  28.   {
  29.      lcd.setCursor(0,0);
  30.      lcd.print("ID: ");
  31.      lcd.print(ID);
  32.      for(int addr = 0; addr <= 1020; addr = addr + 10)
  33.      {
  34.        EEPROM_read(addr, IDR);
  35.        if(ID == IDR)
  36.        {
  37.          lcd.setCursor(0,1);
  38.          lcd.print("Welcome!        "); break;
  39.        }
  40.      }
  41.      if(ID != IDR)
  42.      {
  43.        lcd.setCursor(0,1);
  44.        lcd.print("who you are?      ");
  45.      }
  46.        ID = 0;                    //clean the comdata
  47.   }
  48. }
复制代码



————————————————————————无视我吧,写程序的分割线——————————————————

8月8日更新:我错了,不应该半夜不睡觉,爬起来码程序,最后优化修改过的程序,估计短时间内不会再改了,要改也要配合其他模块一起。读卡识别这部分的程序改成了for循环依次进入地址读取卡号进行匹配,正确则跳出循环,或是循环结束仍不匹配;EEPROM卡号存储改成了读卡时将卡号自行写入EEPROM,就不用人工一个一个变量的定义写入了。具体的往下看吧,欢迎拍砖~



读卡识别部分代码:
  1. #include <EEPROM.h>
  2. #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
  3. #define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

  4. const int ENPin = 2;     // 定义使能端的管脚
  5. int ENState = 1;  //初始化使能端为高电平

  6. void setup()
  7. {
  8.   Serial.begin(9600);
  9.   pinMode(ENPin, INPUT);
  10. }
  11. void loop()
  12. {
  13.   unsigned long ID = 0;    //定义一个变量用于存储读入的ID卡号
  14.   unsigned long IDR = 0; //定义一个变量用于存储从EEPROM读出的ID卡号
  15.   for(ENState = digitalRead(ENPin) ; ENState == LOW && Serial.available() > 0; ) // 读取使能端的电平,判断是否为低电平,是且串口有输入,则进入循环
  16.   {        
  17.     ID = ID * 10 + int(Serial.read()-'0'); //读出卡号
  18.     delay(2);                        
  19.   }
  20.   if(ID != 0)             //如果变量ID不为0
  21.   {
  22.      Serial.println(ID);      //输出读入的卡号,实际应用中考虑到安全性可不输出
  23.      for(int addr = 0; addr <= 1020; addr = addr + 10)    //定义一个变量表示为EEPROM的地址位,UNO的EEPROM有1024B,所以这里设定地址位在小于等于1020时进入循环
  24.      {
  25.        EEPROM_read(addr, IDR);    //读出EEPROM中存放的ID卡号
  26.        if(ID == IDR)                        //判断串口读入的ID卡号与EEPROM中的卡号是否匹配
  27.        {
  28.          Serial.println("Welcome!"); break;          //匹配则输出WELCOME,并跳出循环
  29.        }                                                              //若不匹配,则地址位加10,进行下一卡号匹配,直到与EEPROM内存储的所有卡号对比完,均不匹配,则跳出循环
  30.      }
  31.      if(ID != IDR) Serial.println("Sorry,you are not allowed!");   //均不匹配,则输出SORRY
  32.      ID = 0;                    //变量ID清0
  33.   }
  34. }
复制代码


效果如下:


EEPROM写入卡号程序:
  1. #include <EEPROM.h>
  2. #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
  3. #define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

  4. const int ENPin = 2;     // the number of the EN pin
  5. int ENState = 1;  //default EN state was HIGH      
  6. int addr = 0;

  7. void setup()
  8. {
  9.   Serial.begin(9600);
  10. }

  11. void loop()
  12. {
  13.   unsigned long ID = 0;
  14.   for(ENState = digitalRead(ENPin); ENState == LOW && Serial.available() > 0; )
  15.   {        
  16.     ID = ID * 10 + int(Serial.read()-'0'); //read the number from IDcard
  17.     delay(2);                        
  18.   }
  19.   if(ID != 0)
  20.   {
  21.     Serial.println(ID);
  22.     EEPROM_write(addr, ID);        //写入从串口读出的ID卡号
  23.     unsigned long IDR = 0;           //定义一个变量IDR用于存储从EEPROM中读出的卡号
  24.     EEPROM_read(addr, IDR);      //读出刚刚写入的卡号
  25.     Serial.println(IDR);
  26.     Serial.println(addr);                 //显示地址位
  27.     addr = addr + 10;                   //由于卡号位10数,所以地址位每次加10,进行下一个卡号的写入
  28.     ID = 0;
  29.   }
  30. }
复制代码


效果如下:



——————————————————————默默写程序的分割线——————————————————————————


8月7日:小更新一下。这次是将卡号存在EEPROM中,通过读取,然后再进行对比。目前正在思考利用什么算法能个加快卡号匹配的速度。
  1. #include <EEPROM.h>
  2. #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
  3. #define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

  4. const int ENPin = 2;     // 定义使能管脚
  5. int ENState = 1;  //初始化使能状态为高电平
  6. unsigned long ID; //定义一个数字量用于存储卡号
  7. unsigned long IDR; //定义一个数字量用于存储从EEPROM中读出的卡号
  8. unsigned long IDR1;

  9. void setup()
  10. {
  11.   Serial.begin(9600);
  12.   pinMode(ENPin, INPUT);
  13.   EEPROM_read(0, IDR);        //读出从地址0存储的卡号
  14.   Serial.print("ID card1: ");
  15.   Serial.println(IDR);
  16.   EEPROM_read(10, IDR1);   //读出从地址10存储的卡号
  17.   Serial.print("ID card2: ");
  18.   Serial.println(IDR1);
  19. }
  20. void loop()
  21. {
  22.   for(ENState = digitalRead(ENPin) ; ENState == LOW && Serial.available() > 0; ) //判断使能端是否为低电平,是且串口有输入,则读入卡号
  23.   {        
  24.     ID = ID * 10 + int(Serial.read()-'0'); //读出卡号
  25.     delay(2);                        //加个小延时,让串口有充裕的时间读出数据
  26.   }
  27.   if(ID != 0)             //如果ID内存的值不为0,则输出该卡号
  28.   {
  29.      Serial.println(ID);
  30.      if(ID == IDR) Serial.println("welcome");          //判断是否与EEPROM中的卡号相匹配
  31.      else if(ID == IDR1) Serial.println("welcome");
  32.      else Serial.println("sorry,you are not allowed.");
  33.      ID = 0;                    //清0
  34.   }
  35. }
复制代码


结果如下:


还用了单独的EEPROM读写程序先存储一遍卡号,通过读写的结果,因为存的是数字量,一个数就占一位了,卡号10个数,所以第二个卡号的地址从10开始写入:
  1. #include <EEPROM.h>
  2. #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
  3. #define EEPROM_read(address, p)  {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}

  4. unsigned long ID = 4294916953;
  5. unsigned long ID1 = 4294917240;
  6. unsigned long IDR = 0;
  7. unsigned long IDR1 = 0;

  8. void setup()
  9. {
  10.   Serial.begin(9600);
  11.   EEPROM_write(0, ID);
  12.   EEPROM_write(10, ID1);
  13.   EEPROM_read(0, IDR);
  14.   Serial.println(IDR);
  15.   EEPROM_read(10, IDR1);
  16.   Serial.println(IDR1);
  17. }

  18. void loop()
  19. {
  20.   
  21. }
复制代码


结果如下:




———————————————————低调写程序的分割线——————————————————————

首先感谢thomas,本程序是在他原有程序的基础上进行修改的,来个传送门:http://www.geek-workshop.com/thread-905-1-1.html

thomas的程序有个小BUG,在测试的时候发现卡号并没有依次存入递增的数组下标地址中,而是重复的存入下标为0的首地址中,导致了调试的时候,不能够进行很好的有效卡号设置和匹配。奋斗了两天,把数组接收改成了字符串变量接收,调用的时候,可以以数组的形式依次调用。

comdata += char(Serial.read()) 这里最后直接输出 Serial.println(comdata) 时,输出的是ASCII码的形式,所以改成了逐个地址输出,转成了16进制。有兴趣的一起研究改进哈~

下面放代码:
  1. const int ENPin = 2;     //使能端口
  2. int ENState = 1;  // 初始化为高电平  

  3. String comdata = ""; //定义一个字符串变量

  4. char ID[4] = {0x00,0x17,0x3E,0x41};  //设置一个有效卡的卡号
  5.   
  6. void setup()
  7. {
  8.   Serial.begin(9600);
  9.   pinMode(ENPin, INPUT);
  10. }
  11. void loop()
  12. {
  13.   // 读取使能端的电平,如果使能端为低电平,则读出卡号
  14.   for(ENState = digitalRead(ENPin) ; ENState == LOW && Serial.available() > 0; )
  15.   {     
  16.      comdata += char(Serial.read());   //读出ID卡号
  17.      delay(2);                         //加一个短延时,给单片机足够的时间读取卡号
  18.   }
  19.   if(comdata.length() > 0)             //如果comdata接收到卡号,则读出卡号
  20.   {
  21.      Serial.print(comdata[0],HEX);
  22.      Serial.print(comdata[1],HEX);
  23.      Serial.print(comdata[2],HEX);
  24.      Serial.println(comdata[3],HEX);
  25.      if(comdata[0] == ID[0] && comdata[1] == ID[1] && comdata[2] == ID[2] && comdata[3] == ID[3])
  26.      {                                //判断读入的ID卡是否与预先设置的有效卡号匹配,匹配则输入welcome
  27.        Serial.println("welcome");
  28.      }
  29.      else Serial.println("sorry,you are not allowed.");
  30.      comdata = "";                    //清除comdata内的值
  31.   }
  32. }
复制代码
输出的效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2012-8-1 23:12:11 | 显示全部楼层
又让我想起来刷卡上班。。。。。。
回复 支持 反对

使用道具 举报

发表于 2012-8-1 23:20:59 | 显示全部楼层
俺英文不行,没看懂
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-2 00:18:17 | 显示全部楼层
意见反馈 发表于 2012-8-1 23:20
俺英文不行,没看懂

额。那我改成中文注释好了。。
回复 支持 反对

使用道具 举报

发表于 2012-8-2 10:38:16 | 显示全部楼层
cnkids 发表于 2012-8-2 00:18
额。那我改成中文注释好了。。

非常感谢,辛苦了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-3 00:36:04 | 显示全部楼层
迷你强 发表于 2012-8-1 23:12
又让我想起来刷卡上班。。。。。。

额。。打算做个门禁的...
回复 支持 反对

使用道具 举报

发表于 2012-8-3 21:41:58 | 显示全部楼层
门禁烂大街了,30一个还带密码开锁,可予存500个卡号,楼主这个可存多个卡号吗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-3 22:55:11 | 显示全部楼层
意见反馈 发表于 2012-8-3 21:41
门禁烂大街了,30一个还带密码开锁,可予存500个卡号,楼主这个可存多个卡号吗

可以,目前还在继续开发中。。这个主要是我们学院科协打算自己做一个办公室的门禁~
回复 支持 反对

使用道具 举报

发表于 2012-8-4 20:27:40 | 显示全部楼层
楼主可以给个qq吗??我大三在做一个门禁的小项目,和你的很像,,有问题请教你。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-7 13:43:05 | 显示全部楼层
等回学校可以开工做硬件了~~~
回复 支持 反对

使用道具 举报

发表于 2012-8-7 20:23:01 | 显示全部楼层
本帖最后由 意见反馈 于 2012-8-7 20:26 编辑

恭喜恭喜,发明成功.不过要实际应用得有发卡的功能才行
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-7 20:28:22 | 显示全部楼层
意见反馈 发表于 2012-8-7 20:23
恭喜恭喜,发明成功.不过要实际应用得有发卡的功能才行

呵呵,算不上发明,小项目而已。啥发卡?
回复 支持 反对

使用道具 举报

发表于 2012-8-7 20:36:19 | 显示全部楼层
cnkids 发表于 2012-8-7 20:28
呵呵,算不上发明,小项目而已。啥发卡?

读出卡号并存入系统
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-7 21:07:49 | 显示全部楼层
意见反馈 发表于 2012-8-7 20:36
读出卡号并存入系统

这个可以,加几条语句就好了。目前在思考如何提高效率。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-8 14:48:16 | 显示全部楼层
意见反馈 发表于 2012-8-7 20:23
恭喜恭喜,发明成功.不过要实际应用得有发卡的功能才行

更新了一下,你看这样如何~
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-20 07:36 , Processed in 0.044602 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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