Operácie

Čítačka RFID kariet RC522: Rozdiel medzi revíziami

Zo stránky SensorWiki

StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
 
(10 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 13: Riadok 13:


'''Literatúra:'''  
'''Literatúra:'''  
* [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob]
* [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf Dokumentácia k mikroprocesoru ATmega328P]
* [http://www.humanbenchmark.com/tests/reactiontime/index.php Vyskúšajte si zmerať reakciu on-line]
* [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 ==


Opíšte sem čo a ako ste spravili, ak treba, doplňte obrázkami...
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).
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.  


[[Súbor:GeminiAI-image3.jpg|400px|thumb|center|Celkový pohľad na zariadenie.]]
[[Obrázok:RC522.png|400px|thumb|center|RFID Čítačka RC522]]


Nezabudnite doplniť schému zapojenia! V texte by ste mali opísať základné veci zo zapojenia, samotná schéma nie je dostačujúci opis.
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:GeminiAI-image2.jpg|400px|thumb|center|Schéma zapojenia.]]
 
 
[[Súbor:SchemaBeko.png|600px|thumb|center|Schéma zapojenia.]]




=== Algoritmus a program ===
=== Algoritmus a program ===


Algoritmus programu využíva toto a toto, základné funkcie sú takéto a voláma ich tuto...
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>


int main(void)
 
#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)  
{
{
  unsigned int measuredValue;
    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
}


  while (1)
uint8_t SPI_transfer(uint8_t data)
   {
{
     /* relax */   
    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);
    return 0;
}
}


</syntaxhighlight ></tab>
</syntaxhighlight ></tab>
<tab name="filename.h"><syntaxhighlight  lang="c++" style="background: LightYellow;">
<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 adc_init(void);                                  // A/D converter initialization


unsigned int adc_read(char a_pin);
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á:projektMenoPriezvisko.zip|zdrojaky.zip]]
Zdrojový kód: [[Médiá:projektOliverBeko.zip|Beko_Oliver_MFRC522.zip]]


=== Overenie ===
=== Overenie ===


Ako ste overili funkciu, napríklad... Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia.
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.
Na konci uvádzame fotku hotového zariadenia.  


[[Súbor:GeminiAI-image1.jpg|400px|thumb|center|Aplikácia.]]
[[Súbor:ZapojenieBeko.jpg|400px|thumb|center|Aplikácia.]]


'''Video:'''
'''Video:'''
<center><youtube>D0UnqGm_miA</youtube></center>
<center><youtube>dU1uTPvfh3k</youtube></center>








Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.  
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.

Vývojová doska Arduino UNO.

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).

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


Schéma zapojenia.


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.

Aplikácia.

Video:



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