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);
}