RC522读卡器 M1卡学习总结(二)

RC522读卡器 M1卡学习总结(二)二、说说RC522读卡器       我从淘宝里买来的读卡器模块如下:M1卡 学习总结(二)”title=”RC522读卡器 M1卡 学习总结(二)”style=”margin:0px;padding:0px;border:0px;list-style:none”>它带有一组接口:SDA  SCK  MOSI  MISO  IRQ(NG)  GND  RST  3

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

二、说说RC522读卡器

       我从淘宝里买来的读卡器模块如下:

                                            —-》防冲突检查(Anticollision Loop)选择一张卡片,返回该卡序列号;

                                           —–》选择卡片(Select Tag),选择被选中的卡的序列号,返回卡的容量代码;

                                           —–》三次互相确认(3 Pass Authentication)通过密码校验之后,三次互相认                                             证                                                   之后可以通讯。

 

M1卡指令:

                 读(Read):读一个块;

                 写(Write):写一个块;

                 加值(Increment):对数值块进行加值;

                 减值(Decrement):对数值块进行减值;

                 存储(Restore):将块中数据保存到数据寄存器中;

                 传输(Transfer):将数据寄存器中内容写入到块中;

                 终止(Halt):将卡置于暂停工作状体。


三、RC522读卡器的使用–硬件部分

       我使用了stm8s103来驱动RC522读卡器,硬件连接如下:

      stm8s103引脚                      RC522接口

      3.3v                    ———-   3.3v

      GND                   ———    GND

      PC4                    ———     SDA(NSS)

      PC5(SPI_SCK)    ———     SCK

      PC6(SPI_MISO) ———     MISO

      PC7(SPI_MOSI) ———     MOSI

      至少接这6针。

 

     使用stm8s芯片的spi接口来和rc522通讯,通过相应的寄存器可控制SPI接口的数据传输率、数据时钟相位等通信参数。

     这里使用spi通讯,1/4分频,空闲低电平,第一个时钟周期开始采样,第一个时钟边缘开始数据采样。

注意:片选信号必须保证在写入数据流期间为低电平,而在无数据流写入时为高电平,不得为了省事而一直将NSS置为低电平。


四、单片机stm8s与读卡器RC522通讯—-软件部分

      单片机与读卡器的接口

      RC522读卡器提供三种接口,分别是UART,I2C,SPI这三种接口。我们这里选择了spi接口。关于stm8s为主机,rc522读卡器为从机。spi使用4个管脚与从设备相连,MISO,MOSI,SCK,NSS.

       这里有一点需要注意:MOSI管脚相互连接,MISO脚相互连接。这样,数据在主和从之间串行地传输(MSB位在前)。通信总是由主设备发起。主设备通过MOSI脚把数据发送给从设备,从设备通过MISO引脚回传数据。这意味全双工通信的数据输出和数据输入是用同一个时钟信号同步的:时钟信号由主设备通过SCK脚提供。

(1)SPI初始化如下:

void init_SPI_Master(void)
       
        SPI_CR1 = 0x04;          //fMaster/2, 配置为主设备,空闲低电平,第一个时钟周期开始采样
        SPI_CR2 = 0x03;           //内部指定主模式,NSS上电平决定该位值
        SPI_CRCPR = 0x07;
        SPI_ICR = 0x00;            //中断禁止
        SPI_CR1 |= 0x40;          //开启SPI

}

(2)UART初始化,这里为了调试方便,我们使用uart接口来观察执行情况。

void init_UART(void)
{

       UART1_CR2=0x00;//使发送禁用TEN=0;
       UART1_CR1=0x00;//设置M字长,8位数据位
       UART1_CR3=0x00;//1位停止位
 
       UART1_BRR2=0X00;      //波特率9600,分频系数=2000000/9600=208
       UART1_BRR1=0X0D;       //208=0X0D;
       UART1_CR2=0X2C;       //b3=1,允许发送  b2=1,允许接收  b5=1,允许产生接收中断
}

 (3)UART发送数据函数

void UARTSend(uchar aa)
{

  UART1_CR2=0x00;
  UART1_DR=aa;                   

  UART1_CR2=0x08;
  while((UART1_SR & 0x40) ==0);
  UART1_CR2=0x2c;//0x2c;//0x08; 2位 rev使能 3位 发送使能 5–rien 
}

(4)UART接收中断处理函数

@far @interrupt void UART1_RX_IRQHandler(void)  //UART1_Receiver(void)
{

     unsigned char i;
     _asm(“sim”);    //关总中断
      a=UART1_DR;      //将接收的字符放到a中
     _asm(“rim”);    //开总中断
    return;
}

(5)SPI接收发送字节

//spi接口在写的时候要先发送,发送不一定要传送内容,只是为了
//给从机提供时钟,因为sck是主机来发出的,所以写函数里面要有发送指令,目的是提供从机写时钟
uchar SPIWriteByte(uchar spiData)
{

   uchar retry=0;
  while((SPI_SR & 0X02)==0)  //等待发送区空
  {

   retry++;
   if(retry>200) return 0;  //防止死机
  }
 
  SPI_DR=spiData;             //发送一个byte
  retry=0;
  while((SPI_SR|0X80)==0X80);  //等待通信结束
 
  while((SPI_SR & 0X01)==0);  //等待接收缓冲区空
  {

     retry++;
    if(retry>200) return 0;
  }
  return SPI_DR;    //返回受到的数
 

}

(6)main.c主程序函数

void main()
{

 uchar i;
 uchar Card_Type1[2];
 uchar Card_ID[4];
 uchar Card_KEY[6] = {0xff,0xff,0xff,0xff,0xff,0xff};  
 uchar Card_Data[16];
 uchar status;
  //fmaster=fcpu=2MHz
 CLK_ECKR=0x00;
 CLK_ICKR=0x01;
 CLK_CMSR=0xe1;
 
 CLK_SWR=0xe1;
 CLK_CKDIVR=0x18;

 init_IO();
 init_UART();
 init_SPI_Master();
 
 _asm(“rim”);    //开总中断,便于产生串口接收中断

 status=PcdReset();
 PcdAntennaOff();
 delay(20);
 PcdAntennaOn();
 M500PcdConfigISOType( ‘A’ );
 a=0x63;
 nblock=4;//kuan 0
 t=0;
 while(1)
 {

  

        //    PcdAntennaOff();
        //测试一下接口是否正确
        status = CheckMCURC522interface();
        if(status != MI_OK)
        {

             UARTSend(0x04);
             continue;
        }
    
         status = PcdRequest(PICC_REQALL, g_ucTempbuf);
           if (status != MI_OK)
          {    
              continue;
           }
         //  UARTSend(a);//0x11);
         //  for(i=0;i<8;i++)
         //  UARTSend(g_ucTempbuf[i]);//0400 e52b 0000000000
       

         delay(20);//

         status = PcdAnticoll(g_ucTempbuf);
         if (status != MI_OK)
         {    continue;    }
         //   UARTSend(0x12);
         delay(20);//delay_ms(2);
         status = PcdSelect(g_ucTempbuf);
         if (status != MI_OK)
         {    continue;    }
        //   UARTSend(0x13);
         delay(20);//

       //   UARTSend(nblock);
       //认证卡
         status = PcdAuthState(PICC_AUTHENT1A, nblock, DefaultKey, g_ucTempbuf);
         if (status != MI_OK)
         {    continue;    }
        //   UARTSend(0x14);
        delay(20);//

       if(a==b) continue;
       else b=a;
       UARTSend(a);  //发送执行的命令代码
     switch(a)
     {

     case 0x91://写电子钱包数据到块nblock
       status = PcdWrite(nblock, data1);
         if(status==MI_OK)
       {

        UARTSend(0x88);
        
       }
       else UARTSend(0x44);
       break;
     case 0x92://写普通数据到块nblock
       status = PcdWrite(nblock, data3);
         if(status==MI_OK)
       {

        UARTSend(0x88);
        
       }
       else UARTSend(0x44);
         break;
     case 0x93://从块n中读取数据
       status = PcdRead(nblock, g_ucTempbuf);//PcdRead(2, g_ucTempbuf);
        if (status == MI_OK)
        {   
        UARTSend(0x88);
        for(i=0;i<16;i++)
         UARTSend(g_ucTempbuf[i]);//把写进去的数
        }
        else  UARTSend(0x44);
        break;
     case 0x94://从块n中读取数据
       status = PcdRead(nblock, g_ucTempbuf);//PcdRead(2, g_ucTempbuf);
        if (status == MI_OK)
        {   
        UARTSend(0x88);
        for(i=0;i<16;i++)
         UARTSend(g_ucTempbuf[i]);//把写进去的数
        }
        else  UARTSend(0x44);
        break;
     case 0x95://操作电子钱包
       status = PcdValue(PICC_DECREMENT,nblock,data2);
       if (status == MI_OK)
        
         UARTSend(0x88);
         for(i=0;i<4;i++)
           UARTSend(data2[i]);//
       }
        else  UARTSend(0x44);
       break;
     case 0x96: //备份电子钱包
       status = PcdBakValue(nblock, nblock+1);
        if (status == MI_OK)
        
         UARTSend(0x88);
        
       }
        else  UARTSend(0x44);
        break;
     default:break;
     
     }
    
       
  //    PcdHalt();
  //    PcdAntennaOff();
 }
}

(7)RC522的库函数和网上都基本一样,就不写了。

以上程序本人已经测试过了。

 

(8)本人在学习rc522的过程中参考了很多文章,在此表示感谢!

M1卡介绍  http://wenku.baidu.com/view/62cccb122e3f5727a4e9625c.html

M1卡激活成功教程密码控制位及控制规则http://www.docin.com/p-624326551.html

Mifare1技术说明(M1卡说明文档) http://www.docin.com/p-379085837.html

基于非接触式ic卡的读卡器的设计与开发http://www.docin.com/p-906980594.html

      13.56M读卡器开发详解二http://blog.sina.com.cn/s/blog_6754612e0101c0pe.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/193779.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • github邮箱验证不了_为什么github注册不成功

    github邮箱验证不了_为什么github注册不成功要使用github必须先注册个github账号,注册之后会有一个邮箱验证的步骤需要做但是如果你使用126,163或者其它的一些免费邮箱,极有可能是收不到邮箱的,这个就麻烦了不过,qq邮箱目前是可以使用的,         不过也可能出现收不到的情况,那就换个qq邮箱再试,         如果还不行,换个时间段再试;   

  • tcpdf_teambition搭建

    tcpdf_teambition搭建tcpdf开发文档(中文翻译版)2017年5月3日15:06:15这个是英文翻译版,我看过作者的文档其实不太友善或者不方便阅读,不如wiki方便后面补充一些,结构性文档翻译这是一部官方网站文档,剩余大部分都是开发的时候和网络总结来的项目官网:https://tcpdf.org/github:https://github.com/tecnickcom/TCPDF都没比较完整的api文档…

  • 常见内网IP段_内网ip是什么

    常见内网IP段_内网ip是什么常见内网IP段局域网,解决了ipv4地址不够用的问题。同时方便维护管理。局域网地址范围分三类,以下IP段为内网IP段:C类:192.168.0.0-192.168.255.255B类:172.16.0.0-172.31.255.255A类:10.0.0.0-10.255.255.255…

  • react 中组件状态的一些理解

    react 中组件状态的一些理解

    2020年11月19日
  • PHP环境搭建单独安装「建议收藏」

    PHP环境搭建单独安装「建议收藏」Php环境的搭建主要内容:1、知识回顾2、几种常见的PHP环境安装方式3、安装php的运行环境4、php运行环境的介绍1.知识回顾1.1动态网站和静态网站web1.0(静态网站):不支

  • php rewriterule 规则,如何将一条RewriteCond 对应多个RewriteRule规则

    php rewriterule 规则,如何将一条RewriteCond 对应多个RewriteRule规则RewriteCond是对RewriteRule的条件筛选,一般情况下一个RewriteRule前面有多个RewriteCond,我们想让bbs这个子域名下的链接访问bbs这个目录,而其他子域名则访问web这个子目录,于是有了下面这种写法。RewriteCond%{HTTP_HOST}^bbs.heycode.com$RewriteRule^news-(d+).html$/bbs/news…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号