基于STM32的MFRC522射频卡模块使用

本学期感测技术选修课需要做一个作品出来,用到了MFRC522射频卡模块,经历一个星期的调试,终于可以正常使用并寻卡成功了了。 成功的把C51的程序移植到了STM32上面。 现在分享一下调试过程

1、操作环境

我所使用的是STM32F407的开发板,使用STM32CubeMX配置初始代码。 MFRC522使用软件模拟SPI通信

2、 关于引脚的配置

淘宝买来的模块,店家都会送资料 ,也可以点下面连接保存至网盘

链接:https://pan.baidu.com/s/1boMyMlx

1、SPI通信引脚

 NSS(SDA)       --------->> 片选信号SCK            --------->> 时钟信号MOSI           --------->> 信号输出端(即单片机引脚设置为输入,MFRC522该引脚输出)MISO           --------->> 信号输入端


(上图截图于数据手册,移植别人的程序最好看一下所使用的芯片的数据手册,很有用,方便自己理解程序)

这里说明一下,在 MFRC522数据手册里面说了, MFRC522需要工作在从机模式下。
所以MFRC522这个模块就是从机(Slave),而所使用的单片机就是主机(Master)

这就是为什么上面的MOSI对应的单片机引脚要设置为输出,(Master Output Slave Input)
MISO信号输入端是指的输入给单片机了

2、 通信时序

这是数据手册里面的,一定要注意时序的正确性

片选信号在数据写入期间一定要保持低电平,而无数据时(即空闲状态)必须保持高电平

强调:时序很重要

时序出错,一切都白扯

3、 程序流程

下面我把我用STM32CubeMX的配置贴出来

一定要注意按照这样配置,因为数据手册里面的时序要求是NSS(SDA)引脚默认状态必须是高电平,即1,所以IO口设置必须为High, 且上拉,其他引脚同理,只是不需要上拉了

3、 下面先贴一下寻卡结果

S50的卡是0x04000, 所以打印的就是40了

主函数里面程序

int main(void)
{/* USER CODE BEGIN 1 */unsigned char status,i;unsigned int temp;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */printf("The USART Is Ok!!!\r\n");//  下面进行的是初始化PcdReset();PcdAntennaOff(); //关闭天线PcdAntennaOn();  //开启天线M500PcdConfigISOType('A');  // 选择工作方式printf("开始寻卡... ...\r\n");/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */status = PcdRequest(PICC_REQALL, g_ucTempbuf);//寻卡if (status == MI_ERR)     // 如果寻卡失败,则重新初始化 然后continue 继续寻卡{PcdReset();PcdAntennaOff(); //关闭天线PcdAntennaOn();  //开启天线M500PcdConfigISOType('A');continue;}         // 如果寻卡成功  则LED1闪烁   然后串口打印出来卡的类型HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);HAL_Delay(10);HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);HAL_Delay(10);HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);HAL_Delay(10);HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);HAL_Delay(10);printf("\r\n卡的类型:");for (i = 0; i < 2; i++){temp = g_ucTempbuf[i];printf("%X", temp);}//PcdHalt();}/* USER CODE END 3 */
}

主程序前面还要定义一个变量,要不然会出现g_ucTempbuff未定义的情况:

unsigned char g_ucTempbuf[20];

下面是我移植的底层驱动程序,应该也是大部分人想要的吧,不过最好还是自己好好看看那手册改一下
我只贴出有关SPI通讯的程序,其他部分跟我上面给出的网盘资料里面的C51例程是差不多的,通用

/*******************************************************************@func       : ReadRawRC@brief  : 读RC632寄存器@pram       : Address[IN]:寄存器地址@retval : 读出的值@NOTE        : MFRC522数据手册.pdf 10.2是关于SPI的详细说明   10.2.2 Read data: unsigned char === uint8_t@Call        : 内部调用
*******************************************************************/
unsigned char ReadRawRC(unsigned char Address)
{unsigned char i, ucAddr;unsigned char ucResult=0;HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);// MF522_NSS = 0;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);// MF522_SCK = 0;// 地址左移一位是因为LSB是要保留 即RFU位(Reserved for Future Use)// &0x7E 是把bit1~bit6 的地址(address)写入// |0x80 是为了使最高位为1   1(Read) 0(Write) 即使能 '读'ucAddr = ((Address<<1)&0x7E)|0x80;for(i=8;i>0;i--){if((ucAddr&0x80)==0x80){HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET);}else{HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET);}HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);ucAddr <<= 1;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);}for(i=8;i>0;i--){HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);ucResult <<= 1;ucResult |= HAL_GPIO_ReadPin(MISO_GPIO_Port, MISO_Pin);HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);// 有人说对于STM32这里需要加一句延时,这个是没必要的  这个我经过测试是可以使用的,不用延时}HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);// MF522_NSS = 1;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);// MF522_SCK = 1; return ucResult;
}/*******************************************************************@func     : WriteRawRC@brief     : 写RC632寄存器@pram       : Address[IN]:寄存器地址: value[IN]:写入的值@retval : None@Call        : 内部调用
*******************************************************************/
void WriteRawRC(unsigned char Address, unsigned char value)
{  unsigned char i, ucAddr;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);// MF522_SCK = 0;HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);// MF522_NSS = 0;ucAddr = ((Address << 1) & 0x7E);for(i=8;i>0;i--){if ((ucAddr&0x80)==0x80){HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET);}else{HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET);}HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);ucAddr <<= 1;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);}for(i=8;i>0;i--){// MF522_SI = ((value&0x80)==0x80);if ((value&0x80)==0x80){HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET);}else{HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET);}HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);value <<= 1;HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);}HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);// MF522_NSS = 1; HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);// MF522_SCK = 1;}

复位函数

/*******************************************************************@func       : PcdReset@brief       : 复位RC522@pram     : None@retval  : 成功返回MI_OK@NOTE       : 外部调用
*******************************************************************/
char PcdReset(void)
{/* MF522_RST=1; */HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);HAL_Delay(10);/* MF522_RST=0; */HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);HAL_Delay(10);/* MF522_RST=1; */HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);HAL_Delay(10);WriteRawRC(CommandReg,PCD_RESETPHASE);    // 复位HAL_Delay(10);WriteRawRC(ModeReg,0x3D);                // 和Mifare卡通讯,CRC初始值0x6363WriteRawRC(TReloadRegL,30);            // 16位定时器低位WriteRawRC(TReloadRegH,0);               // 16位定时器高位WriteRawRC(TModeReg,0x8D);               // 定时器内部设置WriteRawRC(TPrescalerReg,0x3E);           // 定时器分频系数设置WriteRawRC(TxAutoReg, 0x40);            // 调制发送信号为100%ASK    调试的时候加上这一句试试return MI_OK;
}

其他的底层驱动函数就不需要改了,由于总的代码量比较长,我就只贴出关键的,其他不需要改的直接参考资料里面的例程即可
我自己移植过来完整的有很多程序的注注释,有兴趣的可以下载一下,不过自己花时间看看数据手册打个注释是最好的

点击这里下载完整移植驱动程序

任何你的不足,在你成功地那一刻,都会被别人说成特色!! 加油吧

STM32F407使用MFRC522射频卡调试及程序移植成功相关推荐

  1. STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID(二)

    本文继上一篇:STM32系列(HAL库)--F103C8T6通过MFRC522.RFID射频卡.门禁卡模块读取卡片ID 本文介绍在运用RC522模块时,运用链表结构存储数据的操作 Let's go! ...

  2. STM32系列(HAL库)——F103C8T6通过MFRC522、RFID射频卡、门禁卡模块读取卡片ID

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)MFRC-522模块 (2)F1的板子,本例使用经典F103C8T6 (3)ST-li ...

  3. STM32 单片机 程序 指纹 门禁锁 RC522 射频卡 发短信 报警

    功能按这个做: 功能设计如下: 硬件:单片机+显示器+指纹模块+继电器+按键+振动模块+发短信模块+人体红外+RC522射频卡刷卡模块+震动模块 1 开机后,检测指纹模块是否存在,如不存在,屏幕会有相 ...

  4. 三、开发调试应用程序

    我们今天将使用三种方式,把我们自己写的helloworld程序在开发板上运行起来.分别是以下三种: 借助U盘开发调试应用程序 借助TF卡开发调试应用程序 把程序打包进最小linux文件系统镜像里 一. ...

  5. 非接触式IC智能(射频)卡

    一.Mifare 1非接触式IC智能射频卡特点 Mifare 1 IC智能(射频)卡的核心是Philips 公司的Mifare 1 IC S50(-01,-02,-03,-04)系列微模块(微晶片). ...

  6. 射频卡读写原理及实现

    射频卡又称非接触式IC卡,它将RFID和IC技术完美结合,使卡片能够在不需要电源及与读卡器不接触的情况下正常工作.目前射频卡已经广泛使用在社会生活的各个领域,如银行卡.企业一卡通系统等.由于射频卡具有 ...

  7. 一种射频卡读写原理及实现

    原文:http://bbs.dzsc.com/space/viewspacepost.aspx?postid=95408 非接触式IC卡又称射频卡,由IC芯片.感应天线组成,封装在一个标准的PVC卡片 ...

  8. Mifare l射频卡初始值及其相关说明

    Mifare l射频卡初始值及其相关说明 [本说明是Mifare 1 卡订货合同不可缺少的技术性文档附件] 电气特性: 容量为8K位EEPrOM: ● 分为16个扇区,每个扇区为4块,每块16个字节, ...

  9. 农业节水自动灌溉 ic射频卡机井灌溉控制器智能取水

    乡村振兴战略大力推进乡村生态文明建设,数字化乡村近年来得到大力推崇,农业生产作为乡村发展的重要组成之一也逐渐趋于自动化.智能化.计讯物联ic射频卡机井灌溉控制器助力农业智能灌溉,可实现远程用水量监测. ...

  10. 射频识别技术漫谈(28)——基于MF1射频卡的酒店门锁设计

    [转自]http://blog.sina.com.cn/s/blog_9ed067ad0101dupi.html 电子门锁是现代星级酒店管理电子化.智能化的重要电子设备.相较于传统的机械锁,基于RFI ...

最新文章

  1. html动画图片重叠,不一样的层叠照片动画-ANIMATED CSS3 PHOTO STACK
  2. Android 事件分发面试
  3. 线程访问 DevExpress控件异常时 解决方法
  4. Ubuntu16.04安装Xtion驱动并测试使用
  5. 报告解读|远程银行:从扎根网络到加速上云
  6. 使用Reactor进行反应式编程最全教程
  7. 【IT资讯】Linus Torvalds:我们都老了,但Linux维护真的很难找
  8. 20175305张天钰 《java程序设计》第四周课下测试总结
  9. Derek解读Bytom源码-P2P网络 地址簿
  10. tipask二次开发总结_二次开发自我总结
  11. swift 字符串转int_Swift Tips Streamline 如何假装写过 Swift
  12. 同样是软件测试工程师,为什么性能测试月薪更高?
  13. 数据库学习笔记6-隔离级别 Serializable
  14. 大学计算机基础发送邮件,东南大学《大学计算机基础》实验16邮件合并.pdf
  15. 蓝牙智能音响测试软件,【天猫精灵蓝牙音箱使用总结】APP|连接|音质|资源|控制_摘要频道_什么值得买...
  16. 可以批量把Word文件转成JPG的软件工具
  17. 员工年终绩效考核表模板
  18. 仿ios相机apk_icamera仿苹果安卓版-icamera仿苹果软件下载-多多root网
  19. 【小5聊】前端基础之上传图片等文件IE浏览器是会显示两个请求
  20. 2018年第50周-maven脚手架: jc-spring-boot-rest-archetype

热门文章

  1. Windows核心编程_修改其它进程里的内存值+示例:修改游戏分数
  2. WPF版的权限管理系统
  3. 关于jquery中html()、text()、val()的区别
  4. 【吴恩达机器学习】学习笔记——4多元线性回归
  5. 《Lua游戏开发实践指南》一3.2游戏项目中的Lua
  6. 成都Uber优步司机奖励政策(1月16日)
  7. PFSense 2.1 端口映射配置
  8. Silverlight 游戏开发小技巧:扇形排列元素
  9. JS中实现Trim(),TrimStart(),TrimEnd() 的方法
  10. 英文论文中“such as, for example, e.g., i.e., etc., et al. ”的用法分析 (转)