|
楼主 |
发表于 2017-8-27 19:22:51
|
显示全部楼层
本帖最后由 qq576193486 于 2017-8-27 19:24 编辑
这几天算是解决了。(我在其他的论坛也发过相关的帖子,这个解决方案也会发在那些论坛里,如果各位在其他论坛看到,或者转载都没问题)一开始也想过,既然共用有问题,那么就不让它们共用。那么把两个模块的电源引脚单独用一个引脚去控制。
这个解决方案,应该说很不好。因为两个模块都说是用SPI通讯的,跟电源没关系。
在Google上,倒是看到过类似的情况,
有的说是要在SD模块的MISO(即主机输入,从机输出,模块向板子发送)之间加一个330R的电阻(这个方案我试过,没成功)
有的说是要在SD模块的MISO之间加个二极管,阳极接SD卡模块,阴极接板子(这个还没试过)
那么 我只把我的实现方法介绍给那些,在搞这两个模块一起用的。在弄这两个模块也发现了以前没注意到的
首先是 RFID模块:
我用的是RFID库, 整理者:极客工坊bg1lsy ([email protected]) 整理时间:2013.05.25
(这个应该蛮多人都在用的,官方有个MRC522的库,应该是基于这个库整理的)
RFID rfid(10,5) (rfid 是个名称 可以改 例 myrfid)
第一个参数 是片选引脚 也就是SDA引脚, (对于SD卡模块 片选引脚是CS引脚 ChipSelect)
然后呢有个初始化函数 rfid.init()
当RFID给电以后 只能运行一次:也就是说
RFID给电后 执行了两次rfid.init() RFID 不工作
RFID断电,重新给电后 没有执行rfid.init() RFID不工作(重新给电后 要延时一小会 再执行初始化函数)
接着是SD卡模块:
这个SD卡官方有库的
SD可以不用声明对象的
初始化函数SD.begin(4) (4就是CS引脚)成功返回true 失败返回false
这个不同于RFID的初始化
如果SD卡模块没问题,第一次执行会返回true 再次执行会返回false,但是SD卡还是能用的,比如读写文件
(我们都可以把SD卡拿下来,再插上去,都不用重启)
还有一点就是,SD卡打开的文件名字不能过长,8+3(文件名别超过8个字母,扩展名别超过3个)
当打开一个不存在的文件时,它会自动以大写字母创建一个文件
----------------------------------------------------------------
我用到了RFID模块,SD模块,舵机(也就是门禁,人比较多,板子存不下了,就加个SD卡)
功能就是RFID读卡号(这里卡号我用的是10进制),去SD卡里的记事本里面一行一行比对,如果有,就舵机动,没有就存到SD卡的一个记事本里面(把没有的存起来,这样添加更简单)
在发一大堆长代码之前,我先把一些函数功能写出来,免得看起来头疼
先写官方的:
File dataFile;//文件类型的,用来准备下一步 SD卡打开的文件
不能同时打开两个文件,也就是说,如果要打开另一个文件之前 要先关闭当前打开的文件 函数是dataFile.close()
dataFile = SD.open("people.txt");//打开文件
dataFile.available();//这个是判断文件是否读取完 常用形式就是while(dataFile.available()) 如果文件没读完 就执行这个循环
dataFile.readStringUntil('\n');//这个就是说读取到指定的字符 我这里就是说读取到换行符结束,返回的是字符串String
我用的形式 就是 String str=dataFile.readStringUntil('\n'); 这样的话 str 就是一行的字符串了
这里还有个文件指针,大概理解就是,记事本里光标的位置
当我执行完一次readStringUntil('\n')后,再次执行的时候,它是从下一行 开始读取的
这个位置在向文件写东西的时候 有关 在打开文件的时候 有关
dataFile.println();//这个函数是向文件里写东西的,参数可以是字符串String 整形int 自动加换行符
那么从哪开始写的呢,这就涉及到位置了。那么对于我来说,我是希望向文件写东西的时候 是写到最后面的
这里就涉及到打开文件的方式了
SD卡打开文件:
dataFile = SD.open("people.txt");//这个打开方式 它的位置 是在最开始的(读取的时候 通常采用这种方式)
dataFile = SD.open("people.txt", FILE_WRITE);//这个打开方式 它的位置是在最末尾(写文件的时候 常采用这种)
Servo舵机:
myservo.detach();//使得舵机不加力
String的函数:
str.indexOf('/');//这个函数是在字符串中 找到第一个匹配的字符,返回字符所在位置 即整形
str.substring(0,n);//这个函数是截取字符串,第一个参数0是起始位置,第二个参数n是结束位置,返回一个新的字符串
这两个函数 结合起来用 就是
str = str.substring(0, str.indexOf('/'));
这样的话str就是/前面的字符了。我的意图就是记事本里 /前面保存卡号 /后面保存注释
例如 111111111111/XXX 修改时间:xxxx年xx月xx日
然后是我自己写的函数
void judge() 用来比较卡号的
void openTheDoor() 开门的
void readCard() 读卡号的
void turnOnSD() 这个函数先关闭RFID的电源 再给SD电源
void turnOnRFID() 这个函数先关闭SD的电源 再给RFID电源 - //整理者:仰望
- //整理时间:2017年8月20日
- #include <Servo.h>
- #include <SD.h>
- #include <SPI.h>
- #include <RFID.h>
- //---------宏定义 各个引脚------------
- //---------RFID-----------------------
- #define RFID_SS_PIN 10
- #define RFID_RST_PIN 5
- #define RFID_POWER_PIN 7//RFID的电源用引脚来控制
- //---------SD-------------------------
- #define SD_SS_PIN 4
- #define SD_POWER_PIN 8
- //---------Servo----------------------
- #define Servo_PIN 9
- //---------两个模块切换的时间间隔 毫秒
- #define CHANGE_TIME 10
- String num = "";//用字符串 存储当前读到的卡号
- int pos = 0;//舵机的角度
- bool flag = false;//是否开门
- Servo myservo; //声明舵机对象
- RFID rfid(RFID_SS_PIN, RFID_RST_PIN); //D10--读卡器MOSI引脚、D5--读卡器RST引脚
- void turnOnRFID() {
- //关掉SD
- digitalWrite(SD_POWER_PIN, LOW);
- delay(CHANGE_TIME);
- //打开RFID
- digitalWrite(RFID_POWER_PIN, HIGH);//RFID的电源给电
- delay(CHANGE_TIME);//延时一小会 再初始化
- rfid.init();//每次重新上电 都要重新初始化
- }
- void turnOnSD() {
- //关掉RFID
- digitalWrite(RFID_POWER_PIN, LOW);
- delay(CHANGE_TIME);
- //打开SD
- digitalWrite(SD_POWER_PIN, HIGH);//SD的电源给电
- delay(CHANGE_TIME);
- SD.begin(SD_SS_PIN);
- }
- void readCard()
- {
- //Serial.println("Find the card!");
- //读取卡序列号
- if (rfid.readCardSerial()) {
- num.concat(rfid.serNum[0]);//拼接字符串
- num.concat(rfid.serNum[1]);
- num.concat(rfid.serNum[2]);
- num.concat(rfid.serNum[3]);
- num.concat(rfid.serNum[4]);
- //Serial.println(num);
- }
- //选卡,可返回卡容量(锁定卡片,防止多数读取),去掉本行将连续读卡
- rfid.selectTag(rfid.serNum);
- }
- void openTheDoor()
- {
- myservo.attach(Servo_PIN);
- for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
- // in steps of 1 degree
- myservo.write(180); // tell servo to go to position in variable 'pos'
- delay(5); // waits 15ms for the servo to reach the position
- }
- delay(3500);
- for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
- myservo.write(0); // tell servo to go to position in variable 'pos'
- delay(5); // waits 15ms for the servo to reach the position
- }
- num = "";
- Serial.println(num);
- flag = false;
- }
- void judge()
- {
- String s;//用来保存从文件读取的一行字符串(截止符'/'前面的字符串)
- Serial.println();
- int n;//用来计数的
- File dataFile;
- dataFile = SD.open("teachers.txt");//打开文件
- if (dataFile) {//判断文件是否打开成功
- n = 1;
- while (dataFile.available())//判断是否读完了整个文件
- {
- s = dataFile.readStringUntil('\n');//读取到换行符 结束(也就是读取一行的字符串)
- //substring 截取字符串 第一个参数是起始位置 第二个参数是结束位置
- //indexOf 查找一个字符的位置 返回位置
- s = s.substring(0, s.indexOf('/'));
- if (s == num) {//判断是否找到了人
- flag = true;//找到了人 令flag为真
- Serial.print("Welcom Teacher ");
- Serial.print("No.");
- Serial.print(n);
- Serial.print(" CARD:");
- Serial.println(s);
- return;
- }
- n++;//没找到就自增1
- }
- }
- else {
- Serial.println("error opening file teachers.txt");
- }
- dataFile.close();
- delay(10);
- dataFile = SD.open("students.txt");//打开文件
- if (dataFile) {//判断文件是否打开成功
- n = 1;
- while (dataFile.available())//判断是否读完了整个文件
- {
- s = dataFile.readStringUntil('\n');//读取到换行符 结束(也就是读取一行的字符串)
- //substring 截取字符串 第一个参数是起始位置 第二个参数是结束位置
- //indexOf 查找一个字符的位置 返回位置
- s = s.substring(0, s.indexOf('/'));
- if (s == num) {//判断是否找到了人
- flag = true;//找到了人 令flag为真
- Serial.print("Welcom Student ");
- Serial.print("No.");
- Serial.print(n);
- Serial.print(" CARD:");
- Serial.println(s);
- return;
- }
- n++;//没找到就自增1
- }
- }
- else {
- Serial.println("error opening file students.txt");
- }
- if (!flag)
- {//如果是未注册的 就写到unexist.txt文件里 方便社员自己加入卡
- dataFile.close();
- delay(10);
- Serial.print("Unregistered CARD: ");
- Serial.println(num);
- dataFile = SD.open("unexist.txt", FILE_WRITE);
- if (dataFile) {
- dataFile.println(num + "/");
- }
- //没打开文件
- else {
- Serial.println("error opening file unexist.txt");
- }
- }
- dataFile.close();
- delay(10);
- }
- void setup()
- {
- pinMode(RFID_POWER_PIN, OUTPUT);
- pinMode(SD_POWER_PIN, OUTPUT);
- Serial.begin(9600);
- SPI.begin();
- myservo.attach(Servo_PIN);//舵机的初始化
- myservo.write(0);
- delay(100);
- // member=sizeof(password);
- Serial.println("START!");
- digitalWrite(SD_POWER_PIN,HIGH);
- if (!SD.begin(SD_SS_PIN)) {
- Serial.println("Card failed, or not present");
- // don't do anything more:
- return;
- }
- Serial.println("card initialized.");
- delay(CHANGE_TIME);
- turnOnRFID();//初始化的时候 先初始化RFID 因为RFID的初始化 必须只执行一次
- }
- void loop()
- {
- //turnOnRFID();//打开RFID
- //找卡
- if (rfid.isCard())
- {
- readCard();//读卡
- //读完卡后 把卡号存到了 String变量num里面 然后在判断之前 打开SD模块
- turnOnSD();
- judge();//判断刷入卡号是否登记
- //判断完后 SD关电 RFID重新上电 执行一次RFID的初始化函数
- turnOnRFID();
- }
- if (flag)
- {
- openTheDoor();//开门
- }
- myservo.detach();//使得舵机不加力
- pinMode(Servo_PIN, OUTPUT);
- digitalWrite(Servo_PIN, LOW);
- delay(90);
- num = "";//清空
- }
复制代码
|
|