STM32F407使用MFRC522射頻卡調試及程序移植成功


 

 版權聲明:轉載請注明出處,謝謝 https://blog.csdn.net/Kevin_8_Lee/article/details/88865556

 或               https://www.cnblogs.com/kevin-nancy/p/10621205.html

 這兩個平台都是我的個人博客

 

 

基於STM32的MFRC522射頻卡模塊使用

 

本學期感測技術選修課需要做一個作品出來,用到了MFRC522射頻卡模塊,經歷一個星期的調試,終於可以正常使用並尋卡成功了了。  成功的把C51的程序移植到了STM32上面。  現在分享一下調試過程

 

1、操作環境

我所使用的是STM32F407的開發板,使用STM32CubeMX配置初始代碼。    MFRC522使用軟件模擬SPI通信

 

 

2、 關於引腳的配置

 

淘寶買來的模塊,店家都會送資料 ,也可以點下面連接保存至網盤

鏈接 :    https://pan.baidu.com/s/1JlNNIjtvHuRbVMSRZocHLA

提取碼:z119 

 

1、SPI通信引腳

 

1         NSS(SDA)       --------->> 片選信號
2         SCK            --------->> 時鍾信號
3         MOSI           --------->> 信號輸出端(即單片機引腳設置為輸入,MFRC522該引腳輸出)
4         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!!!\r\n"); 31   
32   // 下面進行的是初始化
33  PcdReset(); 34   PcdAntennaOff(); //關閉天線
35   PcdAntennaOn();  //開啟天線
36   M500PcdConfigISOType('A');  // 選擇工作方式
37     
38   printf("開始尋卡... ...\r\n"); 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("\r\n卡的類型:"); 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 }

 

其他的底層驅動函數就不需要改了,由於總的代碼量比較長,我就只貼出關鍵的,其他不需要改的直接參考資料里面的例程即可
我自己移植過來完整的有很多程序的注注釋,有興趣的可以下載一下,不過自己花時間看看數據手冊打個注釋是最好的

 

點擊這里下載完整移植驅動程序

 

任何你的不足,在你成功地那一刻,都會被別人說成特色!!     加油吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM