物联网海港码头系统

1.1 、智慧塔杆

1.1.1 tcp_server

/**
 * 功能:
 */
#include <ESP8266WiFi.h>

//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 4

//以下三个定义为调试定义
#define DebugBegin(baud_rate)    Serial.begin(baud_rate)
#define DebugPrintln(message)    Serial.println(message)
#define DebugPrint(message)    Serial.print(message)

//路由器WIFI和密码
const char* ssid = "SHDZ";
const char* password = "88888888";
//const char* ssid = "FAST_6422";
//const char* password = "1234567890@";

//静态地址
IPAddress local_IP(192,168,0,200);
IPAddress gateway(192,168,0,1);
IPAddress subnet(255,255,255,0);

//创建server
WiFiServer server(8088);//端口号,随意修改,范围0-65535
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];

void setup() {
  
  DebugBegin(115200);

  //连接WIFI
  WiFi.config(local_IP, gateway, subnet);//192.168.0.200
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  DebugPrint("\nConnecting to "); 
  DebugPrintln(ssid);

  uint8_t i = 0;

//等待连接
  while (WiFi.status() != WL_CONNECTED && i++ < 200) {
    delay(500);
    DebugPrint(".");
  }

  if (i == 201) {
    DebugPrint("\nCould not connect to "); 
    DebugPrintln(ssid);
    while (1) {
      delay(500);
    }
  }
  //启动server
  server.begin();

  DebugPrint("\nReady! Use 'telnet ");
  DebugPrint(WiFi.localIP());
  DebugPrintln(" 8088' to connect");

//  pinMode(2, OUTPUT);//红外A   D0
//  pinMode(5, OUTPUT);//红外B    D1
//  pinMode(4, OUTPUT);//红外C    D2
//  pinMode(0, OUTPUT);//红外D    D3
  
  pinMode(16, INPUT);
  
//  pinMode(14, INPUT);//电机A    D5
//  pinMode(12, INPUT);//电机A    D6
//  pinMode(13, INPUT);//电机A    D7
//  pinMode(15, INPUT);//电机总   D8
}

void loop() {

  uint8_t i;

  int smoke=0;
  String datas[5];

  //检测是否有新的client请求进来
  if (server.hasClient()) {
      
    //Led灯亮
    digitalWrite(2, LOW);
    DebugPrintln("yes");
    
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //释放旧无效或者断开的client
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
        //分配最新的client
        serverClients[i] = server.available();
        DebugPrint("New client: "); 
        DebugPrint(i);
        break;
      }
    }
    //当达到最大连接数 无法释放无效的client,需要拒绝连接
    if (i == MAX_SRV_CLIENTS) {
      WiFiClient serverClient = server.available();
      serverClient.stop();
      DebugPrintln("Connection rejected ");
    }
  }

  //连接情况 用led灯的状态显示
  int a=0;
  for(int i=0;serverClients[i].connected();i++){
    a=1;
  }
  if(a==0){
    digitalWrite(2, HIGH);
    delay(500);
    digitalWrite(2, LOW);
    delay(500);
    DebugPrintln("no");
  }else{
    digitalWrite(2, LOW);
  }

    
    smoke=digitalRead(16);//D0
    
    int sensorValue = analogRead(A0);//Esp8266模块 A0模拟量
    Serial.println(sensorValue);
    
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        //serverClients[i].println(sbuf, counti);

        serverClients[i].println("a,"+String(smoke));
        delay(100);
        serverClients[i].println("b,"+String(sensorValue));
        delay(100);
      }
    }

//    //串口读取到的转发到wifi,因为串口是一位一位的发送所以在这里缓存完再发送
//    if(Serial.available()>0){
////    size_t counti = Serial.available();//返回串口缓冲区中当前剩余的字符个数
////    uint8_t sbuf[counti];
////    Serial.readBytes(sbuf, counti);
////    Serial.write(sbuf, counti);
//
//    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//      if (serverClients[i] && serverClients[i].connected()) {
//        //serverClients[i].println(sbuf, counti);
////        serverClients[i].write(sbuf, counti);
//
//        serverClients[i].write(smoke);
//        delay(100);
//      }
//    }
//  }else{
//    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//      //释放旧无效或者断开的client
//      if (serverClients[i].connected()) {
//        serverClients[i].println("null");
//        delay(200);
//      }
//    }
//  }
  delay(100);
}

1.1.2 Tower

/**
   功能:
*/
#include <ESP8266WiFi.h>

//定义最多多少个client可以连接本server(一般不要超过4个)
#define MAX_SRV_CLIENTS 4

//路由器WIFI和密码
const char* ssid = "SHDZ";
const char* password = "88888888";
//const char* ssid = "FAST_6422";
//const char* password = "1234567890@";

//静态地址
IPAddress local_IP(192, 168, 0, 203);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

//创建server
WiFiServer server(8088);//端口号,随意修改,范围0-65535
//管理clients
WiFiClient serverClients[MAX_SRV_CLIENTS];

int infrared = 0;
int a;
int i = 0;

void setup() {

  Serial.begin(1200);

  //连接WIFI
  MyconnectWIFI();

  //启动server
  server.begin();

  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
}

void loop() {

  //检测新的Client
  NewClient();

  //LED指示灯
  LEDstate();

  //把收到的客户端数据发送到串口
  ReceiveData();

  //串口数据发送到客户端
  SendData();
}

//连接WIFI
void MyconnectWIFI() {

  //连接WIFI
  WiFi.config(local_IP, gateway, subnet);//192.168.0.200
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  //  Serial.print("\nConnecting to ");
  //  Serial.println(ssid);

  //等待连接
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 200) {
    delay(500);
    Serial.print(".");
  }
  if (i == 201) {
    //    Serial.print("\nCould not connect to ");
    //    Serial.println(ssid);
    while (1) {
      delay(500);
    }
  } else {
    //    Serial.print("\nReady! Use 'telnet ");
    Serial.print(WiFi.localIP());
    //    Serial.println(" :8088");
  }
}

//有客户端连接时常亮,无连接时闪烁
void LEDstate() {

  //连接情况 用led灯的状态显示
  a = 0;
  for (int i = 0; serverClients[i].connected(); i++) {
    a = 1;
  }
  if (a == 0) {
    digitalWrite(2, HIGH);
    delay(500);
    digitalWrite(2, LOW);
    delay(500);
    //    Serial.println("no");
  } else {
    digitalWrite(2, LOW);
  }
}

//检测新的client
void NewClient() {

  //检测是否有新的client请求进来
  if (server.hasClient()) {
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //释放旧无效或者断开的client
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
        //分配最新的client
        serverClients[i] = server.available();
        //        Serial.print("New client: ");
        //        Serial.print(i);
        break;
      }
    }
    //当达到最大连接数 无法释放无效的client,需要拒绝连接
    if (i == MAX_SRV_CLIENTS) {
      WiFiClient serverClient = server.available();
      serverClient.stop();
      //      Serial.println("Connection rejected ");
    }
  }
}

//把收到的客户端数据发送到串口
void ReceiveData() {
  for (i = 0; i < MAX_SRV_CLIENTS; i++) {
    if (serverClients[i] && serverClients[i].connected()) {
      while (serverClients[i].available())
      {
        char data = serverClients[i].read();
        Serial.print(data);
      }
    }
  }
}

//把串口数据发送到客户端
void SendData() {
  while (Serial.available()) {   //串口读取到的转发到wifi,因为串口是一位一位的发送所以在这里缓存完再发送
    size_t counti = Serial.available();
    uint8_t sbuf[counti];
    Serial.readBytes(sbuf, counti);
    //    Serial.write(sbuf, counti);

    //将数据发送给客户端
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        //serverClients[i].println(sbuf, counti);
        serverClients[i].write(sbuf, counti);
        delay(10);
      }
    }
  }
}

1.1.3 Tower_arduino

float a0 = 0;
float a1 = 0;
float a2 = 0;
float a3 = 0;
float a4 = 0;
int b1 = 0;
int b2 = 0;

void setup() {
  Serial.begin(1200);

  pinMode(13, INPUT);//烟雾
  pinMode(11, INPUT);//水浸

  pinMode(12, OUTPUT);
  digitalWrite(12, LOW);
}

void loop() {
  int datas[4];
  a0 = analogRead(A0) * (5.0 / 1023.0); //温度
  a1 = analogRead(A1) * (5.0 / 1023.0); //湿度
  //  a2 = analogRead(A2) * (5.0 / 1023.0); //水位
  a3 = analogRead(A3) * (5.0 / 1023.0); //风速
  a4 = analogRead(A4) * (5.0 / 1023.0); //风向
  b1 = digitalRead(13);//烟雾
  b2 = digitalRead(11);//水浸

  Serial.println("a," + String(a0 * 20-40));
  delay(300);
  Serial.println("b," + String(a1 * 20 - 20));
  delay(300);
  //  Serial.println("c," + String(a2));
//    Serial.println("c," + String(b2));
  if (b2 == 1) {
    Serial.println("c,有水");
  } else {
    Serial.println("c,无水");
  }
  delay(300);
  Serial.println("d," + String(a3 * 6));
  delay(300);
//  Serial.println("e," + String(a4));
  if(a4>=4.69&&a4<=5||a4>=0&&a4<0.31){Serial.println("e,北");}else
  if(a4>=0.31&&a4<0.94){Serial.println("e,东北");}else
  if(a4>=94&&a4<1.56){Serial.println("e,东");}else
  if(a4>=1.56&&a4<2.19){Serial.println("e,东南");}else
  if(a4>=2.19&&a4<2.81){Serial.println("e,南");}else
  if(a4>=2.81&&a4<3.44){Serial.println("e,西南");}else
  if(a4>=3.44&&a4<4.06){Serial.println("e,西");}else
  if(a4>=4.06&&a4<4.69){Serial.println("e,西北");}
  delay(300);
  Serial.println("f," + String(b1));
  delay(500);


  char data = '0';
  //接收数据
  if (Serial.available()) {
    data = Serial.read();
    if (data == 'a') {
      digitalWrite(12, HIGH);
    } else {
      digitalWrite(12, LOW);
    }
  } else {
    delay(100);
  }
}

2.1 arduino RFID

2.1.1、android APP客户端

android APP安装包下载地址 https://www.lanzous.com/i6w7a8d

android studio开发源码下载地址 https://www.lanzous.com/i6w7b0b

2.1.2、ESP8266_client

/*
   把8266作为TCPcleint,加入手机创建的tcpServer中
*/
#include<ESP8266WiFi.h>

//WIFI名字和密码
const char* ssid = "iCloud_TP";
const char* password = "icloud_TP";

const char *host = "192.168.1.220"; //修改为手机的的tcpServer服务端的IP地址,即手机在路由器上的ip
const int tcpPort = 8088;//sfq  修改为你建立的Server服务端的端口号

WiFiClient client;

//连接标识
int a = 0;

void setup()
{
  Serial.begin(9600);
  ConnectWIFI();

  pinMode(16, INPUT);//   D0
  pinMode(5, INPUT);//    D1
  pinMode(4, INPUT);//    D2
  pinMode(0, INPUT);//    D3

  pinMode(2, OUTPUT);//     D4
  pinMode(14, OUTPUT);//    D5
  pinMode(12, OUTPUT);//    D6
  pinMode(13, OUTPUT);//    D7
  pinMode(15, OUTPUT);//    D8

  digitalWrite(2, HIGH);
  digitalWrite(14, HIGH);
}

void loop()
{
  if (a == 1) {
    //串口数据发送到客户端
    Senddata();
  } else {
    //连接服务端
    ConnectServer();
  }

  //连接服务端并用led灯表示连接状态
  LEDstate();

  //  //接收server数据发送到串口
  //  Readdata();
}

//连接WIFI
void ConnectWIFI() {
  WiFi.begin(ssid, password);
  //等待连接 
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 200) {
    delay(500);
//    Serial.print(".");
  }

  //连接失败
  if (i == 201) {
//    Serial.println("\nCould not connect WIFI. ");
    while (1) {
      delay(500);
    }
  } else {
//    Serial.println("connect WIFI ok");
  }
}

//led灯连接时常亮,未连接时闪烁
void LEDstate() {
  //连接情况 用led灯的状态显示
  a = 0;
  for (int i = 0; client.connected(); i++) {
    a = 1;
    break;
  }
  if (a == 0) {
    digitalWrite(2, HIGH);
    delay(500);
    digitalWrite(2, LOW);
    delay(500);
  } else {
    digitalWrite(2, LOW);
  }
}

//连接服务端
void ConnectServer() {
  while (!client.connected())
  {
    if (!client.connect(host, tcpPort)) {
      digitalWrite(2, HIGH);
      delay(500);
      digitalWrite(2, LOW);
      delay(500);
    }
  }
}

//串口数据发送到服务器
void Senddata() {
  //串口读取到的转发到wifi,因为串口是一位一位的发送所以在这里缓存完再发送
  while (Serial.available())
  {
    size_t counti = Serial.available();
    uint8_t sbuf[counti];
    Serial.readBytes(sbuf, counti);
    client.write(sbuf, counti);
//    Serial.write(sbuf, counti);
//    Serial.println("send over!");
  }

  //    //直接发送
  //    client.println(String("222222"));
  //    delay(2000);
}

//void Readdata() {
//  //读取从server返回到响应数据
//  String line = client.readStringUntil('\r');
//  Serial.println(line);
//}

2.1.3、arduino_uno寻卡

/*
   文 件 名:RFID.pde
  RFID模块            Arduino   (UNO)
   VCC                 3.3V
   RST                  5
   GND                 GND
   MISO                 12
   MOSI                 11
   SCK                  13
   NSS                   10
   IRQ  (不接)

  RFID模块            Arduino   (2560)
   VCC                 3.3V
   RST                  5
   GND                 GND
   MISO                 50
   MOSI                 51
   SCK                  52
   NSS                   53
   IRQ  (不接)
   功能描述:Mifare1 寻卡→防冲突→选卡→读写 接口
*/
// the sensor communicates using SPI, so include the library:
#include <SPI.h>

#define  uchar unsigned char
#define uint  unsigned int

//数组最大长度
#define MAX_LEN 16

/////////////////////////////////////////////////////////////////////
//set the pin
/////////////////////////////////////////////////////////////////////
const int chipSelectPin = 10;//如果控制板为UNO,328,168
//const int chipSelectPin = 53; //如果控制板为mega 2560,1280
const int NRSTPD = 5;

//MF522命令字
#define PCD_IDLE              0x00               //NO action;取消当前命令
#define PCD_AUTHENT           0x0E               //验证密钥
#define PCD_RECEIVE           0x08               //接收数据
#define PCD_TRANSMIT          0x04               //发送数据
#define PCD_TRANSCEIVE        0x0C               //发送并接收数据
#define PCD_RESETPHASE        0x0F               //复位
#define PCD_CALCCRC           0x03               //CRC计算

//Mifare_One卡片命令字
#define PICC_REQIDL           0x26               //寻天线区内未进入休眠状态
#define PICC_REQALL           0x52               //寻天线区内全部卡
#define PICC_ANTICOLL         0x93               //防冲撞
#define PICC_SElECTTAG        0x95              //选卡93
#define PICC_AUTHENT1A        0x60               //验证A密钥
#define PICC_AUTHENT1B        0x61               //验证B密钥
#define PICC_READ             0x30               //读块
#define PICC_WRITE            0xA0               //写块
#define PICC_DECREMENT        0xC0
#define PICC_INCREMENT        0xC1
#define PICC_RESTORE          0xC2               //调块数据到缓冲区
#define PICC_TRANSFER         0xB0               //保存缓冲区中数据
#define PICC_HALT             0x50               //休眠


//和MF522通讯时返回的错误代码
#define MI_OK                 0
#define MI_NOTAGERR           (-1)  //1
#define MI_ERR                (-2)  //2


//------------------MFRC522寄存器---------------
//Page 0:Command and Status
#define     Reserved00            0x00
#define     CommandReg            0x01
#define     CommIEnReg            0x02
#define     DivlEnReg             0x03
#define     CommIrqReg            0x04
#define     DivIrqReg             0x05
#define     ErrorReg              0x06
#define     Status1Reg            0x07
#define     Status2Reg            0x08
#define     FIFODataReg           0x09
#define     FIFOLevelReg          0x0A
#define     WaterLevelReg         0x0B
#define     ControlReg            0x0C
#define     BitFramingReg         0x0D
#define     CollReg               0x0E
#define     Reserved01            0x0F
//Page 1:Command
#define     Reserved10            0x10
#define     ModeReg               0x11
#define     TxModeReg             0x12
#define     RxModeReg             0x13
#define     TxControlReg          0x14
#define     TxAutoReg             0x15
#define     TxSelReg              0x16
#define     RxSelReg              0x17
#define     RxThresholdReg        0x18
#define     DemodReg              0x19
#define     Reserved11            0x1A
#define     Reserved12            0x1B
#define     MifareReg             0x1C
#define     Reserved13            0x1D
#define     Reserved14            0x1E
#define     SerialSpeedReg        0x1F
//Page 2:CFG
#define     Reserved20            0x20
#define     CRCResultRegM         0x21
#define     CRCResultRegL         0x22
#define     Reserved21            0x23
#define     ModWidthReg           0x24
#define     Reserved22            0x25
#define     RFCfgReg              0x26
#define     GsNReg                0x27
#define     CWGsPReg              0x28
#define     ModGsPReg             0x29
#define     TModeReg              0x2A
#define     TPrescalerReg         0x2B
#define     TReloadRegH           0x2C
#define     TReloadRegL           0x2D
#define     TCounterValueRegH     0x2E
#define     TCounterValueRegL     0x2F
//Page 3:TestRegister
#define     Reserved30            0x30
#define     TestSel1Reg           0x31
#define     TestSel2Reg           0x32
#define     TestPinEnReg          0x33
#define     TestPinValueReg       0x34
#define     TestBusReg            0x35
#define     AutoTestReg           0x36
#define     VersionReg            0x37
#define     AnalogTestReg         0x38
#define     TestDAC1Reg           0x39
#define     TestDAC2Reg           0x3A
#define     TestADCReg            0x3B
#define     Reserved31            0x3C
#define     Reserved32            0x3D
#define     Reserved33            0x3E
#define     Reserved34            0x3F
//-----------------------------------------------

//4字节卡序列号,第5字节为校验字节
uchar serNum[5];
uchar  writeDate[16] = {'T', 'e', 'n', 'g', ' ', 'B', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0};
//扇区A密码,16个扇区,每个扇区密码6Byte
uchar sectorKeyA[16][16] = {
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
};
uchar sectorNewKeyA[16][16] = {
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
  {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xff, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
};


void setup() {
  Serial.begin(9600);                       // RFID reader SOUT pin connected to Serial RX pin at 2400bps      RFID阅读SOUT引脚以2400bps连接到串行RX引脚
  // start the SPI library:
  SPI.begin();

  pinMode(chipSelectPin, OUTPUT);            // Set digital pin 10 as OUTPUT to connect it to the RFID /ENABLE pin
  digitalWrite(chipSelectPin, LOW);          // Activate the RFID reader
  pinMode(NRSTPD, OUTPUT);              // Set digital pin 10 , Not Reset and Power-down
  digitalWrite(NRSTPD, HIGH);

  //初始化RC522
  MFRC522_Init();
}


void loop()
{
  uchar i, tmp;
  uchar status;
  uchar str[MAX_LEN];
  uchar RC_size;
  uchar blockAddr;  //选择操作的块地址0~63

  //寻卡,返回卡类型
  status = MFRC522_Request(PICC_REQIDL, str);
  if (status == MI_OK)
  {
    //    Serial.println("cardtype");
    //    Serial.println(str);
  }

  //防冲撞,返回卡的序列号 4字节
  status = MFRC522_Anticoll(str);
  memcpy(serNum, str, 5);
  if (status == MI_OK)
  {
    //输出卡号
    String str = "a,";
    for (int i = 0; i < 5; i++) {
      str += serNum[i];
    }
    Serial.println(str);
    delay(1000);
  }

  //  //选卡,返回卡容量
  //  RC_size = MFRC522_SelectTag(serNum);
  //  if (RC_size != 0) {
  
  //    Serial.print("serNum");
  //  }
  //
  //  //写数据卡
  //  blockAddr = 7;    //数据块7
  //  status = MFRC522_Auth(PICC_AUTHENT1A, blockAddr, sectorKeyA[blockAddr / 4], serNum);  //认证
  //  if (status == MI_OK)
  //  {
  //    //写数据
  //    status = MFRC522_Write(blockAddr, sectorNewKeyA[blockAddr / 4]);
  //    Serial.print("set the new card password, and can modify the data of the Sector: ");
  //    Serial.print(blockAddr / 4, DEC);
  //
  //    //写数据
  //    blockAddr = blockAddr - 3 ;
  //    status = MFRC522_Write(blockAddr, writeDate);
  //    if (status == MI_OK)
  //    {
  //      Serial.println("OK!");
  //    }
  //  }
  //
  //  //读卡
  //  blockAddr = 7;    //数据块7
  //  status = MFRC522_Auth(PICC_AUTHENT1A, blockAddr, sectorNewKeyA[blockAddr / 4], serNum); //认证
  //  if (status == MI_OK)
  //  {
  //    //读数据
  //    blockAddr = blockAddr - 3 ;
  //    status = MFRC522_Read(blockAddr, str);
  //    if (status == MI_OK)
  //    {
  //      Serial.println("Read from the card ,the data is : ");
  //      for (i = 0; i < 16; i++)
  //      {
  //        Serial.print(str[i]);
  //      }
  //      Serial.println(" \n");
  //    }
  //  }
  //  //Serial.println(" ");
  //  MFRC522_Halt();     //命令卡片进入休眠状态

}

/*
   函 数 名:Write_MFRC5200
   功能描述:向MFRC522的某一寄存器写一个字节数据
   输入参数:addr--寄存器地址;val--要写入的值
   返 回 值:无
*/
void Write_MFRC522(uchar addr, uchar val)
{
  digitalWrite(chipSelectPin, LOW);

  //地址格式:0XXXXXX0
  SPI.transfer((addr << 1) & 0x7E);
  SPI.transfer(val);

  digitalWrite(chipSelectPin, HIGH);
}


/*
   函 数 名:Read_MFRC522
   功能描述:从MFRC522的某一寄存器读一个字节数据
   输入参数:addr--寄存器地址
   返 回 值:返回读取到的一个字节数据
*/
uchar Read_MFRC522(uchar addr)
{
  uchar val;

  digitalWrite(chipSelectPin, LOW);

  //地址格式:1XXXXXX0
  SPI.transfer(((addr << 1) & 0x7E) | 0x80);
  val = SPI.transfer(0x00);

  digitalWrite(chipSelectPin, HIGH);

  return val;
}

/*
   函 数 名:SetBitMask
   功能描述:置RC522寄存器位
   输入参数:reg--寄存器地址;mask--置位值
   返 回 值:无
*/
void SetBitMask(uchar reg, uchar mask)
{
  uchar tmp;
  tmp = Read_MFRC522(reg);
  Write_MFRC522(reg, tmp | mask);  // set bit mask
}


/*
   函 数 名:ClearBitMask
   功能描述:清RC522寄存器位
   输入参数:reg--寄存器地址;mask--清位值
   返 回 值:无
*/
void ClearBitMask(uchar reg, uchar mask)
{
  uchar tmp;
  tmp = Read_MFRC522(reg);
  Write_MFRC522(reg, tmp & (~mask));  // clear bit mask
}


/*
   函 数 名:AntennaOn
   功能描述:开启天线,每次启动或关闭天线发射之间应至少有1ms的间隔
   输入参数:无
   返 回 值:无
*/
void AntennaOn(void)
{
  uchar temp;

  temp = Read_MFRC522(TxControlReg);
  if (!(temp & 0x03))
  {
    SetBitMask(TxControlReg, 0x03);
  }
}


/*
   函 数 名:AntennaOff
   功能描述:关闭天线,每次启动或关闭天险发射之间应至少有1ms的间隔
   输入参数:无
   返 回 值:无
*/
void AntennaOff(void)
{
  ClearBitMask(TxControlReg, 0x03);
}


/*
   函 数 名:ResetMFRC522
   功能描述:复位RC522
   输入参数:无
   返 回 值:无
*/
void MFRC522_Reset(void)
{
  Write_MFRC522(CommandReg, PCD_RESETPHASE);
}


/*
   函 数 名:InitMFRC522
   功能描述:初始化RC522
   输入参数:无
   返 回 值:无
*/
void MFRC522_Init(void)
{
  digitalWrite(NRSTPD, HIGH);

  MFRC522_Reset();
  //////////////////////////////////////////////
  delay(500);/////////////////////////////////
  ///////////////////////////////////////////////
  //Timer: TPrescaler*TreloadVal/6.78MHz = 24ms
  Write_MFRC522(TModeReg, 0x8D);    //Tauto=1; f(Timer) = 6.78MHz/TPreScaler
  Write_MFRC522(TPrescalerReg, 0x3E); //TModeReg[3..0] + TPrescalerReg
  Write_MFRC522(TReloadRegL, 30);
  Write_MFRC522(TReloadRegH, 0);

  Write_MFRC522(TxAutoReg, 0x40);   //100%ASK
  Write_MFRC522(ModeReg, 0x3D);   //CRC初始值0x6363  ???

  //ClearBitMask(Status2Reg, 0x08);   //MFCrypto1On=0
  //Write_MFRC522(RxSelReg, 0x86);    //RxWait = RxSelReg[5..0]
  //Write_MFRC522(RFCfgReg, 0x7F);      //RxGain = 48dB

  AntennaOn();    //打开天线
}


/*
   函 数 名:MFRC522_Request
   功能描述:寻卡,读取卡类型号
   输入参数:reqMode--寻卡方式,
       TagType--返回卡片类型
        0x4400 = Mifare_UltraLight
        0x0400 = Mifare_One(S50)
        0x0200 = Mifare_One(S70)
        0x0800 = Mifare_Pro(X)
        0x4403 = Mifare_DESFire
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_Request(uchar reqMode, uchar *TagType)
{
  uchar status;
  uint backBits;      //接收到的数据位数

  Write_MFRC522(BitFramingReg, 0x07);   //TxLastBists = BitFramingReg[2..0] ???

  TagType[0] = reqMode;
  status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits);

  if ((status != MI_OK) || (backBits != 0x10))
  {
    status = MI_ERR;
  }

  return status;
}


/*
   函 数 名:MFRC522_ToCard
   功能描述:RC522和ISO14443卡通讯
   输入参数:command--MF522命令字,
       sendData--通过RC522发送到卡片的数据,
       sendLen--发送的数据长度
       backData--接收到的卡片返回数据,
       backLen--返回数据的位长度
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_ToCard(uchar command, uchar *sendData, uchar sendLen, uchar *backData, uint *backLen)
{
  uchar status = MI_ERR;
  uchar irqEn = 0x00;
  uchar waitIRq = 0x00;
  uchar lastBits;
  uchar n;
  uint i;

  switch (command)
  {
    case PCD_AUTHENT:   //认证卡密
      {
        irqEn = 0x12;
        waitIRq = 0x10;
        break;
      }
    case PCD_TRANSCEIVE:  //发送FIFO中数据
      {
        irqEn = 0x77;
        waitIRq = 0x30;
        break;
      }
    default:
      break;
  }

  Write_MFRC522(CommIEnReg, irqEn | 0x80);  //允许中断请求
  ClearBitMask(CommIrqReg, 0x80);     //清除所有中断请求位
  SetBitMask(FIFOLevelReg, 0x80);     //FlushBuffer=1, FIFO初始化

  Write_MFRC522(CommandReg, PCD_IDLE);  //NO action;取消当前命令  ???

  //向FIFO中写入数据
  for (i = 0; i < sendLen; i++)
  {
    Write_MFRC522(FIFODataReg, sendData[i]);
  }

  //执行命令
  Write_MFRC522(CommandReg, command);
  if (command == PCD_TRANSCEIVE)
  {
    SetBitMask(BitFramingReg, 0x80);    //StartSend=1,transmission of data starts
  }

  //等待接收数据完成
  i = 2000; //i根据时钟频率调整,操作M1卡最大等待时间25ms ???
  do
  {
    //CommIrqReg[7..0]
    //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq
    n = Read_MFRC522(CommIrqReg);
    i--;
  }
  while ((i != 0) && !(n & 0x01) && !(n & waitIRq));

  ClearBitMask(BitFramingReg, 0x80);      //StartSend=0

  if (i != 0)
  {
    if (!(Read_MFRC522(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr
    {
      status = MI_OK;
      if (n & irqEn & 0x01)
      {
        status = MI_NOTAGERR;     //??
      }

      if (command == PCD_TRANSCEIVE)
      {
        n = Read_MFRC522(FIFOLevelReg);
        lastBits = Read_MFRC522(ControlReg) & 0x07;
        if (lastBits)
        {
          *backLen = (n - 1) * 8 + lastBits;
        }
        else
        {
          *backLen = n * 8;
        }

        if (n == 0)
        {
          n = 1;
        }
        if (n > MAX_LEN)
        {
          n = MAX_LEN;
        }

        //读取FIFO中接收到的数据
        for (i = 0; i < n; i++)
        {
          backData[i] = Read_MFRC522(FIFODataReg);
        }
      }
    }
    else
    {
      status = MI_ERR;
    }

  }

  //SetBitMask(ControlReg,0x80);           //timer stops
  //Write_MFRC522(CommandReg, PCD_IDLE);

  return status;
}


/*
   函 数 名:MFRC522_Anticoll
   功能描述:防冲突检测,读取选中卡片的卡序列号
   输入参数:serNum--返回4字节卡序列号,第5字节为校验字节
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_Anticoll(uchar *serNum)
{
  uchar status;
  uchar i;
  uchar serNumCheck = 0;
  uint unLen;

  //ClearBitMask(Status2Reg, 0x08);   //TempSensclear
  //ClearBitMask(CollReg,0x80);     //ValuesAfterColl
  Write_MFRC522(BitFramingReg, 0x00);   //TxLastBists = BitFramingReg[2..0]

  serNum[0] = PICC_ANTICOLL;
  serNum[1] = 0x20;
  status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen);

  if (status == MI_OK)
  {
    //校验卡序列号
    for (i = 0; i < 4; i++)
    {
      serNumCheck ^= serNum[i];
    }
    if (serNumCheck != serNum[i])
    {
      status = MI_ERR;
    }
  }

  //SetBitMask(CollReg, 0x80);    //ValuesAfterColl=1

  return status;
}


/*
   函 数 名:CalulateCRC
   功能描述:用MF522计算CRC
   输入参数:pIndata--要读数CRC的数据,len--数据长度,pOutData--计算的CRC结果
   返 回 值:无
*/
void CalulateCRC(uchar *pIndata, uchar len, uchar *pOutData)
{
  uchar i, n;

  ClearBitMask(DivIrqReg, 0x04);      //CRCIrq = 0
  SetBitMask(FIFOLevelReg, 0x80);     //清FIFO指针
  //Write_MFRC522(CommandReg, PCD_IDLE);

  //向FIFO中写入数据
  for (i = 0; i < len; i++)
  {
    Write_MFRC522(FIFODataReg, *(pIndata + i));
  }
  //向MFRC522的某一寄存器写一个字节数据
  Write_MFRC522(CommandReg, PCD_CALCCRC);

  //等待CRC计算完成
  i = 0xFF;
  do
  {
    n = Read_MFRC522(DivIrqReg);
    i--;
  }
  while ((i != 0) && !(n & 0x04));      //CRCIrq = 1

  //读取CRC计算结果
  pOutData[0] = Read_MFRC522(CRCResultRegL);
  pOutData[1] = Read_MFRC522(CRCResultRegM);
}


/*
   函 数 名:MFRC522_SelectTag
   功能描述:选卡,读取卡存储器容量
   输入参数:serNum--传入卡序列号
   返 回 值:成功返回卡容量
*/
uchar MFRC522_SelectTag(uchar *serNum)
{
  uchar i;
  uchar status;
  uchar size;
  uint recvBits;
  uchar buffer[9];

  //ClearBitMask(Status2Reg, 0x08);     //MFCrypto1On=0

  buffer[0] = PICC_SElECTTAG;
  buffer[1] = 0x70;
  for (i = 0; i < 5; i++)
  {
    buffer[i + 2] = *(serNum + i);
  }
  CalulateCRC(buffer, 7, &buffer[7]);   //??
  status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits);

  if ((status == MI_OK) && (recvBits == 0x18))
  {
    size = buffer[0];
  }
  else
  {
    size = 0;
  }

  return size;
}


/*
   函 数 名:MFRC522_Auth
   功能描述:验证卡片密码
   输入参数:authMode--密码验证模式
                 0x60 = 验证A密钥
                 0x61 = 验证B密钥
             BlockAddr--块地址
             Sectorkey--扇区密码
             serNum--卡片序列号,4字节
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_Auth(uchar authMode, uchar BlockAddr, uchar *Sectorkey, uchar *serNum)
{
  uchar status;
  uint recvBits;
  uchar i;
  uchar buff[12];

  //验证指令+块地址+扇区密码+卡序列号
  buff[0] = authMode;
  buff[1] = BlockAddr;
  for (i = 0; i < 6; i++)
  {
    buff[i + 2] = *(Sectorkey + i);
  }
  for (i = 0; i < 4; i++)
  {
    buff[i + 8] = *(serNum + i);
  }
  status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits);

  if ((status != MI_OK) || (!(Read_MFRC522(Status2Reg) & 0x08)))
  {
    status = MI_ERR;
  }

  return status;
}


/*
   函 数 名:MFRC522_Read
   功能描述:读块数据
   输入参数:blockAddr--块地址;recvData--读出的块数据
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_Read(uchar blockAddr, uchar *recvData)
{
  uchar status;
  uint unLen;

  recvData[0] = PICC_READ;
  recvData[1] = blockAddr;
  CalulateCRC(recvData, 2, &recvData[2]);
  status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen);

  if ((status != MI_OK) || (unLen != 0x90))
  {
    status = MI_ERR;
  }

  return status;
}


/*
   函 数 名:MFRC522_Write
   功能描述:写块数据
   输入参数:blockAddr--块地址;writeData--向块写16字节数据
   返 回 值:成功返回MI_OK
*/
uchar MFRC522_Write(uchar blockAddr, uchar *writeData)
{
  uchar status;
  uint recvBits;
  uchar i;
  uchar buff[18];

  buff[0] = PICC_WRITE;
  buff[1] = blockAddr;
  CalulateCRC(buff, 2, &buff[2]);
  status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits);

  if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
  {
    status = MI_ERR;
  }

  if (status == MI_OK)
  {
    for (i = 0; i < 16; i++)    //向FIFO写16Byte数据
    {
      buff[i] = *(writeData + i);
    }
    CalulateCRC(buff, 16, &buff[16]);
    status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits);

    if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A))
    {
      status = MI_ERR;
    }
  }

  return status;
}


/*
   函 数 名:MFRC522_Halt
   功能描述:命令卡片进入休眠状态
   输入参数:无
   返 回 值:无
*/
void MFRC522_Halt(void)
{
  uchar status;
  uint unLen;
  uchar buff[4];

  buff[0] = PICC_HALT;
  buff[1] = 0;
  CalulateCRC(buff, 2, &buff[2]);

  status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen);
}
posted @ 2020-06-06 21:30  icloudelectron  阅读(356)  评论(0编辑  收藏  举报