当前位置:   article > 正文

(HAL)STM32F103C8T6——RC522与主机进行SPI通信(RFID门禁系统入门必备)_rc522 stm32f103c8t6

rc522 stm32f103c8t6

目录

一、MFRC522简介

二、接线

三、存储结构说明

四、代码解析

1、rc522.h

2、rc522.c

3、spi.h

4、spi.c

5、main.c


一、MFRC522简介

店家提供的资料:
提取码:su3m
简言之,MFRCC522是基于SPI通信协议与主机进行通信的模块,可实现RFID无线通信,常用于门禁系统、支付系统等。SPI通信原理细节可看往期笔记。 STM32F4——SPI通信
本篇笔记主要介绍MFRC522模块。

二、接线

STM32
RC522
PB12
SDA
PB13
SCK
PB14
MOSI
PB15
MISO
悬空
IRQ
GND
GND
PB1
RST
VCC
VCC
使用SPI2, 记住主机的MOSI和从机的MOSI相连,不是交叉相连!!!!!!!

三、存储结构说明

利用 软件NFC WRITER对NFC卡扇区内存进行管理,可以查看存储信息,通过串口打印出来的前六个字节000000000000存在错误,应该为FFFFFFFFFFFF。
在网上搜了资料,有些朋友说扇区0是不能够写修改的,由厂家初始化,笔者刚开始也可以读取出来,但由于不熟悉且手贱,刚开始在探究NFC卡扇区的读与写时,错误操作于在扇区0第3区块直接写入六个字节(F1FFFFFFFFFF),之后用软件读取不出扇区的内存信息,怀疑是损坏了或者丢失了。现在密码A仍然可以验证为我写入的F1FFFFFFFFFF,但是密码B不知道是什么,也无法对扇区0内存储信息进行读取。

四、代码解析

1、rc522.h

  1. #ifndef _RC522_H
  2. #define _RC522_H
  3. #include "stm32f1xx_hal.h"
  4. /* CS/NSS/SDA均表示片选 */
  5. #define RC522_RST_Pin GPIO_PIN_1
  6. #define RC522_RST_GPIO_Port GPIOB
  7. #define RC522_CS_Pin GPIO_PIN_12
  8. #define RC522_CS_GPIO_Port GPIOB
  9. #define osDelay HAL_Delay
  10. #define RS522_RST(x) do{ x ? \
  11. HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, GPIO_PIN_SET) :\
  12. HAL_GPIO_WritePin(RC522_RST_GPIO_Port, RC522_RST_Pin, GPIO_PIN_RESET);\
  13. }while(0)
  14. #define RS522_NSS(x) do{ x ? \
  15. HAL_GPIO_WritePin(RC522_CS_GPIO_Port, RC522_CS_Pin, GPIO_PIN_SET) :\
  16. HAL_GPIO_WritePin(RC522_CS_GPIO_Port, RC522_CS_Pin, GPIO_PIN_RESET);\
  17. }while(0)
  18. /***********************************************************************************
  19. * MFRC522驱动程序 *
  20. ************************************************************************************/
  21. /*MFRC522寄存器定义*/
  22. //PAGE0
  23. #define MFRC_RFU00 0x00
  24. #define MFRC_CommandReg 0x01
  25. #define MFRC_ComIEnReg 0x02
  26. #define MFRC_DivlEnReg 0x03
  27. #define MFRC_ComIrqReg 0x04
  28. #define MFRC_DivIrqReg 0x05
  29. #define MFRC_ErrorReg 0x06
  30. #define MFRC_Status1Reg 0x07
  31. #define MFRC_Status2Reg 0x08
  32. #define MFRC_FIFODataReg 0x09
  33. #define MFRC_FIFOLevelReg 0x0A
  34. #define MFRC_WaterLevelReg 0x0B
  35. #define MFRC_ControlReg 0x0C
  36. #define MFRC_BitFramingReg 0x0D
  37. #define MFRC_CollReg 0x0E
  38. #define MFRC_RFU0F 0x0F
  39. //PAGE1
  40. #define MFRC_RFU10 0x10
  41. #define MFRC_ModeReg 0x11
  42. #define MFRC_TxModeReg 0x12
  43. #define MFRC_RxModeReg 0x13
  44. #define MFRC_TxControlReg 0x14
  45. #define MFRC_TxAutoReg 0x15 //中文手册有误
  46. #define MFRC_TxSelReg 0x16
  47. #define MFRC_RxSelReg 0x17
  48. #define MFRC_RxThresholdReg 0x18
  49. #define MFRC_DemodReg 0x19
  50. #define MFRC_RFU1A 0x1A
  51. #define MFRC_RFU1B 0x1B
  52. #define MFRC_MifareReg 0x1C
  53. #define MFRC_RFU1D 0x1D
  54. #define MFRC_RFU1E 0x1E
  55. #define MFRC_SerialSpeedReg 0x1F
  56. //PAGE2
  57. #define MFRC_RFU20 0x20
  58. #define MFRC_CRCResultRegM 0x21
  59. #define MFRC_CRCResultRegL 0x22
  60. #define MFRC_RFU23 0x23
  61. #define MFRC_ModWidthReg 0x24
  62. #define MFRC_RFU25 0x25
  63. #define MFRC_RFCfgReg 0x26
  64. #define MFRC_GsNReg 0x27
  65. #define MFRC_CWGsCfgReg 0x28
  66. #define MFRC_ModGsCfgReg 0x29
  67. #define MFRC_TModeReg 0x2A
  68. #define MFRC_TPrescalerReg 0x2B
  69. #define MFRC_TReloadRegH 0x2C
  70. #define MFRC_TReloadRegL 0x2D
  71. #define MFRC_TCounterValueRegH 0x2E
  72. #define MFRC_TCounterValueRegL 0x2F
  73. //PAGE3
  74. #define MFRC_RFU30 0x30
  75. #define MFRC_TestSel1Reg 0x31
  76. #define MFRC_TestSel2Reg 0x32
  77. #define MFRC_TestPinEnReg 0x33
  78. #define MFRC_TestPinValueReg 0x34
  79. #define MFRC_TestBusReg 0x35
  80. #define MFRC_AutoTestReg 0x36
  81. #define MFRC_VersionReg 0x37
  82. #define MFRC_AnalogTestReg 0x38
  83. #define MFRC_TestDAC1Reg 0x39
  84. #define MFRC_TestDAC2Reg 0x3A
  85. #define MFRC_TestADCReg 0x3B
  86. #define MFRC_RFU3C 0x3C
  87. #define MFRC_RFU3D 0x3D
  88. #define MFRC_RFU3E 0x3E
  89. #define MFRC_RFU3F 0x3F
  90. /*MFRC522的FIFO长度定义*/
  91. #define MFRC_FIFO_LENGTH 64
  92. /*MFRC522传输的帧长定义*/
  93. #define MFRC_MAXRLEN 18
  94. /*MFRC522命令集,中文手册P59*/
  95. #define MFRC_IDLE 0x00 //取消当前命令的执行
  96. #define MFRC_CALCCRC 0x03 //激活CRC计算
  97. #define MFRC_TRANSMIT 0x04 //发送FIFO缓冲区内容
  98. #define MFRC_NOCMDCHANGE 0x07 //无命令改变
  99. #define MFRC_RECEIVE 0x08 //激活接收器接收数据
  100. #define MFRC_TRANSCEIVE 0x0C //发送并接收数据
  101. #define MFRC_AUTHENT 0x0E //执行Mifare认证(验证密钥)
  102. #define MFRC_RESETPHASE 0x0F //复位MFRC522
  103. /*MFRC522通讯时返回的错误代码*/
  104. #define MFRC_OK (char)0
  105. #define MFRC_NOTAGERR (char)(-1)
  106. #define MFRC_ERR (char)(-2)
  107. /*MFRC522函数声明*/
  108. void MFRC_Init(void);
  109. void MFRC_WriteReg(uint8_t addr, uint8_t data);
  110. uint8_t MFRC_ReadReg(uint8_t addr);
  111. void MFRC_SetBitMask(uint8_t addr, uint8_t mask);
  112. void MFRC_ClrBitMask(uint8_t addr, uint8_t mask);
  113. void MFRC_CalulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData);
  114. char MFRC_CmdFrame(uint8_t cmd, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint16_t *pOutLenBit);
  115. /***********************************************************************************
  116. * MFRC552与MF1卡通讯接口程序 *
  117. ************************************************************************************/
  118. /*Mifare1卡片命令字*/
  119. #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态的卡
  120. #define PICC_REQALL 0x52 //寻天线区内全部卡
  121. #define PICC_ANTICOLL1 0x93 //防冲撞
  122. #define PICC_ANTICOLL2 0x95 //防冲撞
  123. #define PICC_AUTHENT1A 0x60 //验证A密钥
  124. #define PICC_AUTHENT1B 0x61 //验证B密钥
  125. #define PICC_READ 0x30 //读块
  126. #define PICC_WRITE 0xA0 //写块
  127. #define PICC_DECREMENT 0xC0 //减值(扣除)
  128. #define PICC_INCREMENT 0xC1 //增值(充值)
  129. #define PICC_TRANSFER 0xB0 //转存(传送)
  130. #define PICC_RESTORE 0xC2 //恢复(重储)
  131. #define PICC_HALT 0x50 //休眠
  132. /*PCD通讯时返回的错误代码*/
  133. #define PCD_OK (char)0 //成功
  134. #define PCD_NOTAGERR (char)(-1) //无卡
  135. #define PCD_ERR (char)(-2) //出错
  136. /*PCD函数声明*/
  137. void PCD_Init(void);
  138. void PCD_Reset(void);
  139. void PCD_AntennaOn(void);
  140. void PCD_AntennaOff(void);
  141. char PCD_Request(uint8_t RequestMode, uint8_t *pCardType); //寻卡,并返回卡的类型
  142. char PCD_Anticoll(uint8_t *pSnr); //防冲突,返回卡号
  143. char PCD_Select(uint8_t *pSnr); //选卡
  144. char PCD_AuthState(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr); //验证密码(密码A和密码B)
  145. char PCD_WriteBlock(uint8_t BlockAddr, uint8_t *pData); //写数据
  146. char PCD_ReadBlock(uint8_t BlockAddr, uint8_t *pData); //读数据
  147. char PCD_Value(uint8_t mode, uint8_t BlockAddr, uint8_t *pValue);
  148. char PCD_BakValue(uint8_t sourceBlockAddr, uint8_t goalBlockAddr);
  149. char PCD_Halt(void);
  150. void Cardcompare(void); //自行定义函数
  151. #endif

2、rc522.c

  1. #include "stm32f1xx_hal.h"
  2. #include "./BSP/RC522/rc522.h"
  3. #include "stdio.h"
  4. #include "./SYSTEM/usart/usart.h"
  5. #include <string.h>
  6. extern SPI_HandleTypeDef hspi2;
  7. /**************************************************************************************
  8. * 函数名称:MFRC_Init
  9. * 功能描述:MFRC初始化
  10. * 入口参数:无
  11. * 出口参数:无
  12. * 返 回 值:无
  13. * 说 明:MFRC的SPI接口速率为0~10Mbps
  14. ***************************************************************************************/
  15. void MFRC_Init(void)
  16. {
  17. RS522_NSS(1);
  18. RS522_RST(1);
  19. }
  20. /**************************************************************************************
  21. * 函数名称: SPI_RW_Byte
  22. * 功能描述: 模拟SPI读写一个字节
  23. * 入口参数: -byte:要发送的数据
  24. * 出口参数: -byte:接收到的数据
  25. ***************************************************************************************/
  26. static uint8_t ret; //这些函数是HAL与标准库不同的地方【读写函数】
  27. uint8_t SPI2_RW_Byte(uint8_t byte)
  28. {
  29. HAL_SPI_TransmitReceive(&hspi2, &byte, &ret, 1, 10);//把byte 写入,并读出一个值,把它存入ret
  30. return ret;//入口是byte 的地址,读取时用的也是ret地址,一次只写入一个值10
  31. }
  32. /**************************************************************************************
  33. * 函数名称:MFRC_WriteReg
  34. * 功能描述:写一个寄存器
  35. * 入口参数:-addr:待写的寄存器地址
  36. * -data:待写的寄存器数据
  37. * 出口参数:无
  38. * 返 回 值:无
  39. * 说 明:无
  40. ***************************************************************************************/
  41. void MFRC_WriteReg(uint8_t addr, uint8_t data)
  42. {
  43. uint8_t AddrByte;
  44. AddrByte = (addr << 1 ) & 0x7E; //求出地址字节
  45. RS522_NSS(0); //NSS拉低
  46. SPI2_RW_Byte(AddrByte); //写地址字节
  47. SPI2_RW_Byte(data); //写数据
  48. RS522_NSS(1); //NSS拉高
  49. }
  50. /**************************************************************************************
  51. * 函数名称:MFRC_ReadReg
  52. * 功能描述:读一个寄存器
  53. * 入口参数:-addr:待读的寄存器地址
  54. * 出口参数:无
  55. * 返 回 值:-data:读到寄存器的数据
  56. * 说 明:无
  57. ***************************************************************************************/
  58. uint8_t MFRC_ReadReg(uint8_t addr)
  59. {
  60. uint8_t AddrByte, data;
  61. AddrByte = ((addr << 1 ) & 0x7E ) | 0x80; //求出地址字节
  62. RS522_NSS(0); //NSS拉低
  63. SPI2_RW_Byte(AddrByte); //写地址字节
  64. data = SPI2_RW_Byte(0x00); //读数据
  65. RS522_NSS(1); //NSS拉高
  66. return data;
  67. }
  68. /**************************************************************************************
  69. * 函数名称:MFRC_SetBitMask
  70. * 功能描述:设置寄存器的位
  71. * 入口参数:-addr:待设置的寄存器地址
  72. * -mask:待设置寄存器的位(可同时设置多个bit)
  73. * 出口参数:无
  74. * 返 回 值:无
  75. * 说 明:无
  76. ***************************************************************************************/
  77. void MFRC_SetBitMask(uint8_t addr, uint8_t mask)
  78. {
  79. uint8_t temp;
  80. temp = MFRC_ReadReg(addr); //先读回寄存器的值
  81. MFRC_WriteReg(addr, temp | mask); //处理过的数据再写入寄存器
  82. }
  83. /**************************************************************************************
  84. * 函数名称:MFRC_ClrBitMask
  85. * 功能描述:清除寄存器的位
  86. * 入口参数:-addr:待清除的寄存器地址
  87. * -mask:待清除寄存器的位(可同时清除多个bit)
  88. * 出口参数:无
  89. * 返 回 值:无
  90. * 说 明:无
  91. ***************************************************************************************/
  92. void MFRC_ClrBitMask(uint8_t addr, uint8_t mask)
  93. {
  94. uint8_t temp;
  95. temp = MFRC_ReadReg(addr); //先读回寄存器的值
  96. MFRC_WriteReg(addr, temp & ~mask); //处理过的数据再写入寄存器
  97. }
  98. /**************************************************************************************
  99. * 函数名称:MFRC_CalulateCRC
  100. * 功能描述:用MFRC计算CRC结果
  101. * 入口参数:-pInData:带进行CRC计算的数据
  102. * -len:带进行CRC计算的数据长度
  103. * -pOutData:CRC计算结果
  104. * 出口参数:-pOutData:CRC计算结果
  105. * 返 回 值:无
  106. * 说 明:无
  107. ***************************************************************************************/
  108. void MFRC_CalulateCRC(uint8_t *pInData, uint8_t len, uint8_t *pOutData)
  109. {
  110. //0xc1 1 2 pInData[2]
  111. uint8_t temp;
  112. uint32_t i;
  113. MFRC_ClrBitMask(MFRC_DivIrqReg, 0x04); //使能CRC中断
  114. MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE); //取消当前命令的执行
  115. MFRC_SetBitMask(MFRC_FIFOLevelReg, 0x80); //清除FIFO及其标志位
  116. for(i = 0; i < len; i++) //将待CRC计算的数据写入FIFO
  117. {
  118. MFRC_WriteReg(MFRC_FIFODataReg, *(pInData + i));
  119. }
  120. MFRC_WriteReg(MFRC_CommandReg, MFRC_CALCCRC); //执行CRC计算
  121. i = 100000;
  122. do
  123. {
  124. temp = MFRC_ReadReg(MFRC_DivIrqReg); //读取DivIrqReg寄存器的值
  125. i--;
  126. }
  127. while((i != 0) && !(temp & 0x04)); //等待CRC计算完成
  128. pOutData[0] = MFRC_ReadReg(MFRC_CRCResultRegL); //读取CRC计算结果
  129. pOutData[1] = MFRC_ReadReg(MFRC_CRCResultRegM);
  130. }
  131. /**************************************************************************************
  132. * 函数名称:MFRC_CmdFrame
  133. * 功能描述:MFRC522和ISO14443A卡通讯的命令帧函数
  134. * 入口参数:-cmd:MFRC522命令字
  135. * -pIndata:MFRC522发送给MF1卡的数据的缓冲区首地址
  136. * -InLenByte:发送数据的字节长度
  137. * -pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
  138. * -pOutLenBit:MF1卡返回数据的位长度
  139. * 出口参数:-pOutdata:用于接收MF1卡片返回数据的缓冲区首地址
  140. * -pOutLenBit:用于MF1卡返回数据位长度的首地址
  141. * 返 回 值:-status:错误代码(MFRC_OK、MFRC_NOTAGERR、MFRC_ERR)
  142. * 说 明:无
  143. ***************************************************************************************/
  144. char MFRC_CmdFrame(uint8_t cmd, uint8_t *pInData, uint8_t InLenByte, uint8_t *pOutData, uint16_t *pOutLenBit)
  145. {
  146. uint8_t lastBits;
  147. uint8_t n;
  148. uint32_t i;
  149. char status = MFRC_ERR;
  150. uint8_t irqEn = 0x00;
  151. uint8_t waitFor = 0x00;
  152. /*根据命令设置标志位*/
  153. switch(cmd)
  154. {
  155. case MFRC_AUTHENT: //Mifare认证
  156. irqEn = 0x12;
  157. waitFor = 0x10; //idleIRq中断标志
  158. break;
  159. case MFRC_TRANSCEIVE: //发送并接收数据
  160. irqEn = 0x77;
  161. waitFor = 0x30; //RxIRq和idleIRq中断标志
  162. break;
  163. }
  164. /*发送命令帧前准备*/
  165. MFRC_WriteReg(MFRC_ComIEnReg, irqEn | 0x80); //开中断
  166. MFRC_ClrBitMask(MFRC_ComIrqReg, 0x80); //清除中断标志位SET1
  167. MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE); //取消当前命令的执行
  168. MFRC_SetBitMask(MFRC_FIFOLevelReg, 0x80); //清除FIFO缓冲区及其标志位
  169. /*发送命令帧*/
  170. for(i = 0; i < InLenByte; i++) //写入命令参数
  171. {
  172. MFRC_WriteReg(MFRC_FIFODataReg, pInData[i]);
  173. }
  174. MFRC_WriteReg(MFRC_CommandReg, cmd); //执行命令
  175. if(cmd == MFRC_TRANSCEIVE)
  176. {
  177. MFRC_SetBitMask(MFRC_BitFramingReg, 0x80); //启动发送
  178. }
  179. i = 300000; //根据时钟频率调整,操作M1卡最大等待时间25ms
  180. do
  181. {
  182. n = MFRC_ReadReg(MFRC_ComIrqReg);
  183. i--;
  184. }
  185. while((i != 0) && !(n & 0x01) && !(n & waitFor)); //等待命令完成
  186. MFRC_ClrBitMask(MFRC_BitFramingReg, 0x80); //停止发送
  187. /*处理接收的数据*/
  188. if(i != 0)
  189. {
  190. if(!(MFRC_ReadReg(MFRC_ErrorReg) & 0x1B))
  191. {
  192. status = MFRC_OK;
  193. if(n & irqEn & 0x01)
  194. {
  195. status = MFRC_NOTAGERR;
  196. }
  197. if(cmd == MFRC_TRANSCEIVE)
  198. {
  199. n = MFRC_ReadReg(MFRC_FIFOLevelReg);
  200. lastBits = MFRC_ReadReg(MFRC_ControlReg) & 0x07;
  201. if (lastBits)
  202. {
  203. *pOutLenBit = (n - 1) * 8 + lastBits;
  204. }
  205. else
  206. {
  207. *pOutLenBit = n * 8;
  208. }
  209. if(n == 0)
  210. {
  211. n = 1;
  212. }
  213. if(n > MFRC_MAXRLEN)
  214. {
  215. n = MFRC_MAXRLEN;
  216. }
  217. for(i = 0; i < n; i++)
  218. {
  219. pOutData[i] = MFRC_ReadReg(MFRC_FIFODataReg);
  220. }
  221. }
  222. }
  223. else
  224. {
  225. status = MFRC_ERR;
  226. }
  227. }
  228. MFRC_SetBitMask(MFRC_ControlReg, 0x80); //停止定时器运行
  229. MFRC_WriteReg(MFRC_CommandReg, MFRC_IDLE); //取消当前命令的执行
  230. return status;
  231. }
  232. /**************************************************************************************
  233. * 函数名称:PCD_Reset
  234. * 功能描述:PCD复位
  235. * 入口参数:无
  236. * 出口参数:无
  237. * 返 回 值:无
  238. * 说 明:无
  239. ***************************************************************************************/
  240. void PCD_Reset(void)
  241. {
  242. /*硬复位*/
  243. RS522_RST(1);//用到复位引脚
  244. osDelay(2);
  245. RS522_RST(0);
  246. osDelay(2);
  247. RS522_RST(1);
  248. osDelay(2);
  249. /*软复位*/
  250. MFRC_WriteReg(MFRC_CommandReg, MFRC_RESETPHASE);
  251. osDelay(2);
  252. /*复位后的初始化配置*/
  253. MFRC_WriteReg(MFRC_ModeReg, 0x3D); //CRC初始值0x6363
  254. MFRC_WriteReg(MFRC_TReloadRegL, 30); //定时器重装值
  255. MFRC_WriteReg(MFRC_TReloadRegH, 0);
  256. MFRC_WriteReg(MFRC_TModeReg, 0x8D); //定时器设置
  257. MFRC_WriteReg(MFRC_TPrescalerReg, 0x3E); //定时器预分频值
  258. MFRC_WriteReg(MFRC_TxAutoReg, 0x40); //100%ASK
  259. PCD_AntennaOff(); //关天线
  260. osDelay(2);
  261. PCD_AntennaOn(); //开天线
  262. printf("初始化完成\n");
  263. }
  264. /**************************************************************************************
  265. * 函数名称:PCD_AntennaOn
  266. * 功能描述:开启天线,使能PCD发送能量载波信号
  267. * 入口参数:无
  268. * 出口参数:无
  269. * 返 回 值:无
  270. * 说 明:每次开启或关闭天线之间应至少有1ms的间隔
  271. ***************************************************************************************/
  272. void PCD_AntennaOn(void)
  273. {
  274. uint8_t temp;
  275. temp = MFRC_ReadReg(MFRC_TxControlReg);
  276. if (!(temp & 0x03))
  277. {
  278. MFRC_SetBitMask(MFRC_TxControlReg, 0x03);
  279. }
  280. }
  281. /**************************************************************************************
  282. * 函数名称:PCD_AntennaOff
  283. * 功能描述:关闭天线,失能PCD发送能量载波信号
  284. * 入口参数:无
  285. * 出口参数:无
  286. * 返 回 值:无
  287. * 说 明:每次开启或关闭天线之间应至少有1ms的间隔
  288. ***************************************************************************************/
  289. void PCD_AntennaOff(void)
  290. {
  291. MFRC_ClrBitMask(MFRC_TxControlReg, 0x03);
  292. }
  293. /***************************************************************************************
  294. * 函数名称:PCD_Init
  295. * 功能描述:读写器初始化
  296. * 入口参数:无
  297. * 出口参数:无
  298. * 返 回 值:无
  299. * 说 明:无
  300. ***************************************************************************************/
  301. void PCD_Init(void)
  302. {
  303. MFRC_Init(); //MFRC管脚配置
  304. PCD_Reset(); //PCD复位 并初始化配置
  305. PCD_AntennaOff(); //关闭天线
  306. PCD_AntennaOn(); //开启天线
  307. }
  308. /***************************************************************************************
  309. * 函数名称:PCD_Request
  310. * 功能描述:寻卡
  311. * 入口参数: -RequestMode:讯卡方式
  312. * PICC_REQIDL:寻天线区内未进入休眠状态
  313. * PICC_REQALL:寻天线区内全部卡
  314. * -pCardType:用于保存卡片类型
  315. * 出口参数:-pCardType:卡片类型
  316. * 0x4400:Mifare_UltraLight
  317. * 0x0400:Mifare_One(S50)
  318. * 0x0200:Mifare_One(S70)
  319. * 0x0800:Mifare_Pro(X)
  320. * 0x4403:Mifare_DESFire
  321. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  322. * 说 明:无
  323. ***************************************************************************************/
  324. char PCD_Request(uint8_t RequestMode, uint8_t *pCardType)
  325. {
  326. int status;
  327. uint16_t unLen;
  328. uint8_t CmdFrameBuf[MFRC_MAXRLEN];
  329. MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);//关内部温度传感器
  330. MFRC_WriteReg(MFRC_BitFramingReg, 0x07); //存储模式,发送模式,是否启动发送等
  331. MFRC_SetBitMask(MFRC_TxControlReg, 0x03);//配置调制信号13.56MHZ
  332. CmdFrameBuf[0] = RequestMode;
  333. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 1, CmdFrameBuf, &unLen);
  334. if((status == PCD_OK) && (unLen == 0x10))
  335. {
  336. *pCardType = CmdFrameBuf[0];
  337. *(pCardType + 1) = CmdFrameBuf[1];
  338. }
  339. return status;
  340. }
  341. /***************************************************************************************
  342. * 函数名称:PCD_Anticoll
  343. * 功能描述:防冲突,获取卡号
  344. * 入口参数:-pSnr:用于保存卡片序列号,4字节
  345. * 出口参数:-pSnr:卡片序列号,4字节
  346. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  347. * 说 明:无
  348. ***************************************************************************************/
  349. char PCD_Anticoll(uint8_t *pSnr)
  350. {
  351. char status;
  352. uint8_t i, snr_check = 0;
  353. uint16_t unLen;
  354. uint8_t CmdFrameBuf[MFRC_MAXRLEN];
  355. MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);
  356. MFRC_WriteReg(MFRC_BitFramingReg, 0x00);
  357. MFRC_ClrBitMask(MFRC_CollReg, 0x80);
  358. CmdFrameBuf[0] = PICC_ANTICOLL1;
  359. CmdFrameBuf[1] = 0x20;
  360. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 2, CmdFrameBuf, &unLen);
  361. if(status == PCD_OK)
  362. {
  363. for(i = 0; i < 4; i++)
  364. {
  365. *(pSnr + i) = CmdFrameBuf[i];
  366. snr_check ^= CmdFrameBuf[i];
  367. }
  368. if(snr_check != CmdFrameBuf[i])
  369. {
  370. status = PCD_ERR;
  371. }
  372. }
  373. MFRC_SetBitMask(MFRC_CollReg, 0x80);
  374. return status;
  375. }
  376. /***************************************************************************************
  377. * 函数名称:PCD_Select
  378. * 功能描述:选卡
  379. * 入口参数:-pSnr:卡片序列号,4字节
  380. * 出口参数:无
  381. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  382. * 说 明:无
  383. ***************************************************************************************/
  384. char PCD_Select(uint8_t *pSnr)
  385. {
  386. char status;
  387. uint8_t i;
  388. uint16_t unLen;
  389. uint8_t CmdFrameBuf[MFRC_MAXRLEN];
  390. CmdFrameBuf[0] = PICC_ANTICOLL1;
  391. CmdFrameBuf[1] = 0x70;
  392. CmdFrameBuf[6] = 0;
  393. for(i = 0; i < 4; i++)
  394. {
  395. CmdFrameBuf[i + 2] = *(pSnr + i);
  396. CmdFrameBuf[6] ^= *(pSnr + i);
  397. }
  398. MFRC_CalulateCRC(CmdFrameBuf, 7, &CmdFrameBuf[7]);
  399. MFRC_ClrBitMask(MFRC_Status2Reg, 0x08);
  400. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 9, CmdFrameBuf, &unLen);
  401. if((status == PCD_OK) && (unLen == 0x18))
  402. {
  403. status = PCD_OK;
  404. }
  405. else
  406. {
  407. status = PCD_ERR;
  408. }
  409. return status;
  410. }
  411. /***************************************************************************************
  412. * 函数名称:PCD_AuthState
  413. * 功能描述:验证卡片密码
  414. * 入口参数:-AuthMode:验证模式
  415. * PICC_AUTHENT1A:验证A密码
  416. * PICC_AUTHENT1B:验证B密码
  417. * -BlockAddr:块地址(0~63)
  418. * -pKey:密码
  419. * -pSnr:卡片序列号,4字节
  420. * 出口参数:无
  421. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  422. * 说 明:验证密码时,以扇区为单位,BlockAddr参数可以是同一个扇区的任意块
  423. ***************************************************************************************/
  424. char PCD_AuthState(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr)
  425. {
  426. char status;
  427. uint16_t unLen;
  428. uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
  429. CmdFrameBuf[0] = AuthMode;
  430. CmdFrameBuf[1] = BlockAddr;
  431. for(i = 0; i < 6; i++)
  432. {
  433. CmdFrameBuf[i + 2] = *(pKey + i);
  434. }
  435. for(i = 0; i < 4; i++)
  436. {
  437. CmdFrameBuf[i + 8] = *(pSnr + i);
  438. }
  439. status = MFRC_CmdFrame(MFRC_AUTHENT, CmdFrameBuf, 12, CmdFrameBuf, &unLen);
  440. if((status != PCD_OK) || (!(MFRC_ReadReg(MFRC_Status2Reg) & 0x08)))
  441. {
  442. status = PCD_ERR;
  443. }
  444. return status;
  445. }
  446. /***************************************************************************************
  447. * 函数名称:PCD_WriteBlock
  448. * 功能描述:读MF1卡数据块
  449. * 入口参数:-BlockAddr:块地址
  450. * -pData: 用于保存待写入的数据,16字节
  451. * 出口参数:无
  452. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  453. * 说 明:无
  454. ***************************************************************************************/
  455. char PCD_WriteBlock(uint8_t BlockAddr, uint8_t *pData)
  456. {
  457. char status;
  458. uint16_t unLen;
  459. uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
  460. CmdFrameBuf[0] = PICC_WRITE;
  461. CmdFrameBuf[1] = BlockAddr;
  462. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  463. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  464. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  465. {
  466. status = PCD_ERR;
  467. }
  468. if(status == PCD_OK)
  469. {
  470. for(i = 0; i < 16; i++)
  471. {
  472. CmdFrameBuf[i] = *(pData + i);
  473. }
  474. MFRC_CalulateCRC(CmdFrameBuf, 16, &CmdFrameBuf[16]);
  475. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 18, CmdFrameBuf, &unLen);
  476. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  477. {
  478. status = PCD_ERR;
  479. }
  480. }
  481. return status;
  482. }
  483. /***************************************************************************************
  484. * 函数名称:PCD_ReadBlock
  485. * 功能描述:读MF1卡数据块
  486. * 入口参数:-BlockAddr:块地址
  487. * -pData: 用于保存读出的数据,16字节
  488. * 出口参数:-pData: 用于保存读出的数据,16字节
  489. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  490. * 说 明:无
  491. ***************************************************************************************/
  492. char PCD_ReadBlock(uint8_t BlockAddr, uint8_t *pData)
  493. {
  494. char status;
  495. uint16_t unLen;
  496. uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
  497. CmdFrameBuf[0] = PICC_READ;
  498. CmdFrameBuf[1] = BlockAddr;
  499. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  500. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  501. if((status == PCD_OK) && (unLen == 0x90))
  502. {
  503. for(i = 0; i < 16; i++)
  504. {
  505. *(pData + i) = CmdFrameBuf[i];
  506. }
  507. }
  508. else
  509. {
  510. status = PCD_ERR;
  511. }
  512. return status;
  513. }
  514. /***************************************************************************************
  515. * 函数名称:PCD_Value
  516. * 功能描述:对MF1卡数据块增减值操作
  517. * 入口参数:
  518. * -BlockAddr:块地址
  519. * -pValue:四字节增值的值,低位在前
  520. * -mode:数值块操作模式
  521. * PICC_INCREMENT:增值
  522. * PICC_DECREMENT:减值
  523. * 出口参数:无
  524. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  525. * 说 明:无
  526. ***************************************************************************************/
  527. char PCD_Value(uint8_t mode, uint8_t BlockAddr, uint8_t *pValue)
  528. {
  529. //0XC1 1 Increment[4]={0x03, 0x01, 0x01, 0x01};
  530. char status;
  531. uint16_t unLen;
  532. uint8_t i, CmdFrameBuf[MFRC_MAXRLEN];
  533. CmdFrameBuf[0] = mode;
  534. CmdFrameBuf[1] = BlockAddr;
  535. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  536. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  537. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  538. {
  539. status = PCD_ERR;
  540. }
  541. if(status == PCD_OK)
  542. {
  543. for(i = 0; i < 16; i++)
  544. {
  545. CmdFrameBuf[i] = *(pValue + i);
  546. }
  547. MFRC_CalulateCRC(CmdFrameBuf, 4, &CmdFrameBuf[4]);
  548. unLen = 0;
  549. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 6, CmdFrameBuf, &unLen);
  550. if(status != PCD_ERR)
  551. {
  552. status = PCD_OK;
  553. }
  554. }
  555. if(status == PCD_OK)
  556. {
  557. CmdFrameBuf[0] = PICC_TRANSFER;
  558. CmdFrameBuf[1] = BlockAddr;
  559. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  560. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  561. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  562. {
  563. status = PCD_ERR;
  564. }
  565. }
  566. return status;
  567. }
  568. /***************************************************************************************
  569. * 函数名称:PCD_BakValue
  570. * 功能描述:备份钱包(块转存)
  571. * 入口参数:-sourceBlockAddr:源块地址
  572. * -goalBlockAddr :目标块地址
  573. * 出口参数:无
  574. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  575. * 说 明:只能在同一个扇区内转存
  576. ***************************************************************************************/
  577. char PCD_BakValue(uint8_t sourceBlockAddr, uint8_t goalBlockAddr)
  578. {
  579. char status;
  580. uint16_t unLen;
  581. uint8_t CmdFrameBuf[MFRC_MAXRLEN];
  582. CmdFrameBuf[0] = PICC_RESTORE;
  583. CmdFrameBuf[1] = sourceBlockAddr;
  584. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  585. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  586. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  587. {
  588. status = PCD_ERR;
  589. }
  590. if(status == PCD_OK)
  591. {
  592. CmdFrameBuf[0] = 0;
  593. CmdFrameBuf[1] = 0;
  594. CmdFrameBuf[2] = 0;
  595. CmdFrameBuf[3] = 0;
  596. MFRC_CalulateCRC(CmdFrameBuf, 4, &CmdFrameBuf[4]);
  597. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 6, CmdFrameBuf, &unLen);
  598. if(status != PCD_ERR)
  599. {
  600. status = PCD_OK;
  601. }
  602. }
  603. if(status != PCD_OK)
  604. {
  605. return PCD_ERR;
  606. }
  607. CmdFrameBuf[0] = PICC_TRANSFER;
  608. CmdFrameBuf[1] = goalBlockAddr;
  609. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  610. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  611. if((status != PCD_OK) || (unLen != 4) || ((CmdFrameBuf[0] & 0x0F) != 0x0A))
  612. {
  613. status = PCD_ERR;
  614. }
  615. return status;
  616. }
  617. /***************************************************************************************
  618. * 函数名称:PCD_Halt
  619. * 功能描述:命令卡片进入休眠状态
  620. * 入口参数:无
  621. * 出口参数:无
  622. * 返 回 值:-status:错误代码(PCD_OK、PCD_NOTAGERR、PCD_ERR)
  623. * 说 明:无
  624. ***************************************************************************************/
  625. char PCD_Halt(void)
  626. {
  627. char status;
  628. uint16_t unLen;
  629. uint8_t CmdFrameBuf[MFRC_MAXRLEN];
  630. CmdFrameBuf[0] = PICC_HALT;
  631. CmdFrameBuf[1] = 0;
  632. MFRC_CalulateCRC(CmdFrameBuf, 2, &CmdFrameBuf[2]);
  633. status = MFRC_CmdFrame(MFRC_TRANSCEIVE, CmdFrameBuf, 4, CmdFrameBuf, &unLen);
  634. return status;
  635. }
  636. uint8_t readUid[5]; //卡号
  637. uint8_t CT[3]; //卡类型
  638. uint8_t DATA[16]; //存放数据
  639. uint8_t KEY_A[6]= {0xff,0xff,0xff,0xff,0xff,0xff};
  640. uint8_t KEY_B[6]= {0xff,0xff,0xff,0xff,0xff,0xff};
  641. unsigned char buf[16]={0x01,0x02,0x03,0x04,0x05,0x06,0xff
  642. ,0x07,0x80,0x69,0x18,0x17,0x16,0x15,0x14,0x13};
  643. uint8_t status;
  644. uint8_t addr = 0x01*4 + 0x03; // 总共16个扇区。一个扇区4个块,从0开始算,表示第一扇区第三块
  645. void Cardcompare(void)
  646. {
  647. uint8_t i;
  648. //status = PCD_WriteBlock(addr, buf);
  649. status = PCD_Request(0x52, CT); //找到卡返回0
  650. if(!status) //寻卡成功
  651. {
  652. status = PCD_ERR;
  653. status = PCD_Anticoll(readUid); //防冲撞
  654. }
  655. if(!status) //防冲撞成功
  656. {
  657. status = PCD_ERR;
  658. printf("卡的类型为:%x%x%x\r\n",CT[0],CT[1],CT[2]); /* 读取卡的类型 */
  659. printf("卡号:%x-%x-%x-%x\r\n",readUid[0],readUid[1],readUid[2],readUid[3]);
  660. HAL_Delay(1000);
  661. status=PCD_Select(readUid); /* 选卡 */
  662. }
  663. if(!status) //选卡成功
  664. {
  665. status = PCD_ERR;
  666. // 验证A密钥 块地址 密码 SN
  667. status = PCD_AuthState(PICC_AUTHENT1A, addr, KEY_A, readUid);
  668. if(status == PCD_OK)//验证A成功
  669. {
  670. printf("A密钥验证成功\r\n");
  671. HAL_Delay(1000);
  672. }
  673. else
  674. {
  675. printf("A密钥验证失败\r\n");
  676. HAL_Delay(1000);
  677. }
  678. // 验证B密钥 块地址 密码 SN
  679. status = PCD_AuthState(PICC_AUTHENT1B, addr, KEY_B, readUid);
  680. if(status == PCD_OK)//验证B成功
  681. {
  682. printf("B密钥验证成功\r\n");
  683. }
  684. else
  685. {
  686. printf("B密钥验证失败\r\n");
  687. }
  688. HAL_Delay(1000);
  689. }
  690. if(status == PCD_OK)//验证密码成功,接着读取3
  691. {
  692. status = PCD_ERR;
  693. status = PCD_ReadBlock(addr, DATA);
  694. if(status == PCD_OK)//读卡成功
  695. {
  696. printf("1扇区3块DATA:");
  697. for(i = 0; i < 16; i++)
  698. {
  699. printf("%02x", DATA[i]);
  700. }
  701. printf("\r\n");
  702. }
  703. else
  704. {
  705. printf("读卡失败\r\n");
  706. }
  707. HAL_Delay(1000);
  708. }
  709. }
常用函数,搞清楚下面这些函数会用即可,刚开始使用时,过于去抠原理,新手很难坚持下来。先从如何使用,实现每个小功能开始,有点成就感,才能学得更好,走得更远。兴趣才是最好的老师。如何通过这些基础函数来进行其他操作,对卡号进行识别、读写扇区存储信息、修改密码A/B等等,可通过另写一个函数实现,本文利用void Cardcompare(void);该函数进行实现。
char PCD_Request(uint8_t RequestMode, uint8_t *pCardType);  //寻卡,并返回卡的类型
char PCD_Anticoll(uint8_t *pSnr);                           //防冲突,返回卡号
char PCD_Select(uint8_t *pSnr);                             //选卡
char PCD_AuthState(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr); //验证密码(密码A和密码B)   
char PCD_WriteBlock(uint8_t BlockAddr, uint8_t *pData);   //写数据
char PCD_ReadBlock(uint8_t BlockAddr, uint8_t *pData);    //读数据

3、spi.h

  1. #ifndef __SPI_H
  2. #define __SPI_H
  3. #include "stm32f1xx_hal.h"
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif
  7. extern SPI_HandleTypeDef hspi2;
  8. void MX_SPI2_Init(void);
  9. #ifdef __cplusplus
  10. }
  11. #endif
  12. #endif

4、spi.c

  1. #include "./BSP/SPI/spi.h"
  2. #include "main.h"
  3. SPI_HandleTypeDef hspi2;
  4. /* SPI2 init function */
  5. void MX_SPI2_Init(void)
  6. {
  7. hspi2.Instance = SPI2;
  8. hspi2.Init.Mode = SPI_MODE_MASTER;
  9. hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  10. hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  11. hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  12. hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  13. hspi2.Init.NSS = SPI_NSS_SOFT;
  14. hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  15. hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  16. hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  17. hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  18. hspi2.Init.CRCPolynomial = 10;
  19. if (HAL_SPI_Init(&hspi2) != HAL_OK)
  20. {
  21. Error_Handler();
  22. }
  23. }
  24. void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
  25. {
  26. GPIO_InitTypeDef GPIO_InitStruct = {0};
  27. if(spiHandle->Instance==SPI2)
  28. {
  29. /* USER CODE BEGIN SPI2_MspInit 0 */
  30. /* USER CODE END SPI2_MspInit 0 */
  31. /* SPI2 clock enable */
  32. __HAL_RCC_SPI2_CLK_ENABLE();
  33. __HAL_RCC_GPIOB_CLK_ENABLE();
  34. /**SPI2 GPIO Configuration
  35. PB13 ------> SPI2_SCK
  36. PB14 ------> SPI2_MISO
  37. PB15 ------> SPI2_MOSI
  38. */
  39. GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;
  40. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  41. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  42. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  43. GPIO_InitStruct.Pin = GPIO_PIN_14;
  44. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  45. GPIO_InitStruct.Pull = GPIO_NOPULL;
  46. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  47. GPIO_InitTypeDef GPIO_InitStruct = {0};
  48. /*
  49. PB12为片选引脚(CS/NSS/SDA)
  50. PB1为RST引脚
  51. */
  52. /*Configure GPIO pins : PB12 PB4 */
  53. GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_1;
  54. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  55. GPIO_InitStruct.Pull = GPIO_NOPULL;
  56. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  57. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  58. /*Configure GPIO pin Output Level */
  59. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12|GPIO_PIN_1, GPIO_PIN_SET); /* 必须要拉高 */
  60. }
  61. }

5、main.c

  1. #include "./SYSTEM/sys/sys.h"
  2. #include "./SYSTEM/usart/usart.h"
  3. #include "./SYSTEM/delay/delay.h"
  4. #include "./BSP/LED/led.h"
  5. #include "./BSP/KEY/key.h"
  6. #include "./BSP/OLED/OLED.h"
  7. #include "./BSP/SPI/spi.h"
  8. #include "./BSP/RC522/rc522.h"
  9. #include "main.h"
  10. void SystemClock_Config(void);
  11. int main(void)
  12. {
  13. SystemClock_Config(); /* 系统时钟初始化 */
  14. HAL_Init(); /* 初始化HAL库 */
  15. sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
  16. delay_init(72); /* 延时初始化 */
  17. usart_init(115200); /* 初始化串口 */
  18. led_init(); /* led初始化 */
  19. key_init(); /* 按键初始化 */
  20. OLED_Init(); /* oled显示初始化 */
  21. MX_SPI2_Init(); /* spi初始化 */
  22. MFRC_Init(); /* MFRC522初始化 */
  23. PCD_Reset(); /* MFRC522重置 */
  24. while (1)
  25. {
  26. Cardcompare();
  27. }
  28. }
  29. /**
  30. * @brief System Clock Configuration
  31. * @retval None
  32. */
  33. void SystemClock_Config(void)
  34. {
  35. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  36. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  37. /** Initializes the RCC Oscillators according to the specified parameters
  38. * in the RCC_OscInitTypeDef structure.
  39. */
  40. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  41. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  42. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  43. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  44. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  45. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  46. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  47. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  48. {
  49. Error_Handler();
  50. }
  51. /** Initializes the CPU, AHB and APB buses clocks
  52. */
  53. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  54. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  55. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  56. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  57. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  58. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  59. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  60. {
  61. Error_Handler();
  62. }
  63. }
  64. /* USER CODE BEGIN 4 */
  65. /* USER CODE END 4 */
  66. /**
  67. * @brief This function is executed in case of error occurrence.
  68. * @retval None
  69. */
  70. void Error_Handler(void)
  71. {
  72. /* USER CODE BEGIN Error_Handler_Debug */
  73. /* User can add his own implementation to report the HAL error return state */
  74. __disable_irq();
  75. while (1)
  76. {
  77. }
  78. /* USER CODE END Error_Handler_Debug */
  79. }
  80. #ifdef USE_FULL_ASSERT
  81. /**
  82. * @brief Reports the name of the source file and the source line number
  83. * where the assert_param error has occurred.
  84. * @param file: pointer to the source file name
  85. * @param line: assert_param error line source number
  86. * @retval None
  87. */
  88. void assert_failed(uint8_t *file, uint32_t line)
  89. {
  90. /* USER CODE BEGIN 6 */
  91. /* User can add his own implementation to report the file name and line number,
  92. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  93. /* USER CODE END 6 */
  94. }
  95. #endif /* USE_FULL_ASSERT */

至于main.h主要是声明Error_Handler();函数,其他main.c中如系统时钟初始化等函数均是由cumax所自动生成。

有问题的朋友可以在下面留言交流,需要源码的关注并留言自己的邮箱即可获取~
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/433224
推荐阅读
相关标签
  

闽ICP备14008679号