I2C-Chipkarten
aus MariaTheresia, der freien Wissensdatenbank
I²C – Chipkartenlesegerät
Diese Projekt umfasst die Möglichkeit über I²C von Chipkarten zu lesen, so wie es bei vielen Zeitnehmungssystemen möglich ist.
Zuerst ist einmal ein Wissen über I²C erforderlich.
hier einige hilfreiche Seiten:
www.sprut.de/electronic/pic/grund/i2c.htm
www.hifish.de/sebastian/_LE_DA/node31.html
weiters die benötigten wir Bauteile:
I²C-fähige Chipkarten
... sind bei Conrad erhältlich:
Artikel-Nr. Größe Preis 967815 – HK 2kBit 4,99 € 972924 – HK 16kBit 6,95 € 972967 – HK 64kBit 9,95 € //?könnte das Programm etwas anders sein
zum lesen der Karten wir außerdem ein Kartenleser
... ebenfalls bei Conrad erhältlich: (unter dem Begriff: Chipkarten-Kontaktiereinrichtung)
Artikel-Nr. Preis 730513 – HK 5,95 730521 – HK 11,53
I²C fähiger Prozessor (ich verwendete den 16F877A von [www.microchip.com])
3 x 4k7 Ohm Wiederstände
natürlich ein paar Stecker und Drähte für die Verbindung
---
nun zur Verkabelung: die Informationen finden Sie in hier: I2C_Bauplan.pdf
---
Nun zu meinem Programm
Wenn eine Chipkarte eingesteckt wird, beginnt das Programm. Es fragt einen 4-Stelligen Code ab und vergleicht ihn mit einem der auf der Karte gespeichert wurde. Ein Mastercode (2222) lässt zu dass zugegriffen wird, ohne den Code zu wissen. (z.B. wenn die Karte noch keinen Code hat) Es lassen sich dann Daten von der Karte auslesen oder neue Daten darauf speichern.
der Code: -- chipkarten.c --
///************ Chipkarten über I2C ***********************///
///************ Version 1: Claudia Michalecz **************///
#include <16F877.h>
#include <stdlib.h>
#include <I2C.c>
#fuses hs,nowdt,put,noprotect
#use DELAY(CLOCK=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define CODE_ADR 0x70 //Speicheradresse des Codes
#define NAME_ADR 0x50 //Speicheradresse eines Namensfeldes
#define CHIP_NR 0xa0 //Device Adresse des genützen Speichers
#define CARD_PIN pin_b0 //Prüfpin des Kartenkontaktes
int read_code (void) //Liest und überprüft den Code
{
byte code[4], c_code[4];
//code … User, c_code … auf der Karte
int gueltig=0, zz=0, x=0;
for( ;gueltig==0 && zz<3;zz++)
{
printf("\r\nBitte geben Sie den Code ein: ");
for(x=0; x < 4; x++)
{
code[x]=getc(); //Eingabe des Codes
if(code[x]>='0' && code[x]<='9') //nur Zahlen
{
putc('*');
code[x]-=48;
x++;
}
}
gueltig=2;
for(x=0; x<4; x++) if(code[x]!=2) gueltig=0;
//Vergleich mit dem Mastercode
if(gueltig < 2)
{
read_i2c_struct(c_code, CODE_ADR, 4, CHIP_NR);
gueltig=1;
for(x=0; x<4; x++) if(code[x]!=c_code[x]) gueltig=0;
//lesen und vergleichen mit dem Kartencode
}
if(gueltig==0) printf("\n\r Leider der falsche Code. Sie haben noch %d Versuche", 2-zz);
}
if(gueltig==2) printf("\n\r MASTERCODE");
if(gueltig==1) printf("\n\r Code gueltig");
if(gueltig==0) printf("\n\r Code 3x ungeueltig eingegeben, Karte wird ausgeworfen");
return (gueltig);
}
void read_i2c_data (void) //lesen Daten von der Karte
{
byte name[30];
int zz=0;
read_i2c_struct(name, NAME_ADR, 30, CHIP_NR);
printf("\n\r DATEN der Chipkarte: ");
printf("\n\r Name: ");
for(zz=0; zz<30; zz++) {putc((char)name[zz]);}
//Ausgabe des abgespeicherten Namens
getch();
}
void change_i2c_data(void) //Ändern der Daten auf der Karte
{
byte name[30], code[4];
int zz=0;
printf("\n\r Bitte geben Sie den Namen ein: (max. 30 Zeichen) ");
for(zz=0; zz<30 && (zz==1 || name[zz-1]!= '\r'); zz++)
{
name[zz]=getc();
putc((char) name[zz]);
} //Eingabe des Namens durch User
zz = zz - 1;
for(; zz<30; zz++) name[zz]=' '; //Auffüllen mit Blanks
write_i2c_struct(name, NAME_ADR, 30, CHIP_NR);
//Schreiben auf die Karte
printf("\n\r Bitte geben Sie einen Code ein: (4 Zahlen) ");
for(zz=0; zz<4;) //Codeeingabe, wieder nur Zahlen
{
code[zz]=getc();
if(code[zz]>='0' && code[zz]<='9')
{
putc('*');
code[zz]-=48;
zz++;
}
}
write_i2c_struct(code, CODE_ADR, 4, CHIP_NR);
//Schreiben auf die Karte
printf("\n\n\r Daten wurden gespeichert");
}
int menue (int user) //Auswahlmenü
{
int next=0;
while( (next<1 || next>3) && !(user==2 && next==4))
{
printf("\n\n\r -- MENUE --");
printf("\n\r Was wollen Sie tun?");
printf("\n\r (1) Daten auslesen"); //read_i2c_data()
printf("\n\r (2) Daten eingeben"); //change_i2c_data()
printf("\n\r (3) Exit");
if(user==2) printf("\n\r (4) Karte auslesen");
//read_card() nur vom Master aus möglich
next=(int)getc()-48; //Eingabe als Zahl in Ascii
}
return next;
}
void read_card (void)//lesen was alles gespeichert-für 16kbit!
{
Byte adr=0x00, text[32];
int c_nr = 0xa0;
int zz=0, start=0;
for (;c_nr<0xb0; c_nr+=0x02)
//durchlaufen aller 8 Speicher der Karte
{
start=0;
for (adr=0x00 ; adr>0x00 || start==0 ; adr+=32)
{
//durchlaufen in 32-Sätzen
start=1;
read_i2c_struct(text, adr, 32, c_nr); // 32 Byte lesen
printf("%04x - %04x ",c_nr,adr); // und ausgeben
for(zz=0; zz<32; zz++) {putc((char) text[zz]);}
printf("\n\r");
}
delay_ms(800);
}
getch();
}
void main (void)
{
int c=0, next=0;
init_i2c();
printf("\r\n\n\n\n\n\n START DER KONSOLE\n\r");
output_low (CARD_PIN);
while(TRUE)
{
//solange keine Karte eingefügt wurde
while(!input(CARD_PIN)) {
printf("\r\n Bitte fuegen Sie eine Karte ein!");
delay_ms(500);
}
printf("\r\n\n Karte wurde eingefuegt");
c=read_code(); //wenn ungültig 0, gültig 1, mastercode 2
if(c > 0)
{
do
{
next=menue(c); //menüfunktion
switch (next)
{
case 1: read_i2c_data(); break; //daten lesen
case 2: change_i2c_data(); break; //daten ändern
case 3: break; //karte auswerfen
case 4: read_card(); next = 0; break; //karte auslesen
default: next=0;
}
} while(next<3);
}
//karte auswerfen, bwz. warten bis entnommen wird
while(input(CARD_PIN)) {
printf("\n\r Bitte entnehmen Sie die Karte");
delay_ms(500);
}
}
}
-- I2C.c --
Das Grundgerüst zu diesem Programm habe ich von Andreas Pirker – vielen Dank
///************ I²C Funktionen ****************************///
///************ Version 1: Andreas Pirker *****************///
///************ Überarbeitung: Claudia Michalecz **********///
//für pic16f877a
#define I2C_SDA pin_C4 //SDA -- Datenleitung
#define I2C_SCL PIN_C3 //SCL -- Clock, Tackt
#use DELAY(CLOCK=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use I2C(MASTER, SDA=I2C_SDA, SCL=I2C_SCL, FORCE_HW, FAST)
//Master, festlegung der Leitungen, HW-Steuerung, Fast-Mode
//Initialisieren des I2C-Buses
void init_i2c()
{
output_float(I2C_SCL);
output_float(I2C_SDA);
}
//Schreiben von einem Byte über I2C
void write_i2c(Byte address, BYTE data, int c_nr)
{
short int status;
i2c_start(); //Belegen des Buses
i2c_write(0xfe & c_nr); //schreiben der Deviceadresse
i2c_write(address); //Datenadresse
i2c_write(data); //1 Byte Daten
i2c_stop(); //Busfreigabe
//Warten bis die Daten verarbeitet und Gerät wieder bereit
i2c_start();
status=i2c_write(c_nr);
//Statusabfrage, 0-Gerät reagiert, 1-Gerät reagiert nicht
while(status==1) //Warten bis es reagiert
{
i2c_start();
status=i2c_write(0xa0 | c_nr);
}
i2c_stop();
}
BYTE read_i2c(Byte address, int c_nr) //Lesen eines Bytes
{
BYTE data;
i2c_start(); //Belegen des Buses
i2c_write(0xfe & c_nr); //schreiben der Deviceadresse
i2c_write(address); //Datenadresse
i2c_start(); //Restarten des Buses
i2c_write(0xa1 | c_nr); //1 steht für Lesezugriff
data=i2c_read(0); //1 Byte lesen
i2c_stop(); //Freigeben des Buses
return(data);
}
//Schreiben von beliebig vielen Bytes
void write_i2c_struct(byte *ptr,byte address,int size,int c_nr)
{
int i = (int) address, start=0;
byte status;
//schreiben nur innerhalb eines Blocks (max 256 Bytes)
for(; i < (size + (int)address && i < 256 ;)
{
start=0;
i2c_start(); //Belegen des Buses
i2c_write(0xfe & c_nr); //schreiben der Deviceadresse
i2c_write(address); //Datenadresse
//Daten werden in 16er Blöcke geschrieben
for (; i<size && i<256 && start == 0 || (i%16) > 0; i++)
{
i2c_write(ptr[i]);
start=1;
}
i2c_stop(); //vorläufige Freigabe
//Warten bis die Daten verarbeitet und Gerät wieder bereit
i2c_start();
status=i2c_write(c_nr);
while(status==1)
{
i2c_start();
status=i2c_write(c_nr);
}
i2c_stop();
address+=16; //Beginnpunkt der nächsten 16 Bytes
}
}
//Lesen von beliebig vielen Bytes
void read_i2c_struct(byte *ptr, byte address, int size, int c_nr)
{
int i = 0;
i2c_start(); //Belegen des Buses
i2c_write(0xfe & c_nr); //schreiben der Deviceadresse
i2c_write(address); //Datenadresse
i2c_start(); //Restarten des Buses
i2c_write(0xa1 | c_nr); //1 steht für Lesezugriff
for (; i < size - 1; i++) //1 … noch weitere Bytes bitte
{
ptr[i] = i2c_read(1);
}
ptr[i] = i2c_read(0); //0 … keine weiteren Bytes mehr
i2c_stop(); //Busfreigabe
}
Seitenkategorien: TODO | Projekt | Elektronik | Smartcard | Projekt

