Operácie

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

Zo stránky SensorWiki

Balogh (diskusia | príspevky)
Vytvorená stránka „Záverečný projekt predmetu MIPS / LS2025 - '''Meno Priezvisko''' == Zadanie == Toto je ta citacka: https://techfun.sk/produkt/citacka-rfid-rc522-klucenka-a-karta/ Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie 400px|thumb|center|Vývojová doska ACROB. '''Literatúra:''' * [http://ap.urpi.fei.stuba.sk/sensorwiki/index.php/Acrob_technical_description Dokumentácia k doske Acrob] * [http://www.hu…“
 
StudentMIPS (diskusia | príspevky)
Bez shrnutí editace
 
(17 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 4: Riadok 4:
== Zadanie ==
== Zadanie ==


Toto je ta citacka:  
Toto je čítačka s ktorou pracujem:  
https://techfun.sk/produkt/citacka-rfid-rc522-klucenka-a-karta/
https://techfun.sk/produkt/citacka-rfid-rc522-klucenka-a-karta/




Sem príde text zadania, ak bolo len voľne formulované, rozpíšte ho podrobnejšie
Čí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:ard.jpg|400px|thumb|center|Vývojová doska ACROB.]]
[[Obrázok:UNO.jpg|400px|thumb|center|Vývojová doska Arduino UNO.]]


'''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...
Modul MFRC522 je bezkontaktná RFID čítačka pracujúca na frekvencii 13,56 MHz, je určená na komunikáciu s RFID tagmi štandardu ISO/IEC 14443A. Obsahuje integrovaný vysielač a prijímač, ktorý zabezpečuje komunikáciu s kartami. Ovládanie čítačky prebieha prostredníctvom sústavy riadiacich registrov, ktoré riadia jej činnosť a spracovanie dát.
Podrobne opíšte použité komponenty (okrem základnej dosky s ATmega328P procesorom), pridajte linky na datasheety alebo opis obvodu.  
Napríklad:
*CommandReg (0x01) určuje, aký príkaz má čítačka aktuálne vykonať (napr. soft reset, čítanie, vysielanie...)
*FIFODataReg (0x09) slúži na zápis a čítanie dát, ktoré sa posielajú medzi čítačkou a kartou
*TxControlReg (0x14) umožňuje zapnúť alebo vypnúť anténu čítačky
*BitFramingReg (0x0D) nastavuje počet bitov v poslednom odosielanom bajte a riadi spustenie prenosu
*ErrorReg (0x06) obsahuje príznaky chýb počas komunikácie – napr. chyba parity, kolízia, chyba časovača alebo buffer overflow


[[Súbor:GeminiAI-image3.jpg|400px|thumb|center|Celkový pohľad na zariadenie.]]
Každá operácia, ako napríklad detekcia karty, získanie UID alebo výber konkrétneho tagu, si vyžaduje presnú sekvenciu zápisov do registrov, často vrátane nastavenia prenosových parametrov a čakacích podmienok. 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).


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.
[[Obrázok:RC522.png|400px|thumb|center|RFID Čítačka RC522]]


[[Súbor:GeminiAI-image2.jpg|400px|thumb|center|Schéma zapojenia.]]
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: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 78:
#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)
{
    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)  
{
{
  unsigned int measuredValue;
    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);
    }


  while (1)
    return true;
  {
}
     /* relax */
 
  }
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 440:
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 20:50, 12. 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

Modul MFRC522 je bezkontaktná RFID čítačka pracujúca na frekvencii 13,56 MHz, je určená na komunikáciu s RFID tagmi štandardu ISO/IEC 14443A. Obsahuje integrovaný vysielač a prijímač, ktorý zabezpečuje komunikáciu s kartami. Ovládanie čítačky prebieha prostredníctvom sústavy riadiacich registrov, ktoré riadia jej činnosť a spracovanie dát. Napríklad:

  • CommandReg (0x01) určuje, aký príkaz má čítačka aktuálne vykonať (napr. soft reset, čítanie, vysielanie...)
  • FIFODataReg (0x09) slúži na zápis a čítanie dát, ktoré sa posielajú medzi čítačkou a kartou
  • TxControlReg (0x14) umožňuje zapnúť alebo vypnúť anténu čítačky
  • BitFramingReg (0x0D) nastavuje počet bitov v poslednom odosielanom bajte a riadi spustenie prenosu
  • ErrorReg (0x06) obsahuje príznaky chýb počas komunikácie – napr. chyba parity, kolízia, chyba časovača alebo buffer overflow

Každá operácia, ako napríklad detekcia karty, získanie UID alebo výber konkrétneho tagu, si vyžaduje presnú sekvenciu zápisov do registrov, často vrátane nastavenia prenosových parametrov a čakacích podmienok. 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. :)