Programlama Kodları
//AÇIKLAMA
//Bu uygulamada "MEHMET-GOKDAG-78" yazısı kartın 2. bloğuna yazılır ve ardından okunarak seri port ekranına yazdırılır. Ardından
//Kartın/Etiketin Bellek Dökümünü/Haritası ekrana seri port ekranına yazdırılır.
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key; //'key' adında bir MIFARE_Key yapısı değişkeni oluşturuldu. Bu değişkeni, güvenlik anahtarını programa bildirmek için kullanacağız. 6 bayttır.
int blok = 2; //Bu, içine yazıp sonra okuyacağımız blok numarasıdır.0. sektör 2. blok anlamındadır.
byte gonderilen_veri[16] = {"MEHMET-GOKDAG-78"}; //Bloğa yazdıracağımız verilerimizi belirlemek için, 16 baytlık bir dizi tanımlayıp, içerisine yazı yazıyoruz. Eğer bir bloğun içini silmek istiyorsak; {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; dizisinin o bloğa yazdırılması yeterlidir.
byte okunan_veri[18]; //Bloktaki verileri okuduktan sonra kaydedeceğimiz diziyi tanımlıyoruz. Okuyacağımız veri 16 bayt olmasına rağmen diziyi 18 elemanlı tanımladık. Bunun nedeni, MFRC522 kütüphanesindeki MIFARE_Read fonksiyonunun en az 18 baytlık bir tampon gerektirmesidir.
void setup()
{
Serial.begin(9600);
SPI.begin();
rfid.PCD_Init();
Serial.println("MIFARE Classic Kart/Etiket Bekleniyor...");
//_______________________Güvenlik Anahtarını Kütüphaneye Bildirme____________________
//Yukarıda tanımladığımız 'key' adındaki 6 baytlık değişkeni kullanarak, güvenlik anahtarını kütüphaneye bildiririz.
//Güvenlik anahtarı aşağıdaki for döngüsünde görüldüğü üzere her biri 1 baytlık olan 6 adet "0xFF" verisinden oluşur.
//Yeni RFID kartlarının tümünün güvenlik anahtarı varsayılan olarak 0xFF olarak belirlenir.
for (byte i = 0; i < 6; i++)
{
key.keyByte[i] = 0xFF;
}
}
void loop()
{
//If'in içerisinde return kullanmamızın nedeni: If içi 1(true) olduğunda programın, loop
//döngüsünün başına gitmesini sağlamak içindir.
if (!rfid.PICC_IsNewCardPresent())
{
return;
}
if (!rfid.PICC_ReadCardSerial())
{
return;
}
Serial.println("Kart/Etiket Algılandı.");
veriyaz(blok, gonderilen_veri); //"gonderilen_veri" dizisinde tanımlanan veri 2 numaralı bloğa yazılır.
verioku(blok, okunan_veri); //2 numaralı bloktaki veri okunarak "okunan_veri" dizisine kaydedilir.
//Bloktan okunan veri seri port ekranına yazdırılır.
Serial.print("Bloktan Okunan Veri: ");
for (int j = 0; j < 16; j++) {
Serial.write(okunan_veri[j]);
}
Serial.println("");
//Kart/etiket hakkında tüm bilgileri seri port ekranına yazdırır.
Serial.println(" ");
Serial.print("_________________"); Serial.print("Kartın/Etiketin Bellek Dökümünü/Haritası"); Serial.println("__________________");
rfid.PICC_DumpToSerial(&(rfid.uid));
rfid.PCD_StopCrypto1(); //okuyucu (PCD) ile kart/etiket(PICC) arasındaki şifreli iletişimi (Crypto1) güvenli bir şekilde kapat.
}
//_______________________Bloğa Veri Yazma Fonksiyonu____________________
int veriyaz(int blok_no, byte gon_veri_dizisi[])
{
//Bu kısımda trailer(son) blok değeri belirlenir ve blok kontrolü yapılır. Verilen blok numarasının veri bloğuna mı yoksa sonlandırıcı bloğa mı karşılık geldiği kontrol edilir. Verilen blok numarası bir veri bloğuna karşılık gelmiyorsa, fonksiyon bir hata mesajı döndürür.
int sayi_tam_kisim = blok_no / 4 * 4; //blok_no önce 4'e bölünür sonra 4 ile çarpılır. Fakat değişkenler int türünden tanımlandığı için blok_no 4'e bölündüğünde sonuç virgüllü çıksa bile sadece tam kısmı alınır. Örn: 7/4=1,25 olarak değil sadece tam kısmı alınacağından bölüm sonucu 1 olur.
int trailer_blok = sayi_tam_kisim + 3; //Sektör için trailer(son) blok değerini belirleyin.
if (blok_no > 2 && (blok_no + 1) % 4 == 0)
{
Serial.print(blok_no);
Serial.println(" numaralı blok trailer bloğudur.");
return 2;
}
Serial.print(blok_no);
Serial.println(" numaralı blok veri bloğudur.");
//Bu kısımda bloğa erişim için key doğrulaması yapılır. Doğrulama başarısız olursa, fonksiyon bir hata mesajı döndürür.
byte status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailer_blok, &key, &(rfid.uid));
if (status != MFRC522::STATUS_OK)
{
Serial.print("Key doğrulama hatası: ");
Serial.println(rfid.GetStatusCodeName(status));
return 3; //return "3" as error message
}
//Bu kısımda belirlenen veri olan "MEHMET-GOKDAG-78" yazısı bloğa yazılır.
status = rfid.MIFARE_Write(blok_no, gon_veri_dizisi, 16);
if (status != MFRC522::STATUS_OK)
{
Serial.print("MIFARE_Write() Yazma Hatası: ");
Serial.println(rfid.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("Bloğa yazma işlemi yapıldı.");
}
//_______________________Bloktan Veri Okuma Fonksiyonu____________________
int verioku(int blok_no, byte okunan_veri_dizisi[])
{
//Bu kısımda trailer(son) blok değeri belirlenir
int sayi_tam_kisim = blok_no / 4 * 4;
int trailer_blok = sayi_tam_kisim + 3; //Sektör için trailer(son) blok değerini belirleyin.
//Bu kısımda bloğa erişim için key doğrulaması yapılır. Doğrulama başarısız olursa, fonksiyon bir hata mesajı döndürür.
byte status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailer_blok, &key, &(rfid.uid));
if (status != MFRC522::STATUS_OK)
{
Serial.print("Key doğrulama hatası: ");
Serial.println(rfid.GetStatusCodeName(status));
return 3; //return "3" as error message
}
//Bu kısımda bloktan veri okunur.
byte dizi_boyutu = 18; //"okunan_veri_dizisi" dizinin boyutunu belirlemek ve boyut değişkeninin adresini kütüphaneye bildirebilmek için değişken tanımlandı. boyut değişkeninin adresi, "&" işaretçisi kullanılarak kütüphaneye bildirilir.
status = rfid.MIFARE_Read(blok_no, okunan_veri_dizisi, &dizi_boyutu);
if (status != MFRC522::STATUS_OK)
{
Serial.print("MIFARE_read() Okuma Hatası: ");
Serial.println(rfid.GetStatusCodeName(status));
return 4; //return "4" as error message
}
Serial.println("Blok Okundu");
}
Devre Şeması
Seri Port Ekran Görüntüsü