.

QuickBuilder
for Microchip PICs

Home - About- Consulting* - Articles - FAQs - Contact
Tour - Application Example - Sub circuits - Projects - Download
Projects: Serial I2C Smart Card Reader/Writter

This QuickBuilder project can be downloaded here.

 

Serial I2C Smart Card Reader/Writter


Introduction
This project demonstrates how to operate the 'I2C card reader (ST14C02)' using a serial interface.

The target device is a PIC16F84 running at 4Mhz.

Operation
See application code below. When a 256-byte I2C memory card such as the ST Microelectronics ST14C02 is inserted in to the card socket the string "/E01" is transmitted out of the serial port, when the card is removed the string "/E00" is transmitted.

The card reader/writer responds to the following commands. All commands are appended with a carriage return.

READ
"/Raa" Read 4-bytes of data from hexadecimal address aa.
Example: Read 4-bytes of data from address 80hex.
Command: "/R80"
Response: "/Rdddddddd" where dd is hexadecimal data

WRITE
"/Waadddddddd" Write 4-bytes of data to hexadecimal address aa.
Example: Write 4-bytes of data (1,2,3,4) to address 00hex
Command: "/W0001020304"
Response: "/W"

QUERY
"/Q" Query card status.
Example: Get card status
Command: "/Q"
Response: "/Qdd" where dd=00 card absent, dd=01 card present

Remember to put the carriage return at the end of each command.


Application code
Below is the application code for this project. To use it, select and copy (ctr-insert) the code below, paste it into a text editor and save as a 'C' file in your working directory. You may also need to change the build output path using 'Project | Options'

 

 
///////////////////////////////////////////////////////////////////////
////                           AI2CCARD.C                          ////
////                                                               ////
////  Demonstrates the 'I2C card reader (ST14C02)' sub-circuit.    ////
////  When an ST140 is inserted into the card socket the           ////
////  string "/E01" is sent and "/E00" when the card is removed.   ////
////  "/Waadddddddd" writes data to the card where aa is the       ////
////  address in hex and DD are four data bytes to write.          ////
////  "/Raa" reads four bytes of data from address aa.             ////
////  All commands and responses are appended with a carriage      ////
////  return.                                                      ////
////                                                               ////
////  This program is an example of how your application code is   ////
////  is organised. Note the #include "i2ccard.inc", this include  ////
////  file was generated by QuickBuilder and contains all          ////
////  dirver code.                                                 ////
////                                                               ////
////  This demo is intended for  a PIC16F84                        ////
////  Compile using CCS 'C'  visit www.quickbuilder.co.uk/qb/ccs   ////
///////////////////////////////////////////////////////////////////////
#include <16f84.H>

#fuses   XT,NOPROTECT,NOWDT

#case

#include "i2ccard.inc"


// Comms vars
int     RxCmd = 0;
int     RxData[8];
int     RxIP=0;
int     RxState = 0;

void BlinkLED(void) {
    LED_1OFF();
    delay_ms(100);
    LED_1ON();
}

int HexToNibble( char c ) {
    if ( (c >= '0') && (c <= '9') )
        return c-'0';
    else if ( (c >= 'A') && (c <= 'F') )
        return c-('A'-0x0a);
    else
        return 0;
}

int GetCommand( void ) {
    int c,d,n;
    

    if ( RS232_1INCOMING()==0 )     // incomming char
        return 0;

    c = RS232_1IN();
    if (c=='/')
        RxState = 0;    

    switch ( RxState ) {
        case 0 : // command start
            RxIP = 0;
            n = 0;
            RxCmd = RS232_1IN();        // get command char
            RxState = 1;
            break;
        case 1 : // get data
            if (c==0x0d) {              // end of commad hex data
                RxState = 0;
                return 1;
            } else {                    // get data
                c = HexToNibble( c);
                if ( !bit_test(n,0) ) { // high nibble
                    RxData[ RxIP ] = c<<4;
                    n++;
                } else {                // low nibble
                    RxData[ RxIP] |= c;
                    RxIP++;             // inc index and wrap
                    RxIP &=0x7;
                    n++;
                }
            }
            break;
        default: // illegal state
            RxState = 0;
    }
    return 0;
}

void DoCommand( void ) {
    int addr,i,d;

    BlinkLED();
    switch (RxCmd) {
        case 'R' :  // read 4-bytes from card
            printf(RS232_1OUT,"/R");
            for (i=0 ; i<4; i++) {
                d = ST1402_1READ( RxData[0]++ );
                printf(RS232_1OUT,"%02X", d);
            }
            printf(RS232_1OUT,"\n");
            break;
        case 'W' :  // write 4-bytes to card 
            for (i=1 ; i<5; i++) {
                ST1402_1WRITE( RxData[0]++,RxData[i] );
            }
            printf(RS232_1OUT,"/W\n");
            break;
        case 'Q' : // query card status
            if ( ST1402_1PRESENT() )    // card present
                printf(RS232_1OUT,"/Q01\n");
            else                        // card not present
                printf(RS232_1OUT,"/Q00\n");
            break;

        default:    // unknown command
            printf(RS232_1OUT,"/?\n");        
        }
    RxCmd = 0;

}

void DoCard( void ) {
    static int1 CardPresent=0;

    if (ST1402_1PRESENT() ) {
        if (!CardPresent) {
            BlinkLED();
            printf(RS232_1OUT,"/E01\n");
        }
        CardPresent = 1;
    } else {
        if (CardPresent) {
            BlinkLED();
            printf(RS232_1OUT,"/E00\n");
        }
        CardPresent = 0;
    }

}

main() {
    INIT_SUB_CIRCUITS();
    BlinkLED();

    while(1) {
        if ( GetCommand() )
            DoCommand();
        DoCard();
    }
}
Copyright 2002-2009 Summit Electronics Ltd
www.quickbuilder.co.uk