Czytnik RFID działa na STM32, problemem może być jedynie obsługa przerwań.
Hardware
Podłączymy do SPI2 (trzeba włączyć obsługę w CubeMX):
STM32 <=> RFID RC522
SPI2_MISO PB14 -> MISO
SPI2_MOSI PB15 -> MOSI
SPI2_SCK PB13 -> SCK
Teraz pin CS – można by do standardowego PB12, ale lepiej na osbony pin (można wtedy podłączyć więcej urządzeń SPI2 na jednej linii):
PA8 -> SDA – ten pin tylko włącza transfer do urządzenia ustawiając stan pinu
Dodatkowo potem do eksperymentów z przerwaniami można zdefiniować osobny pin np.
PA15 -> IRQ (ta linia jest niewykorzystana i nie musi być podłączana)
Uwaga na RST
Trzeba uważać na konfigurację linii RST dla RC522, domyślnie przy output (jest to output STM32 do RC522) ustawiona jest na 1 i się resetuje cały czas, objaw jest taki, że każde polecenie (np. pobranie wersji)
1 2 | uint8_t RC522version = MFRC522_ReadRegister(MFRC522_REG_VERSION); printfx("RC522 Version (92 = version 2, 91 = version 1, ff = rst error): %#08x\r\n", RC522version ); |
zamiast zwrócić 0x91 (stara wersja RC522) lub 0x92 (nowa wersja) zwraca 0xFF, a czytnik nie działa. Jeśli taka jest sytuacja, w funkcji:
1 | static void MX_GPIO_Init(void) |
na końcu dopisujemy
1 | HAL_GPIO_WritePin(GPIOB, RC522_RST_Pin, GPIO_PIN_SET); //domyślnie RESET będzie i dlatego nie działa. |
(zmienna GPIOB i RC522_RST_Pin wskazują na pin podłączony do RST RC522, trzeba ustawić taki,jaki macie w CubeMX)
Soft
Trochę przerobiłem (uprościłem) przykład z innego poradnika i taki nieduży projekt wygląda tak, do terminala używam UART3 (printfx):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2020 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ //obsługa RFID #include "mfrc522.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ SPI_HandleTypeDef hspi2; UART_HandleTypeDef huart3; /* USER CODE BEGIN PV */ uint8_t i; //for uint8_t differentRFID; //czy nowe RFID jest inne? (multiple readings protect) uint8_t txBufInd; uint8_t comand; uint8_t txBuffer[18] = "ID: 00000000 "; //id w postaci char * uint8_t retstr[10]; //powrót z funkcji konwersji hex_dec uint8_t rxBuffer[8]; //ID w postacji stringu do odczytania (heksadecynalny) uint8_t lastID[4]; //poprzednio wczytany ID w postaci binarnej uint8_t str[MFRC522_MAX_LEN]; //aktualnie wczytany id w postaci binarnej (4 bajty, ale miejsca na 16) /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART3_UART_Init(void); static void MX_SPI2_Init(void); static void MX_NVIC_Init(void); /* USER CODE BEGIN PFP */ #include <stdio.h> #include <string.h> volatile char t[100]; char buf_printf[100]; //max printf length #define printfx(f_, ...) snprintf(buf_printf, 100, (f_), ##__VA_ARGS__); \ HAL_UART_Transmit(&huart3, (uint8_t*)buf_printf, strlen(buf_printf), 1000); volatile uint8_t rc522interrupt = 0; // wystąpiło przerwanie RC522 trzeba obsłużyć w loop() //FUNKCJE CZYTNIKA uint8_t MFRC522_Check(uint8_t* id); uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID); void MFRC522_WriteRegister(uint8_t addr, uint8_t val); uint8_t MFRC522_ReadRegister(uint8_t addr); void MFRC522_SetBitMask(uint8_t reg, uint8_t mask); void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask); uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType); uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen); uint8_t MFRC522_Anticoll(uint8_t* serNum); void MFRC522_CalulateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData); uint8_t MFRC522_SelectTag(uint8_t* serNum); uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum); uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData); uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData); void MFRC522_Init(void); void MFRC522_Reset(void); void MFRC522_AntennaOn(void); void MFRC522_AntennaOff(void); void MFRC522_Halt(void); ////////////// void char_to_hex(uint8_t data); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* 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_USART3_UART_Init(); MX_SPI2_Init(); /* Initialize interrupts */ MX_NVIC_Init(); /* USER CODE BEGIN 2 */ //FX: MFRC522_Init(); printfx("FX:Init OK\r\n"); uint8_t RC522version = MFRC522_ReadRegister(MFRC522_REG_VERSION); printfx("RC522 Version (92 = version 2, 91 = version 1): %#08x\n", RC522version ); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (!MFRC522_Request(PICC_REQIDL, str))//str - nasz klucz //PICC_REQIDL find the antenna area does not enter hibernation { if (!MFRC522_Anticoll(str))//str nasz klucz[16] ANTI COLLISION { //TU ODCZYTAł nowy klucz ID differentRFID = 0; //bool czy kolejny wczytany klucz inny jest od poprzedniego? Tylko wtedy działaj (multiple readings) txBufInd = 9; //indeks w stringu od którego piszemy ID: ... for (i=0; i<4 && !differentRFID; i++) if (lastID[i] != str[i]) differentRFID = 1; //sprawdzenie czy wczytany teraz klucz != poprzednio wczytanego if (differentRFID) { //to się wywołuje jeśli kod RFID jest inny nniż do tej pory for (i=0; i<4; i++) lastID[i] = str[i]; //zapamiętaj ostatni nowy ID w str for (i=0; i<4; i++) { char_to_hex(str[i]); //tu zapisuje w systemie 16 klucz do stringu z formatu bitowego na liczby 16 = 4 bajty txBuffer[txBufInd] = retstr[0]; //retstr to return string z funkcji char_to_hex txBufInd++; txBuffer[txBufInd] = retstr[1]; //retstr to return string z funkcji char_to_hex txBufInd++; } printfx("RFID: %s \n\r", (char *)txBuffer); //HAL_UART_Transmit(&huart3, txBuffer, 18, 100); } } } HAL_Delay(10); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief NVIC Configuration. * @retval None */ static void MX_NVIC_Init(void) { /* EXTI15_10_IRQn interrupt configuration */ HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); } /** * @brief SPI2 Initialization Function * @param None * @retval None */ static void MX_SPI2_Init(void) { /* USER CODE BEGIN SPI2_Init 0 */ /* USER CODE END SPI2_Init 0 */ /* USER CODE BEGIN SPI2_Init 1 */ //Tylko od standardowego zmieniona linia hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; z dwóch /* USER CODE END SPI2_Init 1 */ /* SPI2 parameter configuration*/ hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI2_Init 2 */ /* USER CODE END SPI2_Init 2 */ } /** * @brief USART3 Initialization Function * @param None * @retval None */ static void MX_USART3_UART_Init(void) { /* USER CODE BEGIN USART3_Init 0 */ /* USER CODE END USART3_Init 0 */ /* USER CODE BEGIN USART3_Init 1 */ /* USER CODE END USART3_Init 1 */ huart3.Instance = USART3; huart3.Init.BaudRate = 115200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART3_Init 2 */ /* USER CODE END USART3_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GREENLED_GPIO_Port, GREENLED_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : GREENLED_Pin */ GPIO_InitStruct.Pin = GREENLED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GREENLED_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : SPI2_CS_Pin */ GPIO_InitStruct.Pin = SPI2_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SPI2_CS_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : RC522IRQ_Pin */ GPIO_InitStruct.Pin = RC522IRQ_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(RC522IRQ_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ // char number to string hex (FF) (Only big letters!) void char_to_hex(uint8_t data) { uint8_t digits[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; if (data < 16) { retstr[0] = '0'; retstr[1] = digits[data]; } else { retstr[0] = digits[(data & 0xF0)>>4]; retstr[1] = digits[(data & 0x0F)]; } } void irqHandlerRC522(void) {//niepodłączone rc522interrupt = 1; } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ printfx("(main.c) Error_Handler"); /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
Biblioteka rc522.h (pożyczona z sieci), powinna być rozdzielona na plik h i c, ale na skróty w jednym wygląda tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | #define cs_reset() HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_RESET) #define cs_set() HAL_GPIO_WritePin(SPI2_CS_GPIO_Port, SPI2_CS_Pin, GPIO_PIN_SET) // Status enumeration, Used with most functions #define MI_OK 0 #define MI_NOTAGERR 1 #define MI_ERR 2 // MFRC522 Commands #define PCD_IDLE 0x00 // NO action; Cancel the current command #define PCD_AUTHENT 0x0E // Authentication Key #define PCD_RECEIVE 0x08 // Receive Data #define PCD_TRANSMIT 0x04 // Transmit data #define PCD_TRANSCEIVE 0x0C // Transmit and receive data, #define PCD_RESETPHASE 0x0F // Reset #define PCD_CALCCRC 0x03 // CRC Calculate // Mifare_One card command word #define PICC_REQIDL 0x26 // find the antenna area does not enter hibernation #define PICC_REQALL 0x52 // find all the cards antenna area #define PICC_ANTICOLL 0x93 // anti-collision #define PICC_SElECTTAG 0x93 // election card #define PICC_AUTHENT1A 0x60 // authentication key A #define PICC_AUTHENT1B 0x61 // authentication key B #define PICC_READ 0x30 // Read Block #define PICC_WRITE 0xA0 // write block #define PICC_DECREMENT 0xC0 // debit #define PICC_INCREMENT 0xC1 // recharge #define PICC_RESTORE 0xC2 // transfer block data to the buffer #define PICC_TRANSFER 0xB0 // save the data in the buffer #define PICC_HALT 0x50 // Sleep // MFRC522 Registers // Page 0: Command and Status #define MFRC522_REG_RESERVED00 0x00 #define MFRC522_REG_COMMAND 0x01 #define MFRC522_REG_COMM_IE_N 0x02 #define MFRC522_REG_DIV1_EN 0x03 #define MFRC522_REG_COMM_IRQ 0x04 #define MFRC522_REG_DIV_IRQ 0x05 #define MFRC522_REG_ERROR 0x06 #define MFRC522_REG_STATUS1 0x07 #define MFRC522_REG_STATUS2 0x08 #define MFRC522_REG_FIFO_DATA 0x09 //str 44 #define MFRC522_REG_FIFO_LEVEL 0x0A //7 bit - zeruje FIFO, reszta odczyt poziomu fifo #define MFRC522_REG_WATER_LEVEL 0x0B #define MFRC522_REG_CONTROL 0x0C #define MFRC522_REG_BIT_FRAMING 0x0D #define MFRC522_REG_COLL 0x0E #define MFRC522_REG_RESERVED01 0x0F // Page 1: Command #define MFRC522_REG_RESERVED10 0x10 #define MFRC522_REG_MODE 0x11 #define MFRC522_REG_TX_MODE 0x12 #define MFRC522_REG_RX_MODE 0x13 #define MFRC522_REG_TX_CONTROL 0x14 #define MFRC522_REG_TX_AUTO 0x15 #define MFRC522_REG_TX_SELL 0x16 #define MFRC522_REG_RX_SELL 0x17 #define MFRC522_REG_RX_THRESHOLD 0x18 #define MFRC522_REG_DEMOD 0x19 #define MFRC522_REG_RESERVED11 0x1A #define MFRC522_REG_RESERVED12 0x1B #define MFRC522_REG_MIFARE 0x1C #define MFRC522_REG_RESERVED13 0x1D #define MFRC522_REG_RESERVED14 0x1E #define MFRC522_REG_SERIALSPEED 0x1F // Page 2: CFG #define MFRC522_REG_RESERVED20 0x20 #define MFRC522_REG_CRC_RESULT_M 0x21 #define MFRC522_REG_CRC_RESULT_L 0x22 #define MFRC522_REG_RESERVED21 0x23 #define MFRC522_REG_MOD_WIDTH 0x24 #define MFRC522_REG_RESERVED22 0x25 #define MFRC522_REG_RF_CFG 0x26 #define MFRC522_REG_GS_N 0x27 #define MFRC522_REG_CWGS_PREG 0x28 #define MFRC522_REG__MODGS_PREG 0x29 #define MFRC522_REG_T_MODE 0x2A #define MFRC522_REG_T_PRESCALER 0x2B #define MFRC522_REG_T_RELOAD_H 0x2C #define MFRC522_REG_T_RELOAD_L 0x2D #define MFRC522_REG_T_COUNTER_VALUE_H 0x2E #define MFRC522_REG_T_COUNTER_VALUE_L 0x2F // Page 3:TestRegister #define MFRC522_REG_RESERVED30 0x30 #define MFRC522_REG_TEST_SEL1 0x31 #define MFRC522_REG_TEST_SEL2 0x32 #define MFRC522_REG_TEST_PIN_EN 0x33 #define MFRC522_REG_TEST_PIN_VALUE 0x34 #define MFRC522_REG_TEST_BUS 0x35 #define MFRC522_REG_AUTO_TEST 0x36 #define MFRC522_REG_VERSION 0x37 #define MFRC522_REG_ANALOG_TEST 0x38 #define MFRC522_REG_TEST_ADC1 0x39 #define MFRC522_REG_TEST_ADC2 0x3A #define MFRC522_REG_TEST_ADC0 0x3B #define MFRC522_REG_RESERVED31 0x3C #define MFRC522_REG_RESERVED32 0x3D #define MFRC522_REG_RESERVED33 0x3E #define MFRC522_REG_RESERVED34 0x3F #define MFRC522_DUMMY 0x00 // Dummy byte #define MFRC522_MAX_LEN 16 // Buf len byte #include "stm32f1xx_hal.h" //hal zamiast it //#include "mfrc522.h" extern SPI_HandleTypeDef hspi2; // RC522 extern uint8_t MFRC522_Check(uint8_t* id); extern uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID); extern void MFRC522_WriteRegister(uint8_t addr, uint8_t val); extern uint8_t MFRC522_ReadRegister(uint8_t addr); extern void MFRC522_SetBitMask(uint8_t reg, uint8_t mask); extern void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask); extern uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType); extern uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen); extern uint8_t MFRC522_Anticoll(uint8_t* serNum); extern void MFRC522_CalulateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData); extern uint8_t MFRC522_SelectTag(uint8_t* serNum); extern uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum); extern uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData); extern uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData); extern void MFRC522_Init(void); extern void MFRC522_Reset(void); extern void MFRC522_AntennaOn(void); extern void MFRC522_AntennaOff(void); extern void MFRC522_Halt(void); //////////////////////////////////////////////////////////////////////////////////////////// ///// mfrc522.c /////////////////////////////////////////////////////////////////////////////////////////// uint8_t SPI1SendByte(uint8_t data) { unsigned char writeCommand[1]; unsigned char readValue[1]; writeCommand[0] = data; HAL_SPI_TransmitReceive(&hspi2, (uint8_t*)&writeCommand, (uint8_t*)&readValue, 1, 10); return readValue[0]; } void SPI1_WriteReg(uint8_t address, uint8_t value) { cs_reset(); SPI1SendByte(address); SPI1SendByte(value); cs_set(); } uint8_t SPI1_ReadReg(uint8_t address) { uint8_t val; cs_reset(); SPI1SendByte(address); val = SPI1SendByte(0x00); cs_set(); return val; } void MFRC522_WriteRegister(uint8_t addr, uint8_t val) { addr = (addr << 1) & 0x7E; // Address format: 0XXXXXX0 SPI1_WriteReg(addr, val); } uint8_t MFRC522_ReadRegister(uint8_t addr) { uint8_t val; addr = ((addr << 1) & 0x7E) | 0x80; val = SPI1_ReadReg(addr); return val; } uint8_t MFRC522_Check(uint8_t* id) { uint8_t status; status = MFRC522_Request(PICC_REQIDL, id); // Find cards, return card type if (status == MI_OK) status = MFRC522_Anticoll(id); // Card detected. Anti-collision, return card serial number 4 bytes MFRC522_Halt(); // Command card into hibernation return status; } uint8_t MFRC522_Compare(uint8_t* CardID, uint8_t* CompareID) { uint8_t i; for (i = 0; i < 5; i++) { if (CardID[i] != CompareID[i]) return MI_ERR; } return MI_OK; } void MFRC522_SetBitMask(uint8_t reg, uint8_t mask) { MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) | mask); } void MFRC522_ClearBitMask(uint8_t reg, uint8_t mask){ MFRC522_WriteRegister(reg, MFRC522_ReadRegister(reg) & (~mask)); } uint8_t MFRC522_Request(uint8_t reqMode, uint8_t* TagType) { uint8_t status; uint16_t backBits; // The received data bits MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x07); // TxLastBists = BitFramingReg[2..0] TagType[0] = reqMode; status = MFRC522_ToCard(PCD_TRANSCEIVE, TagType, 1, TagType, &backBits); //PCD_TRANSCEIVE - wyślij i odbierz if ((status != MI_OK) || (backBits != 0x10)) status = MI_ERR; return status; } uint8_t MFRC522_ToCard(uint8_t command, uint8_t* sendData, uint8_t sendLen, uint8_t* backData, uint16_t* backLen) { uint8_t status = MI_ERR; uint8_t irqEn = 0x00; uint8_t waitIRq = 0x00; uint8_t lastBits; uint8_t n; uint16_t i; switch (command) { case PCD_AUTHENT: { irqEn = 0x12; waitIRq = 0x10; break; } case PCD_TRANSCEIVE: { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } MFRC522_WriteRegister(MFRC522_REG_COMM_IE_N, irqEn | 0x80); MFRC522_ClearBitMask(MFRC522_REG_COMM_IRQ, 0x80); MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_IDLE); // Writing data to the FIFO for (i = 0; i < sendLen; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, sendData[i]); // Execute the command MFRC522_WriteRegister(MFRC522_REG_COMMAND, command); if (command == PCD_TRANSCEIVE) MFRC522_SetBitMask(MFRC522_REG_BIT_FRAMING, 0x80); i = 2000; // do { n = MFRC522_ReadRegister(MFRC522_REG_COMM_IRQ); i--; } while ((i!=0) && !(n&0x01) && !(n&waitIRq)); MFRC522_ClearBitMask(MFRC522_REG_BIT_FRAMING, 0x80); // StartSend=0 if (i != 0) { if (!(MFRC522_ReadRegister(MFRC522_REG_ERROR) & 0x1B)) { status = MI_OK; if (n & irqEn & 0x01) status = MI_NOTAGERR; if (command == PCD_TRANSCEIVE) { n = MFRC522_ReadRegister(MFRC522_REG_FIFO_LEVEL); lastBits = MFRC522_ReadRegister(MFRC522_REG_CONTROL) & 0x07; if (lastBits) *backLen = (n-1)*8+lastBits; else *backLen = n*8; if (n == 0) n = 1; if (n > MFRC522_MAX_LEN) n = MFRC522_MAX_LEN; for (i = 0; i < n; i++) backData[i] = MFRC522_ReadRegister(MFRC522_REG_FIFO_DATA); // Reading the received data in FIFO } } else status = MI_ERR; } return status; } uint8_t MFRC522_Anticoll(uint8_t* serNum) { uint8_t status; uint8_t i; uint8_t serNumCheck = 0; uint16_t unLen; MFRC522_WriteRegister(MFRC522_REG_BIT_FRAMING, 0x00); // TxLastBists = BitFramingReg[2..0] serNum[0] = PICC_ANTICOLL; serNum[1] = 0x20; status = MFRC522_ToCard(PCD_TRANSCEIVE, serNum, 2, serNum, &unLen); if (status == MI_OK) { // Check card serial number for (i = 0; i < 4; i++) serNumCheck ^= serNum[i]; if (serNumCheck != serNum[i]) status = MI_ERR; } return status; } void MFRC522_CalculateCRC(uint8_t* pIndata, uint8_t len, uint8_t* pOutData) { uint8_t i, n; MFRC522_ClearBitMask(MFRC522_REG_DIV_IRQ, 0x04); // CRCIrq = 0 MFRC522_SetBitMask(MFRC522_REG_FIFO_LEVEL, 0x80); // Clear the FIFO pointer // Write_MFRC522(CommandReg, PCD_IDLE); // Writing data to the FIFO for (i = 0; i < len; i++) MFRC522_WriteRegister(MFRC522_REG_FIFO_DATA, *(pIndata+i)); MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_CALCCRC); // Wait CRC calculation is complete i = 0xFF; do { n = MFRC522_ReadRegister(MFRC522_REG_DIV_IRQ); i--; } while ((i!=0) && !(n&0x04)); // CRCIrq = 1 // Read CRC calculation result pOutData[0] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_L); pOutData[1] = MFRC522_ReadRegister(MFRC522_REG_CRC_RESULT_M); } uint8_t MFRC522_SelectTag(uint8_t* serNum) { uint8_t i; uint8_t status; uint8_t size; uint16_t recvBits; uint8_t buffer[9]; buffer[0] = PICC_SElECTTAG; buffer[1] = 0x70; for (i = 0; i < 5; i++) buffer[i+2] = *(serNum+i); MFRC522_CalculateCRC(buffer, 7, &buffer[7]); //?? status = MFRC522_ToCard(PCD_TRANSCEIVE, buffer, 9, buffer, &recvBits); if ((status == MI_OK) && (recvBits == 0x18)) size = buffer[0]; else size = 0; return size; } uint8_t MFRC522_Auth(uint8_t authMode, uint8_t BlockAddr, uint8_t* Sectorkey, uint8_t* serNum) { uint8_t status; uint16_t recvBits; uint8_t i; uint8_t buff[12]; // Verify the command block address + sector + password + card serial number buff[0] = authMode; buff[1] = BlockAddr; for (i = 0; i < 6; i++) buff[i+2] = *(Sectorkey+i); for (i=0; i<4; i++) buff[i+8] = *(serNum+i); status = MFRC522_ToCard(PCD_AUTHENT, buff, 12, buff, &recvBits); if ((status != MI_OK) || (!(MFRC522_ReadRegister(MFRC522_REG_STATUS2) & 0x08))) status = MI_ERR; return status; } uint8_t MFRC522_Read(uint8_t blockAddr, uint8_t* recvData) { uint8_t status; uint16_t unLen; recvData[0] = PICC_READ; recvData[1] = blockAddr; MFRC522_CalculateCRC(recvData,2, &recvData[2]); status = MFRC522_ToCard(PCD_TRANSCEIVE, recvData, 4, recvData, &unLen); if ((status != MI_OK) || (unLen != 0x90)) status = MI_ERR; return status; } uint8_t MFRC522_Write(uint8_t blockAddr, uint8_t* writeData) { uint8_t status; uint16_t recvBits; uint8_t i; uint8_t buff[18]; buff[0] = PICC_WRITE; buff[1] = blockAddr; MFRC522_CalculateCRC(buff, 2, &buff[2]); status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR; if (status == MI_OK) { // Data to the FIFO write 16Byte for (i = 0; i < 16; i++) buff[i] = *(writeData+i); MFRC522_CalculateCRC(buff, 16, &buff[16]); status = MFRC522_ToCard(PCD_TRANSCEIVE, buff, 18, buff, &recvBits); if ((status != MI_OK) || (recvBits != 4) || ((buff[0] & 0x0F) != 0x0A)) status = MI_ERR; } return status; } void MFRC522_Init(void) { MFRC522_Reset(); MFRC522_WriteRegister(MFRC522_REG_T_MODE, 0x8D); MFRC522_WriteRegister(MFRC522_REG_T_PRESCALER, 0x3E); MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_L, 30); MFRC522_WriteRegister(MFRC522_REG_T_RELOAD_H, 0); MFRC522_WriteRegister(MFRC522_REG_RF_CFG, 0x70); // 48dB gain MFRC522_WriteRegister(MFRC522_REG_TX_AUTO, 0x40); MFRC522_WriteRegister(MFRC522_REG_MODE, 0x3D); MFRC522_AntennaOn(); // Open the antenna } void MFRC522_Reset(void) { MFRC522_WriteRegister(MFRC522_REG_COMMAND, PCD_RESETPHASE); } void MFRC522_AntennaOn(void) { uint8_t temp; temp = MFRC522_ReadRegister(MFRC522_REG_TX_CONTROL); if (!(temp & 0x03)) MFRC522_SetBitMask(MFRC522_REG_TX_CONTROL, 0x03); } void MFRC522_AntennaOff(void) { MFRC522_ClearBitMask(MFRC522_REG_TX_CONTROL, 0x03); } void MFRC522_Halt(void) { uint16_t unLen; uint8_t buff[4]; buff[0] = PICC_HALT; buff[1] = 0; MFRC522_CalculateCRC(buff, 2, &buff[2]); MFRC522_ToCard(PCD_TRANSCEIVE, buff, 4, buff, &unLen); } |