TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: sistemasorp en 26 de Agosto de 2009, 14:28:09
-
Hola.
Recientemente adquirí unas tarjetas goldcard (smartcard con PIC 16f84a) y quería de momento simular un ATR (answer to reset), pero con el lector de tarjetas que tengo siempre me da error, por lo que creo que el código esta mal, pero no se donde:
#include <16F84A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#use delay(clock=3571200)
#use fast_io(b)
void envia_byte(char caracter);
void main()
{
unsigned char atr[] = {0x3B,7,1,2,3,4,5,6,7};
int indice;
//setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
SET_TRIS_B(0);
OUTPUT_HIGH(PIN_B7);
for(indice = 0; indice < sizeof(atr); indice++)
{
envia_byte(atr[indice]);
}
OUTPUT_HIGH(PIN_B7);
for(;;);
}
void envia_byte(unsigned char caracter)
{
int contador;
int valor = 0x80;
int paridad = 0;
OUTPUT_LOW(PIN_B7);
delay_us(104);
for(contador = 0; contador < 8; contador++)
{
if(caracter & valor > 0)
{
OUTPUT_HIGH(PIN_B7);
paridad++;
}
else
{
OUTPUT_LOW(PIN_B7);
}
valor >>= 1;
delay_us(104);
}
// paridad
if(paridad % 2 == 0)
{
OUTPUT_LOW(PIN_B7);
}
else
{
OUTPUT_HIGH(PIN_B7);
}
delay_us(104);
//stop
OUTPUT_HIGH(PIN_B7);
delay_us(208);
}
Parto de la base de que los lectores de tarjetas, según el estandar ISO 7816 otorgan al PIC una frecuencia de 3,57 Mhz. Que después de un reset la tarjeta se comunica a 9600 bps, 8 bits de datos, paridad par y 2 bits de stop. La espera entre bit y bit es de 104 us cuando se trata de una velocidad de 9600 bps. El ATR es muy sencillo, sólo envía el TS, un T0 indicando 7 bytes históricos y 7 bytes (del 1 al 7).
-
Me respondo a mi mismo (por si a alguien le sirve) con un código que además de devolver el ATR, devuelve el CLA INS P1 P2 y LEN de cualquier orden que se le envíe. Probado con una goldcard y un lector smartcard ltc31.
#include <16F84A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#use delay(clock=3571200)
#use fast_io(b)
#byte W = 0x0000
#byte F = 0x0001
#byte PORTB = 0x06
#byte STATUS = 0x03
byte CONST C = 0x0000;
void sendByte(int iSendData);
int receiveByte();
void main()
{
unsigned char atr[] = {0x3B,0x09,0,0xFF,0x80,0xAA,'o','s','c','a','r'};
unsigned char envia[5];
int indice;
SET_TRIS_B(0x7F);
OUTPUT_HIGH(PIN_B7);
//delay_us(RETARDO * 3);
for(indice = 0; indice < sizeof(atr); indice++)
{
sendByte(atr[indice]);
}
for(;;)
{
for(indice = 0; indice < 5; indice++)
{
envia[indice] = receiveByte();
//WRITE_EEPROM(indice, envia[indice]);
}
sendByte(envia[1]);
for(indice = 0; indice < 5; indice++)
{
sendByte(envia[indice]);
}
sendByte(0x90);
sendByte(0);
}
}
void sendByte(int iSendData)
{
int iParity;
int iCtr;
int iPauseCtr;
#asm
movlw 0x32 ; Pause for 170 ?s
call Pause ; call Pause
bcf PORTB,7 ; Send start bit in RB7
movlw 0x7F
tris PORTB ; TRIS PORB with 01111111 (0x7F)
clrf iParity ; Initialize Parity to 0
movlw 0x08
movwf iCtr ; Initialize 8 to counter to send 8 data bits
send_loop:
call Std_pause ; Pause for 93 ?s (at 9600 bps)
rrf iSendData,f
rrf iSendData,W
andlw 0x80
xorwf iParity,f ; Calculate Parity
xorwf PORTB,W
xorwf PORTB,f
decfsz iCtr,f ; Decrement Data Bit counter
goto send_loop ; Loop
call Std_pause ; Pause
movf iParity,W ; Send Parity
xorwf PORTB,W
xorwf PORTB,f
call Std_pause
movlw 0xFF
tris PORTB
movlw 0x3E
goto Pause ; Pause 0x3E
Std_pause:
movlw 0x1A ; Standard Pause Value
Pause:
movwf iPauseCtr ; Initialize iPauseCounter with value of W Register
Pause_loop:
decfsz iPauseCtr,f ; Decrement Pause Counter
goto Pause_loop
retlw 0x00 ; Return after setting W Register to 0
#endasm
}
int receiveByte()
{
int iCtr;
int iPauseCtr;
int iReceiveData;
#asm
Receive:
btfsc PORTB,7
goto Receive
movlw 0x2D
call Pause
movlw 0x09
movwf iCtr
ReceiveLoop:
bcf STATUS,C
btfsc PORTB,7
bsf STATUS,C
rrf iReceiveData,f
call Std_pause
nop
nop
decfsz iCtr,f
goto ReceiveLoop
rlf iReceiveData,f
movlw 0x1D
call Pause
movf iReceiveData,W
#endasm
return iReceiveData;
#asm
Std_pause:
movlw 0x1A
Pause:
movwf iPauseCtr
Pause_loop:
decfsz iPauseCtr,f
goto Pause_loop
retlw 0x00
#endasm
}