完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
基于STM32的MFRC522射频卡模块使用
本学期感测威廉希尔官方网站 选修课需要做一个作品出来,用到了MFRC522射频卡模块,经历一个星期的调试,终于可以正常使用并寻卡成功了了。 成功的把C51的程序移植到了STM32上面。 现在分享一下调试过程 1、操作环境 我所使用的是STM32F407的开发板,使用STM32CubeMX配置初始代码。 MFRC522使用软件模拟SPI通信 2、 关于引脚的配置 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了 主函数里面程序 1 int main(void) 2 { 3 /* USER CODE BEGIN 1 */ 4 unsigned char status,i; 5 unsigned int temp; 6 7 /* USER CODE END 1 */ 8 9 /* MCU Configuration--------------------------------------------------------*/ 10 11 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 12 HAL_Init(); 13 14 /* USER CODE BEGIN Init */ 15 16 /* USER CODE END Init */ 17 18 /* Configure the system clock */ 19 SystemClock_Config(); 20 21 /* USER CODE BEGIN SysInit */ 22 23 /* USER CODE END SysInit */ 24 25 /* Initialize all configured peripherals */ 26 MX_GPIO_Init(); 27 MX_USART1_UART_Init(); 28 /* USER CODE BEGIN 2 */ 29 30 printf(“The USART Is Ok!!!rn”); 31 32 // 下面进行的是初始化 33 PcdReset(); 34 PcdAntennaOff(); //关闭天线 35 PcdAntennaOn(); //开启天线 36 M500PcdConfigISOType(‘A’); // 选择工作方式 37 38 printf(“开始寻卡。.. 。..rn”); 39 /* USER CODE END 2 */ 40 41 /* Infinite loop */ 42 /* USER CODE BEGIN WHILE */ 43 while (1) 44 { 45 /* USER CODE END WHILE */ 46 47 /* USER CODE BEGIN 3 */ 48 49 status = PcdRequest(PICC_REQALL, g_ucTempbuf);//寻卡 50 if (status == MI_ERR) // 如果寻卡失败,则重新初始化 然后continue 继续寻卡 51 { 52 PcdReset(); 53 PcdAntennaOff(); //关闭天线 54 PcdAntennaOn(); //开启天线 55 M500PcdConfigISOType(‘A’); 56 continue; 57 } 58 59 // 如果寻卡成功 则LED1闪烁 然后串口打印出来卡的类型 60 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); 61 HAL_Delay(10); 62 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); 63 HAL_Delay(10); 64 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); 65 HAL_Delay(10); 66 HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); 67 HAL_Delay(10); 68 printf(“rn卡的类型:”); 69 for (i = 0; i 《 2; i++) 70 { 71 temp = g_ucTempbuf[i]; 72 printf(“%X”, temp); 73 } 74 //PcdHalt(); 75 } 76 /* USER CODE END 3 */ 77 } 下面是我移植的底层驱动程序,应该也是大部分人想要的吧,不过最好还是自己好好看看那手册改一下 我只贴出有关SPI通讯的程序,其他部分跟我上面给出的网盘资料里面的C51例程是差不多的,通用 1 /******************************************************************* 2 @func : ReadRawRC 3 @brief : 读RC632寄存器 4 @pram : Address[IN]:寄存器地址 5 @retval : 读出的值 6 @NOTE : MFRC522数据手册.pdf 10.2是关于SPI的详细说明 10.2.2 Read data 7 : unsigned char === uint8_t 8 @Call : 内部调用 9 *******************************************************************/ 10 unsigned char ReadRawRC(unsigned char Address) 11 { 12 unsigned char i, ucAddr; 13 unsigned char ucResult=0; 14 15 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);// MF522_NSS = 0; 16 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);// MF522_SCK = 0; 17 18 19 // 地址左移一位是因为LSB是要保留 即RFU位(Reserved for Future Use) 20 // &0x7E 是把bit1~bit6 的地址(address)写入 21 // |0x80 是为了使最高位为1 1(Read) 0(Write) 即使能 ‘读’ 22 ucAddr = ((Address《《1)&0x7E)|0x80; 23 24 for(i=8;i》0;i--) 25 { 26 if((ucAddr&0x80)==0x80) 27 { 28 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET); 29 } 30 else 31 { 32 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET); 33 } 34 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); 35 ucAddr 《《= 1; 36 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); 37 38 } 39 40 for(i=8;i》0;i--) 41 { 42 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); 43 ucResult 《《= 1; 44 ucResult |= HAL_GPIO_ReadPin(MISO_GPIO_Port, MISO_Pin); 45 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); 46 // 有人说对于STM32这里需要加一句延时,这个是没必要的 这个我经过测试是可以使用的,不用延时 47 } 48 49 50 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);// MF522_NSS = 1; 51 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);// MF522_SCK = 1; 52 53 54 return ucResult; 55 } 56 57 58 59 /******************************************************************* 60 @func : WriteRawRC 61 @brief : 写RC632寄存器 62 @pram : Address[IN]:寄存器地址 63 : value[IN]:写入的值 64 @retval : None 65 @Call : 内部调用 66 *******************************************************************/ 67 void WriteRawRC(unsigned char Address, unsigned char value) 68 { 69 unsigned char i, ucAddr; 70 71 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);// MF522_SCK = 0; 72 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);// MF522_NSS = 0; 73 74 ucAddr = ((Address 《《 1) & 0x7E); 75 76 for(i=8;i》0;i--) 77 { 78 if ((ucAddr&0x80)==0x80) 79 { 80 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET); 81 } 82 else 83 { 84 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET); 85 } 86 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); 87 ucAddr 《《= 1; 88 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); 89 } 90 91 92 for(i=8;i》0;i--) 93 { 94 // MF522_SI = ((value&0x80)==0x80); 95 if ((value&0x80)==0x80) 96 { 97 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_SET); 98 } 99 else 100 { 101 HAL_GPIO_WritePin(MOSI_GPIO_Port, MOSI_Pin, GPIO_PIN_RESET); 102 } 103 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); 104 value 《《= 1; 105 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); 106 } 107 108 109 110 111 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);// MF522_NSS = 1; 112 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);// MF522_SCK = 1; 113 114 } 复位函数 1 /******************************************************************* 2 @func : PcdReset 3 @brief : 复位RC522 4 @pram : None 5 @retval : 成功返回MI_OK 6 @NOTE : 外部调用 7 *******************************************************************/ 8 char PcdReset(void) 9 { 10 /* MF522_RST=1; */ 11 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET); 12 HAL_Delay(10); 13 /* MF522_RST=0; */ 14 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET); 15 HAL_Delay(10); 16 /* MF522_RST=1; */ 17 HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET); 18 HAL_Delay(10); 19 WriteRawRC(CommandReg,PCD_RESETPHASE); // 复位 20 HAL_Delay(10); 21 22 WriteRawRC(ModeReg,0x3D); // 和Mifare卡通讯,CRC初始值0x6363 23 WriteRawRC(TReloadRegL,30); // 16位定时器低位 24 WriteRawRC(TReloadRegH,0); // 16位定时器高位 25 WriteRawRC(TModeReg,0x8D); // 定时器内部设置 26 WriteRawRC(TPrescalerReg,0x3E); // 定时器分频系数设置 27 WriteRawRC(TxAutoReg, 0x40); // 调制发送信号为100%ASK 调试的时候加上这一句试试 28 return MI_OK; 29 } 其他的底层驱动函数就不需要改了,由于总的代码量比较长,我就只贴出关键的,其他不需要改的直接参考资料里面的例程即可 我自己移植过来完整的有很多程序的注注释,有兴趣的可以下载一下,不过自己花时间看看数据手册打个注释是最好的 任何你的不足,在你成功地那一刻,都会被别人说成特色!! 加油吧 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1804 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1629 浏览 1 评论
1097 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
736 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1686 浏览 2 评论
1944浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
747浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
580浏览 3评论
602浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
565浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-28 09:53 , Processed in 0.844940 second(s), Total 74, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号