Čítačka RFID kariet RC522: Rozdiel medzi revíziami
Zo stránky SensorWiki
Bez shrnutí editace |
Bez shrnutí editace |
||
(11 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 10: | Riadok 10: | ||
Čítačka RFID kariet RC522 - spojazdniť, vedieť načítať kartu a jej ID, vytvoriť program ktorý rozozná konkrétnu kartu a rozsvieti LED. | Čítačka RFID kariet RC522 - spojazdniť, vedieť načítať kartu a jej ID, vytvoriť program ktorý rozozná konkrétnu kartu a rozsvieti LED. | ||
[[Obrázok: | [[Obrázok:UNO.jpg|400px|thumb|center|Vývojová doska Arduino UNO.]] | ||
'''Literatúra:''' | '''Literatúra:''' | ||
* [ | * [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf Dokumentácia k mikroprocesoru ATmega328P] | ||
* [ | * [https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf Dokumentácia k mikroprocesoru MFRC522] | ||
Riadok 21: | Riadok 21: | ||
== Analýza a opis riešenia == | == Analýza a opis riešenia == | ||
Na komunikáciu s RFID čítačkou som použil SPI rozhranie. Najdôležitejšia vec bola preštudovanie datasheetu, spísanie si všetkých registrov a funkcií a ďalej aj normy pre posielanie informácií karte pomocou čítačky. Pre správnu funkciu zariadenia bolo potrebné vhodne inicializovať RC522, vysielať "budiace" signály a sledovať či sa karta ozve. Po tom ako sa karta ozvala si od nej treba vypýtať jej UID a ďalej už len skontrolovať, či sa zhoduje s nami nahratým UID pre "otvorenie dverí" (zapnutie zelenej LED diódy). | |||
[[ | [[Obrázok:RC522.png|400px|thumb|center|RFID Čítačka RC522]] | ||
Popis zapojenia: | |||
RC522 (slave) je pomocou SPI rozhrania pripojený na Arduino UNO (slave) a ďalej sú k Arduino UNO pripojené 2 LED diódy slúžiace na indikovanie prítomnosti správnej prípadne nesprávnej karty. | |||
*SS -> PB2 (slave select) | |||
*MOSI -> PB3 (master to slave) | |||
*MISO -> PB4 (slave to master) | |||
*SCK -> PB5 (hodinové impulzy) | |||
*RST -> PD7 (voľný pin na reset) | |||
*GND -> GND | |||
*Vcc -> 3,3V | |||
*LED (zelená) -> PD5 | |||
*LED (červená) -> PD6 | |||
[[Súbor: | |||
[[Súbor:SchemaBeko.png|600px|thumb|center|Schéma zapojenia.]] | |||
=== Algoritmus a program === | === Algoritmus a program === | ||
Algoritmus programu využíva | Algoritmus programu využíva knižnicu uart, ktorú sme vytvárali na niektorom z cvičení tento semester. Okrem toho som vytvoril funkcie: | ||
Výpis kódu je nižšie... | |||
*void USART_send_byte_hex(uint8_t byte) (konverzia bajtu na HEX a poslanie cez uart) | |||
: | |||
*void SPI_init() (inicializácia SPI rozhrania) | |||
*uint8_t SPI_transfer(uint8_t data) (prenos dát cez SPI) | |||
: | |||
*void RC522_write(uint8_t reg, uint8_t value) (zapísanie dát do RC522) | |||
*uint8_t RC522_read(uint8_t reg) (prečítanie dát z RC522) | |||
*bool RC522_command(uint8_t command) (zápis konkrétnej úlohy do command registra RC522) | |||
*void RC522_reset() (pre soft reset RC522) | |||
*void RC522_init() (inicializácia RC522) | |||
: | |||
*bool requestTag(uint8_t *tagType) (na pýtanie sa či, a aká karta je v blízkosti čítačky) | |||
*bool detect_card() | |||
*bool antiCollision(uint8_t *uid) | |||
*void wait_for_card_removal() | |||
V programe nie sú priamo použité všetky funkcie, ktoré som vytváral. Výpis kódu je nižšie... | |||
Riadok 41: | Riadok 70: | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#define F_CPU 16000000UL | |||
#define BAUD 9600 | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#include "uart.h" | |||
#define bool uint8_t | |||
#define true 1 | |||
#define false 0 | |||
// SPI piny pre ATmega328P | |||
#define SS_PIN PB2 // slave select | |||
#define MOSI_PIN PB3 // master to slave | |||
#define MISO_PIN PB4 // slave to master | |||
#define SCK_PIN PB5 // hodiny | |||
#define RST_PIN PD7 // voľný pin na RESET | |||
// ----------------------------- | |||
// USART (UART) FUNKCIE | |||
// ----------------------------- | |||
// Konverzia bajtu na HEX a poslanie cez UART | |||
void USART_send_byte_hex(uint8_t byte) | |||
{ | { | ||
const char hexChars[] = "0123456789ABCDEF"; | |||
uart_putc(hexChars[(byte >> 4) & 0x0F]); | |||
uart_putc(hexChars[byte & 0x0F]); | |||
} | |||
// ----------------------------- | |||
// SPI FUNKCIE | |||
// ----------------------------- | |||
void SPI_init() | |||
{ | |||
DDRB |= (1 << SS_PIN) | (1 << MOSI_PIN) | (1 << SCK_PIN); | |||
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); // SPI enable, Master, nastvenie frekvencie Fosc/16 | |||
PORTB |= (1 << SS_PIN); // SS HIGH = neaktívny | |||
} | |||
uint8_t SPI_transfer(uint8_t data) | |||
{ | { | ||
/ | SPDR = data; | ||
while (!(SPSR & (1 << SPIF))); //SPI interrupt flag (čakám kým sa odvysiela) | |||
return SPDR; // vráti obsah SPDR | |||
} | |||
// ----------------------------- | |||
// RC522 NÍZKOÚROVŇOVÉ FUNKCIE | |||
// ----------------------------- | |||
void RC522_write(uint8_t reg, uint8_t value) | |||
{ | |||
PORTB &= ~(1 << SS_PIN); // poviem mu, že chcem komunikovať (nastavím 0) | |||
SPI_transfer((reg << 1) & 0x7E); | |||
// posuniem adresu na správne miesto registra a nastavím prvý aj | |||
// posledný bit na 0, MSB určuje read/write (1/0) a LSB musí byť 0 | |||
SPI_transfer(value); // odoslanie dát | |||
PORTB |= (1 << SS_PIN); // ukončím komunikáciu (zapíšem 1) | |||
_delay_ms(1); // potrebný delay, lebo RFID pracuje pomaly | |||
} | |||
uint8_t RC522_read(uint8_t reg) | |||
{ | |||
PORTB &= ~(1 << SS_PIN); // poviem mu, že chcem komunikovať (nastavím 0) | |||
SPI_transfer(((reg << 1) & 0x7E) | 0x80); // posuniem adresu na správne miesto registra a nastavím prvý aj | |||
// posledný bit na 0, MSB určuje read/write (1/0) a LSB musí byť 0 | |||
// nakoniec pomocou "| 0x80" nastavím MSB na 1 (read) | |||
uint8_t val = SPI_transfer(0x00); // dummy write - prijímam dáta | |||
PORTB |= (1 << SS_PIN); // ukončím komunikáciu | |||
_delay_ms(1); // potrebný delay, lebo RFID pracuje pomaly | |||
return val; | |||
} | |||
bool RC522_command(uint8_t command) | |||
{ | |||
RC522_write(0x01, command); // CommandReg = spustenie príkazu | |||
// Počkáme, kým sa dokončí príkaz (max 25 ms timeout) | |||
uint8_t i = 0; | |||
do | |||
{ | |||
_delay_ms(1); | |||
i++; | |||
if (i > 25) return false; // Timeout | |||
} while (RC522_read(0x04) & 0x01); // ComIrqReg, bit 0 = command stále beží | |||
return true; | |||
} | |||
///// DEFINOVANIE COMMANDOV DO COMMAND_REG ///// | |||
#define RFID_CMD_IDLE 0x00 // nečinný režim | |||
#define RFID_CMD_MEM 0x01 // presun pamäte | |||
#define RFID_CMD_RANDOM_ID 0x02 // vygeneruj náhodné ID | |||
#define RFID_CMD_CALC_CRC 0x03 // spočítaj CRC | |||
#define RFID_CMD_TRANSMIT 0x04 // len vysielaj | |||
#define RFID_CMD_NO_CHANGE 0x07 // nezmeň príkaz | |||
#define RFID_CMD_RECEIVE 0x08 // len prijímaj | |||
#define RFID_CMD_TRANSCEIVE 0x0C // vysielaj aj prijímaj | |||
#define RFID_CMD_AUTHENTICATE 0x0E // autentifikácia | |||
#define RFID_CMD_SOFT_RESET 0x0F // soft reset čipu | |||
void RC522_reset() | |||
{ | |||
RC522_write(0x01, RFID_CMD_SOFT_RESET); // CommandReg = SoftReset | |||
_delay_ms(50); | |||
} | |||
// ----- REGISTRE PODĽA DATASHEETU ----- | |||
#define CommandReg 0x01 | |||
#define CommIEnReg 0x02 | |||
#define CommIrqReg 0x04 | |||
#define ErrorReg 0x06 | |||
#define Status1Reg 0x07 | |||
#define FIFODataReg 0x09 | |||
#define FIFOLevelReg 0x0A | |||
#define ControlReg 0x0C | |||
#define BitFramingReg 0x0D | |||
#define ModeReg 0x11 | |||
#define TxModeReg 0x12 | |||
#define RxModeReg 0x13 | |||
#define TxControlReg 0x14 | |||
#define TxASKReg 0x15 | |||
#define TModeReg 0x2A | |||
#define TPrescalerReg 0x2B | |||
#define TReloadRegL 0x2C | |||
#define TReloadRegH 0x2D | |||
// Inicializácia čipu MFRC522 – nastaví registre potrebné pre komunikáciu a zapne anténu | |||
void RC522_init() | |||
{ | |||
RC522_reset(); | |||
RC522_write(TModeReg, 0x8D); | |||
RC522_write(TPrescalerReg, 0x3E); | |||
RC522_write(TReloadRegL, 30); | |||
RC522_write(TReloadRegH, 0); | |||
RC522_write(TxASKReg, 0x40); | |||
RC522_write(ModeReg, 0x3D); | |||
RC522_write(TxControlReg, 0x83); // zapni anténu | |||
} | |||
// ----------------------------- | |||
// RC522 VYŠŠIE FUNKCIE | |||
// ----------------------------- | |||
bool requestTag(uint8_t *tagType) | |||
{ | |||
RC522_write(CommandReg, RFID_CMD_IDLE); | |||
RC522_write(FIFOLevelReg, 0x80); // Flush FIFO | |||
RC522_write(BitFramingReg, 0x07); // Nastav počet bitov na 7 (7 bits = 1 byte - REQA) | |||
RC522_write(FIFODataReg, 0x26); // REQA príkaz | |||
RC522_write(CommandReg, RFID_CMD_TRANSCEIVE); | |||
RC522_write(BitFramingReg, 0x87); // StartSend = 1, nastav počet bitov na 7 | |||
uint8_t i = 0; | |||
while (!(RC522_read(CommIrqReg) & 0x30)) | |||
{ | |||
_delay_ms(1); | |||
if (++i > 25) return false; | |||
} | |||
if ((RC522_read(ErrorReg) & 0x1B) == 0) | |||
{ | |||
uint8_t dlzka = RC522_read(FIFOLevelReg); | |||
if (dlzka >= 2) | |||
{ | |||
tagType[0] = RC522_read(FIFODataReg); | |||
tagType[1] = RC522_read(FIFODataReg); | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
bool detect_card() | |||
{ | |||
uint8_t tagType[2]; | |||
return requestTag(tagType); | |||
} | |||
bool antiCollision(uint8_t *uid) | |||
{ | |||
RC522_write(CommandReg, RFID_CMD_IDLE); | |||
RC522_write(FIFOLevelReg, 0x80); // Flush FIFO | |||
RC522_write(BitFramingReg, 0x00); // Počet bitov = 0 | |||
RC522_write(FIFODataReg, 0x93); // Anti-collision command | |||
RC522_write(FIFODataReg, 0x20); // NVB = 0x20 (2 bajty) | |||
RC522_write(CommandReg, RFID_CMD_TRANSCEIVE); | |||
RC522_write(BitFramingReg, 0x80); // StartSend = 1 | |||
uint8_t i = 0; | |||
while (!(RC522_read(CommIrqReg) & 0x30)) | |||
{ | |||
_delay_ms(1); | |||
if (++i > 25) return false; | |||
} | |||
if (RC522_read(ErrorReg) & 0x1B) return false; | |||
uint8_t dlzka = RC522_read(FIFOLevelReg); | |||
if (dlzka < 5) return false; | |||
for (uint8_t j = 0; j < 5; j++) | |||
{ | |||
uid[j] = RC522_read(FIFODataReg); | |||
} | |||
return true; | |||
} | |||
void wait_for_card_removal() | |||
{ | |||
while (detect_card()) | |||
{ | |||
_delay_ms(100); | |||
} | |||
} | |||
int main(void) | |||
{ | |||
uart_init(); | |||
SPI_init(); | |||
RC522_init(); | |||
// inicializácia LED: červená na PD6, zelená na PD7 | |||
DDRD |= (1 << PD6) | (1 << PD5); | |||
PORTD &= ~((1 << PD6) | (1 << PD5)); // LEDky vypnuté | |||
int token = 0; | |||
uint8_t keycard[5] = {0x91, 0x27, 0xE1, 0x2B, 0x7C}; | |||
uart_puts("Inicializujem MFRC522...\r\n"); | |||
_delay_ms(3000); // Delay aby to vyzeralo že to niečo robí (stabilizácia) | |||
uint8_t uid[5]; | |||
while (1) | |||
{ | |||
uart_puts("Priloz kartu \r\n"); | |||
while (!detect_card()); | |||
if(detect_card()); // debugovanie: niečo nefunguje ako má ale s týmto už program plní svoju funkciu | |||
if (detect_card()) | |||
{ | |||
if (antiCollision(uid)) | |||
{ | |||
token = 0; | |||
for (uint8_t i = 0; i < 5; i++) | |||
{ | |||
if (uid[i] == keycard[i]) | |||
token++; | |||
} | |||
if (token != 5) | |||
{ | |||
//zapni cervenu LED | |||
PORTD |= (1 << PD6); | |||
uart_puts("Nespravna karta, tu je jej UID: "); // 91 27 E1 2B 7C | |||
for (uint8_t i = 0; i < 5; i++) { | |||
USART_send_byte_hex(uid[i]); | |||
uart_puts(" "); | |||
} | |||
uart_puts("\r\nNa otvorenie dveri treba: UID: "); | |||
for (uint8_t i = 0; i < 5; i++) { | |||
USART_send_byte_hex(keycard[i]); | |||
uart_puts(" "); | |||
} | |||
//pockaj 3sekundy a vypni cervenu led | |||
_delay_ms(3000); | |||
PORTD &= ~(1 << PD6); | |||
} | |||
else | |||
{ | |||
uart_puts("\r\nSpravna karta, vitajte!"); | |||
//zapni zelenu LED na 3sekundy a potom ju vypni | |||
PORTD |= (1 << PD5); | |||
_delay_ms(3000); | |||
PORTD &= ~(1 << PD5); | |||
} | |||
uart_puts("\r\n\n"); | |||
} | |||
else uart_puts("Chyba v anticollision\r\n"); | |||
} | |||
else uart_puts("Ziadna karta\r\n"); | |||
} | |||
return 0; | |||
} | } | ||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
<tab name=" | <tab name="uart.h"><syntaxhighlight lang="c++" style="background: LightYellow;"> | ||
#ifndef UART_H_ | |||
#define UART_H_ | |||
#define BAUD 9600 | |||
#define F_CPU 16000000UL | |||
void uart_init( void ); | |||
void uart_putc( char c ); | |||
void uart_puts( const char *s ); | |||
char uart_getc( void ); | |||
#endif /* UART_H_ */ | |||
</syntaxhighlight ></tab> | |||
<tab name="uart.c"><syntaxhighlight lang="c++" style="background: LightYellow;"> | |||
#include <avr/io.h> | #include <avr/io.h> | ||
//#include <util/setbaud.h> | |||
#define BAUD 9600 | |||
#define F_CPU 16000000UL | |||
void uart_init( void ) | |||
{ | |||
UBRR0 =103; | |||
/* | |||
#if USE_2X | |||
UCSR0A |= _BV(U2X0); | |||
#else | |||
UCSR0A &= ~(_BV(U2X0)); | |||
#endif*/ | |||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */ | |||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */ | |||
} | |||
void uart_putc(char c) | |||
{ | |||
if (c == '\n') | |||
{ | |||
uart_putc('\r'); | |||
} | |||
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */ | |||
UDR0 = c; | |||
} | |||
void uart_puts(const char *s) | |||
{ | |||
/* toto je vasa uloha */ | |||
while(*s!='\0'){ | |||
uart_putc(*s); | |||
s++; | |||
} | |||
} | |||
char uart_getc(void) { | |||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */ | |||
return UDR0; | |||
} | |||
</syntaxhighlight ></tab> | </syntaxhighlight ></tab> | ||
</tabs> | </tabs> | ||
Riadok 65: | Riadok 432: | ||
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'': | Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x ''zdrojaky.zip'': | ||
Zdrojový kód: [[Médiá: | Zdrojový kód: [[Médiá:projektOliverBeko.zip|Beko_Oliver_MFRC522.zip]] | ||
=== Overenie === | === Overenie === | ||
Funkciu zariadenia som overil tak, že som zobral dve karty s rôznymi UID, ktoré som potom prikladal na RFID čítačku a sledoval terminál na monitore a LED diódy signalizujúce priloženie správnej alebo nesprávnej karty. | |||
[[Súbor: | [[Súbor:ZapojenieBeko.jpg|400px|thumb|center|Aplikácia.]] | ||
'''Video:''' | '''Video:''' | ||
<center><youtube> | <center><youtube>dU1uTPvfh3k</youtube></center> | ||
Kľúčové slová 'Category', ktoré sú na konci stránky | Kľúčové slová 'Category', ktoré sú na konci stránky som nemenil. :) | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] |
Aktuálna revízia z 07:55, 5. máj 2025
Záverečný projekt predmetu MIPS / LS2025 - Meno Priezvisko
Zadanie
Toto je čítačka s ktorou pracujem: https://techfun.sk/produkt/citacka-rfid-rc522-klucenka-a-karta/
Čítačka RFID kariet RC522 - spojazdniť, vedieť načítať kartu a jej ID, vytvoriť program ktorý rozozná konkrétnu kartu a rozsvieti LED.

Literatúra:
Analýza a opis riešenia
Na komunikáciu s RFID čítačkou som použil SPI rozhranie. Najdôležitejšia vec bola preštudovanie datasheetu, spísanie si všetkých registrov a funkcií a ďalej aj normy pre posielanie informácií karte pomocou čítačky. Pre správnu funkciu zariadenia bolo potrebné vhodne inicializovať RC522, vysielať "budiace" signály a sledovať či sa karta ozve. Po tom ako sa karta ozvala si od nej treba vypýtať jej UID a ďalej už len skontrolovať, či sa zhoduje s nami nahratým UID pre "otvorenie dverí" (zapnutie zelenej LED diódy).

Popis zapojenia: RC522 (slave) je pomocou SPI rozhrania pripojený na Arduino UNO (slave) a ďalej sú k Arduino UNO pripojené 2 LED diódy slúžiace na indikovanie prítomnosti správnej prípadne nesprávnej karty.
- SS -> PB2 (slave select)
- MOSI -> PB3 (master to slave)
- MISO -> PB4 (slave to master)
- SCK -> PB5 (hodinové impulzy)
- RST -> PD7 (voľný pin na reset)
- GND -> GND
- Vcc -> 3,3V
- LED (zelená) -> PD5
- LED (červená) -> PD6

Algoritmus a program
Algoritmus programu využíva knižnicu uart, ktorú sme vytvárali na niektorom z cvičení tento semester. Okrem toho som vytvoril funkcie:
- void USART_send_byte_hex(uint8_t byte) (konverzia bajtu na HEX a poslanie cez uart)
- void SPI_init() (inicializácia SPI rozhrania)
- uint8_t SPI_transfer(uint8_t data) (prenos dát cez SPI)
- void RC522_write(uint8_t reg, uint8_t value) (zapísanie dát do RC522)
- uint8_t RC522_read(uint8_t reg) (prečítanie dát z RC522)
- bool RC522_command(uint8_t command) (zápis konkrétnej úlohy do command registra RC522)
- void RC522_reset() (pre soft reset RC522)
- void RC522_init() (inicializácia RC522)
- bool requestTag(uint8_t *tagType) (na pýtanie sa či, a aká karta je v blízkosti čítačky)
- bool detect_card()
- bool antiCollision(uint8_t *uid)
- void wait_for_card_removal()
V programe nie sú priamo použité všetky funkcie, ktoré som vytváral. Výpis kódu je nižšie...
#include <avr/io.h>
#define F_CPU 16000000UL
#define BAUD 9600
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
#define bool uint8_t
#define true 1
#define false 0
// SPI piny pre ATmega328P
#define SS_PIN PB2 // slave select
#define MOSI_PIN PB3 // master to slave
#define MISO_PIN PB4 // slave to master
#define SCK_PIN PB5 // hodiny
#define RST_PIN PD7 // voľný pin na RESET
// -----------------------------
// USART (UART) FUNKCIE
// -----------------------------
// Konverzia bajtu na HEX a poslanie cez UART
void USART_send_byte_hex(uint8_t byte)
{
const char hexChars[] = "0123456789ABCDEF";
uart_putc(hexChars[(byte >> 4) & 0x0F]);
uart_putc(hexChars[byte & 0x0F]);
}
// -----------------------------
// SPI FUNKCIE
// -----------------------------
void SPI_init()
{
DDRB |= (1 << SS_PIN) | (1 << MOSI_PIN) | (1 << SCK_PIN);
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); // SPI enable, Master, nastvenie frekvencie Fosc/16
PORTB |= (1 << SS_PIN); // SS HIGH = neaktívny
}
uint8_t SPI_transfer(uint8_t data)
{
SPDR = data;
while (!(SPSR & (1 << SPIF))); //SPI interrupt flag (čakám kým sa odvysiela)
return SPDR; // vráti obsah SPDR
}
// -----------------------------
// RC522 NÍZKOÚROVŇOVÉ FUNKCIE
// -----------------------------
void RC522_write(uint8_t reg, uint8_t value)
{
PORTB &= ~(1 << SS_PIN); // poviem mu, že chcem komunikovať (nastavím 0)
SPI_transfer((reg << 1) & 0x7E);
// posuniem adresu na správne miesto registra a nastavím prvý aj
// posledný bit na 0, MSB určuje read/write (1/0) a LSB musí byť 0
SPI_transfer(value); // odoslanie dát
PORTB |= (1 << SS_PIN); // ukončím komunikáciu (zapíšem 1)
_delay_ms(1); // potrebný delay, lebo RFID pracuje pomaly
}
uint8_t RC522_read(uint8_t reg)
{
PORTB &= ~(1 << SS_PIN); // poviem mu, že chcem komunikovať (nastavím 0)
SPI_transfer(((reg << 1) & 0x7E) | 0x80); // posuniem adresu na správne miesto registra a nastavím prvý aj
// posledný bit na 0, MSB určuje read/write (1/0) a LSB musí byť 0
// nakoniec pomocou "| 0x80" nastavím MSB na 1 (read)
uint8_t val = SPI_transfer(0x00); // dummy write - prijímam dáta
PORTB |= (1 << SS_PIN); // ukončím komunikáciu
_delay_ms(1); // potrebný delay, lebo RFID pracuje pomaly
return val;
}
bool RC522_command(uint8_t command)
{
RC522_write(0x01, command); // CommandReg = spustenie príkazu
// Počkáme, kým sa dokončí príkaz (max 25 ms timeout)
uint8_t i = 0;
do
{
_delay_ms(1);
i++;
if (i > 25) return false; // Timeout
} while (RC522_read(0x04) & 0x01); // ComIrqReg, bit 0 = command stále beží
return true;
}
///// DEFINOVANIE COMMANDOV DO COMMAND_REG /////
#define RFID_CMD_IDLE 0x00 // nečinný režim
#define RFID_CMD_MEM 0x01 // presun pamäte
#define RFID_CMD_RANDOM_ID 0x02 // vygeneruj náhodné ID
#define RFID_CMD_CALC_CRC 0x03 // spočítaj CRC
#define RFID_CMD_TRANSMIT 0x04 // len vysielaj
#define RFID_CMD_NO_CHANGE 0x07 // nezmeň príkaz
#define RFID_CMD_RECEIVE 0x08 // len prijímaj
#define RFID_CMD_TRANSCEIVE 0x0C // vysielaj aj prijímaj
#define RFID_CMD_AUTHENTICATE 0x0E // autentifikácia
#define RFID_CMD_SOFT_RESET 0x0F // soft reset čipu
void RC522_reset()
{
RC522_write(0x01, RFID_CMD_SOFT_RESET); // CommandReg = SoftReset
_delay_ms(50);
}
// ----- REGISTRE PODĽA DATASHEETU -----
#define CommandReg 0x01
#define CommIEnReg 0x02
#define CommIrqReg 0x04
#define ErrorReg 0x06
#define Status1Reg 0x07
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxASKReg 0x15
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegL 0x2C
#define TReloadRegH 0x2D
// Inicializácia čipu MFRC522 – nastaví registre potrebné pre komunikáciu a zapne anténu
void RC522_init()
{
RC522_reset();
RC522_write(TModeReg, 0x8D);
RC522_write(TPrescalerReg, 0x3E);
RC522_write(TReloadRegL, 30);
RC522_write(TReloadRegH, 0);
RC522_write(TxASKReg, 0x40);
RC522_write(ModeReg, 0x3D);
RC522_write(TxControlReg, 0x83); // zapni anténu
}
// -----------------------------
// RC522 VYŠŠIE FUNKCIE
// -----------------------------
bool requestTag(uint8_t *tagType)
{
RC522_write(CommandReg, RFID_CMD_IDLE);
RC522_write(FIFOLevelReg, 0x80); // Flush FIFO
RC522_write(BitFramingReg, 0x07); // Nastav počet bitov na 7 (7 bits = 1 byte - REQA)
RC522_write(FIFODataReg, 0x26); // REQA príkaz
RC522_write(CommandReg, RFID_CMD_TRANSCEIVE);
RC522_write(BitFramingReg, 0x87); // StartSend = 1, nastav počet bitov na 7
uint8_t i = 0;
while (!(RC522_read(CommIrqReg) & 0x30))
{
_delay_ms(1);
if (++i > 25) return false;
}
if ((RC522_read(ErrorReg) & 0x1B) == 0)
{
uint8_t dlzka = RC522_read(FIFOLevelReg);
if (dlzka >= 2)
{
tagType[0] = RC522_read(FIFODataReg);
tagType[1] = RC522_read(FIFODataReg);
return true;
}
}
return false;
}
bool detect_card()
{
uint8_t tagType[2];
return requestTag(tagType);
}
bool antiCollision(uint8_t *uid)
{
RC522_write(CommandReg, RFID_CMD_IDLE);
RC522_write(FIFOLevelReg, 0x80); // Flush FIFO
RC522_write(BitFramingReg, 0x00); // Počet bitov = 0
RC522_write(FIFODataReg, 0x93); // Anti-collision command
RC522_write(FIFODataReg, 0x20); // NVB = 0x20 (2 bajty)
RC522_write(CommandReg, RFID_CMD_TRANSCEIVE);
RC522_write(BitFramingReg, 0x80); // StartSend = 1
uint8_t i = 0;
while (!(RC522_read(CommIrqReg) & 0x30))
{
_delay_ms(1);
if (++i > 25) return false;
}
if (RC522_read(ErrorReg) & 0x1B) return false;
uint8_t dlzka = RC522_read(FIFOLevelReg);
if (dlzka < 5) return false;
for (uint8_t j = 0; j < 5; j++)
{
uid[j] = RC522_read(FIFODataReg);
}
return true;
}
void wait_for_card_removal()
{
while (detect_card())
{
_delay_ms(100);
}
}
int main(void)
{
uart_init();
SPI_init();
RC522_init();
// inicializácia LED: červená na PD6, zelená na PD7
DDRD |= (1 << PD6) | (1 << PD5);
PORTD &= ~((1 << PD6) | (1 << PD5)); // LEDky vypnuté
int token = 0;
uint8_t keycard[5] = {0x91, 0x27, 0xE1, 0x2B, 0x7C};
uart_puts("Inicializujem MFRC522...\r\n");
_delay_ms(3000); // Delay aby to vyzeralo že to niečo robí (stabilizácia)
uint8_t uid[5];
while (1)
{
uart_puts("Priloz kartu \r\n");
while (!detect_card());
if(detect_card()); // debugovanie: niečo nefunguje ako má ale s týmto už program plní svoju funkciu
if (detect_card())
{
if (antiCollision(uid))
{
token = 0;
for (uint8_t i = 0; i < 5; i++)
{
if (uid[i] == keycard[i])
token++;
}
if (token != 5)
{
//zapni cervenu LED
PORTD |= (1 << PD6);
uart_puts("Nespravna karta, tu je jej UID: "); // 91 27 E1 2B 7C
for (uint8_t i = 0; i < 5; i++) {
USART_send_byte_hex(uid[i]);
uart_puts(" ");
}
uart_puts("\r\nNa otvorenie dveri treba: UID: ");
for (uint8_t i = 0; i < 5; i++) {
USART_send_byte_hex(keycard[i]);
uart_puts(" ");
}
//pockaj 3sekundy a vypni cervenu led
_delay_ms(3000);
PORTD &= ~(1 << PD6);
}
else
{
uart_puts("\r\nSpravna karta, vitajte!");
//zapni zelenu LED na 3sekundy a potom ju vypni
PORTD |= (1 << PD5);
_delay_ms(3000);
PORTD &= ~(1 << PD5);
}
uart_puts("\r\n\n");
}
else uart_puts("Chyba v anticollision\r\n");
}
else uart_puts("Ziadna karta\r\n");
}
return 0;
}
#ifndef UART_H_
#define UART_H_
#define BAUD 9600
#define F_CPU 16000000UL
void uart_init( void );
void uart_putc( char c );
void uart_puts( const char *s );
char uart_getc( void );
#endif /* UART_H_ */
#include <avr/io.h>
//#include <util/setbaud.h>
#define BAUD 9600
#define F_CPU 16000000UL
void uart_init( void )
{
UBRR0 =103;
/*
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif*/
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}
void uart_putc(char c)
{
if (c == '\n')
{
uart_putc('\r');
}
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
}
void uart_puts(const char *s)
{
/* toto je vasa uloha */
while(*s!='\0'){
uart_putc(*s);
s++;
}
}
char uart_getc(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
return UDR0;
}
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:
Zdrojový kód: Beko_Oliver_MFRC522.zip
Overenie
Funkciu zariadenia som overil tak, že som zobral dve karty s rôznymi UID, ktoré som potom prikladal na RFID čítačku a sledoval terminál na monitore a LED diódy signalizujúce priloženie správnej alebo nesprávnej karty.

Video:
Kľúčové slová 'Category', ktoré sú na konci stránky som nemenil. :)