Drive Smart Cards With A Low-Cost MCU's UART

Idea for Design published in the Electronic Design magazine on March 29, 2007.
www.electronicdesign.com/Articles/ArticleID/15147/15147.html
By Carlos Cossio

 

DESIGN IDEAS
- CMOS IC Makes Low-Cost Digital Potentiometer

- Power Management In The ST62


-
Automatic Power-Off Circuit Saves Battery

- Simple PC Smart Card Reader Enhancement

-
Digital Position Encoder Does Away With ADC

-
Single-Supply RS-232 Transmission Without Level-Translator ICs

-
µC Controls Charge Pump As Background Task

-
Clock Multiplier Circumvents PLL

- Drive Smart Cards With A Low-Cost MCU's UART 

- Wireless “Battery” Energizes Low-Power Devices

- Harvest Energy Using A Piezoelectric Buzzer

- Drive A Single-Coil Latching Relay Without An H-Bridge Circuit

DESIGN CONTESTS
- The Mobile Phonebook

- The CheckPoint Charlie

- The Lord Of The Keys

- MoneyPenny

- Enigma

- Bye Bye Standby


- Flower Power

ARTICLES
- Mobile Phone Book: M16C/62P Based Data Backup System

- Internet Password Manager

- RFID Payment Terminal 

- Tecnología NFC Para Aplicaciones De Proximidad Seguras

- The Green Standby

- Flower Power

CONTACT
- E-mail

 

The growing need for security and enhanced functionality in the banking, identification, and telecom markets has increased the use of smart cards worldwide, to the detriment of the low-security magnetic-stripe cards.

However, the development of the hardware and firmware needed for proper communications in a system based on a smart card poses new challenges to designers. Unfortunately, only some high-end microcontrollers have a dedicated UART (universal asynchronous receiver/transmitter) that can drive smart cards directly. The design described here, though, lets you drive a smart card using just the standard UART on a low-end 8-bit microcontroller, in this case an Atmel AVR ATmega 168.

Smart cards have just one communication path, labeled I/O, with the outside world, so it's used as a bidirectional signal to input and output data. This signal must line up with the UART's unidirectional reception and transmission signals RxD and TxD, respectively. Because RxD is an input signal and TxD is an output signal, a 1-kΩ resistor must be used to connect them to the smartcard I/O line to avoid line contention (see the figure).

On the firmware side, the design must implement a specific procedure for the reception and transmission of data to and from the smart card (see the code listing). On the one hand, to receive a byte from the smart card, the system must disable the UART's transmitter unit again, to avoid line contention.

On the other hand, to transmit a byte to the smart card, the firmware must disable the UART's reception unit to avoid the reception of an echo character. Then it must wait until the end of the byte transmission to avoid false byte receptions. In this way, you can exchange information back and forth with the smart card using the T=0 protocol described in section 3 of the Smart Card Standard, ISO 7816-3, Electronic Signals and Transmission Protocols.

As an improvement and to fully comply with the standard describing the smart-card communication protocols the design must implement the parity error detection and re-transmission scheme defined in the ISO 7816-3 standard.

#include <avr/io.h>

#define CARD_BAUD_RATE          12711
#define FOSC                    4915200L
#define ISO7816_BAUD_RATE       (FOSC/16/CARD_BAUD_RATE - 1)
 

/*****************************************************************************
Name:         ISO7816_Init
Author:       Carlos Cossio  
Parameters:   None             
Returns:      None
Description:  USART0 initialization - 12711 baud, 8 data bits, 2 stop bit, even parity
*****************************************************************************/
void ISO7816_Init (void)
{
    DDRD &= ~((0x01<<TXD) | (0x01<<RXD));               // TXD & RXD pins as input

    UBRR0H = (unsigned char)(ISO7816_BAUD_RATE>>8);     // Set the baud rate register
    UBRR0L = (unsigned char) ISO7816_BAUD_RATE;    

    UCSR0B = ((1 << RXEN0) | (1 << TXEN0));             // Enable USART0 receiver and
                                                        // transmitter
    UCSR0C = (1<<USBS0)|(3<<UCSZ00)|(2<<UPM00);         // Set frame format:
                                                        // 8 data, even parity, 2 stop bits
    PORTD |= (0x01<<PD4);                               // Set CARD_RST pull-up
    PORTD &= ~(0x01<<PD4);                              // CARD_RST low
    DDRD |= (0x01<<PD4);                                // CARD_RST as output
}

/*****************************************************************************
Name:        ISO7816_ReceiveByte
Author:      Carlos Cossio      
Parameters:  None                  
Returns:     Byte received  
Description: This function waits and receives an asynchronous serial byte
             through the RxD pin. The communication frame is 1 start bit,
             8 data bits (LSB first), 1 even parity bit. This transmission is
             followed by 2 stop bits.
             The parity error detection and re-transmission scheme as defined
             in the ISO7816 standard is not implemented.
******************************************************************************/
unsigned char ISO7816_ReceiveByte (void)
{
    UCSR0B &= ~(1 << TXEN0);                            // Disable transmitter
    UCSR0B |= (1 << RXEN0);                             // Enable receiver        

    while (!(UCSR0A & (1<<RXC0)));                      // Wait for incomming data

    return (UDR0);                                      // Read in
}                                

/*****************************************************************************
Name:        ISO7816_SendByte
Author:      Carlos Cossio

Parameters:  byte -> the character to output                   
Returns:     None  
Description: This function transmits a byte in a serial asynchronous format,
             through the TxD pin. The communication format is the following:                                   
             1 start bit - 8 data bits (LSB first) - 1 even parity bit
             This transmission is followed by two stop bits.
             The parity error detection and re-transmission scheme as defined in
             the ISO7816 standard is not implemented.
*****************************************************************************/
void ISO7816_SendByte (unsigned char byte)
{   
    UCSR0B &= ~(1 << RXEN0);                            // Disable receiver
    UCSR0B |= (1 << TXEN0);                             // Enable transmitter  

    while (!(UCSR0A & (1<<UDRE0)));                     // Wait for empty transmit buffer                    

    UCSR0A |= (1 << TXC0);
    UDR0 = byte;                                        // Start transmission  

    while (!(UCSR0A & (1<<TXC0)));                      // Wait for end of transmission                
}

Listing: Functions to initialize, receive a byte, and send a byte to the smart card through the Atmel AVR microcontroller’s UART

 


© 2007 Carlos Cossio. All Rights Reserved.