Saturday, February 25, 2012

Interfacing 7 segment displays with AVR (ATmega32)

Recently, I had the opportunity to give a workshop on AVR microcontroller in American International University of Bangladesh (AIUB). I had prepared some codes for the conference, which I will share here.

7 Segment displays can be readily interfaced to the AVR by applying high or low output to their pins from an AVR. For my circuit I had used a common anode 7 seg display.






This figure shows the basic connection. To increase port usage, multiple 7 segment displays can be time multiplexed and the anode pin is controlled with a seperate pin. (This technique was actually shown to me first by my friend UM Omee)

The same block is copied to form this structure:



Finally the 7 segment displays are driven with the help of a ULN2803 IC. The 2803 is a combination of 8 darlington pair ICs, each capable of sinking 1000mA current. 

The final circuit is shown as follows:



For accessing single pins of the portA, the SFR_MEM_ADDR command is used. The given code example uses only two seven segment displays. It is essentially a mod 100 counter.

#include <avr/io.h>
#include <util/delay.h>


/* Code for single pin addressing */
typedef struct 
{ 
  unsigned char bit0:1; 
  unsigned char bit1:1; 
  unsigned char bit2:1; 
  unsigned char bit3:1; 
  unsigned char bit4:1; 
  unsigned char bit5:1; 
  unsigned char bit6:1; 
  unsigned char bit7:1; 
}io_reg; 

#define D0      ((volatile io_reg*)_SFR_MEM_ADDR(PORTA))->bit4
#define D1      ((volatile io_reg*)_SFR_MEM_ADDR(PORTA))->bit5
#define D2      ((volatile io_reg*)_SFR_MEM_ADDR(PORTA))->bit6
#define D3      ((volatile io_reg*)_SFR_MEM_ADDR(PORTA))->bit7

/* Code for 7 seg display */
static unsigned  char SEVEN_SEG[] = {
0x3F,
0x06,
0x5B,
0x4F,
0x66,
0x6D,
0x7D,
0x07,
0x7F,
0x6F,
0x77,
0x7C,
0x39,
0x5E,
0x79,
0x71};


int main (void) {
unsigned char num = 0x01;
int i;

DDRB = 0xFF;
DDRA = 0xFF;



while (1) {

 num ++;
 if (num> 99) num = 0;


 for (i=0; i<10; i++) {
  D0=0;
  D1=0;
  PORTB = SEVEN_SEG[num%10];
  D0=1;
  D1=0;
  _delay_ms(10);
  D0=0;
  D1=0;
  PORTB = SEVEN_SEG[num/10];
  D0=0;
  D1=1;
  _delay_ms(10);
  }
 }

}

So this is how the output looks like in Proteus:


2 comments:

  1. do u help me to burn hex file into AT89C51 uc?

    ReplyDelete
  2. excellent post about seven segment driving. especially the proteus simulation, the way shown is very nice. but i think u shouldn't provide delay of 1 sec

    ReplyDelete