MSP430 - Multiplexed 7-Segment Displays

Now that you have seen how easy it is to interface to a single seven-segment display, let us add multiple digits to the design.

In a traditional digital counter design using standard digital ICs, every time you need to add another digit you need to add another counter, latch, decoder/driver, etc. the circuit becomes more complex.

Not so with a microcontroller interface. To add another digit we simply add another seven-segment display.

Of course, there is a limit to how many digits you can have. Because each LED display is turned on for a fraction of the whole display cycle, the displays will become progressively dimmer as more digits are added. I think four digits would be the limit. For more than four digits you can drive the displays at a higher voltage which would require having to use driver transistors for every of the seven LED segments and one for every digit.


We add additional digits by connecting the pins to each of the seven segments in parallel. The COMMON ANODE pin will be driven by logic HIGH from PORT2 output pins, one for each digit.




Here is the extended layout showing three digits:






Code:
//--------------------------------------------------------
// Project #2 - Multiplexed Seven-segment LED interface
// 2013.06.11 - MrChips
//--------------------------------------------------------

#include "io430.h"

#define NUMBER_OF_DIGITS 3
#define DELAY 100000
#define TIMER_DELAY 630

char seg[16];
char d[5];
char digit;

// simple software delay
void delay(unsigned long d)
{
  unsigned long i;
  for (i = 0; i < d; i++);
}

void display_hex(unsigned short v)
{ // enter with 16-bit integer v
  // fill global array d[ ]
  short i;
  for (i = 0; i < 4; i++)
  {
     d[i] = v % 16;
     v = v/16;
  }
}

void display_BCD(unsigned short v)
{// enter with 16-bit integer v
 // fill global array d[ ]
  short i;
  for (i = 0; i < 5; i++)
  {
     d[i] = v % 10;
     v = v/10;
  }
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void myTimerISR(void)
{
  digit = ++digit % NUMBER_OF_DIGITS;   //use MOD operator
  P1OUT = ~seg[d[digit]];
  P2OUT = 1 << digit;
}

void init(void)
{
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  
  // initialize Timer0_A
  TA0CCR0 = TIMER_DELAY;                  // set up terminal count
  TA0CTL = TASSEL_2 + ID_3 + MC_1;  // configure and start timer

  // enable interrupts
  TA0CCTL0_bit.CCIE = 1;   // enable timer interrupts
  __enable_interrupt();    // set GIE in SR
  
  P1DIR  = 0xFF;       // enable segment outputs
  P2DIR  = 0x0F;   // enable digit select
  
  // create 7-segment table
  seg[0]  = 0x3F;
  seg[1]  = 0x06;
  seg[2]  = 0x5B;
  seg[3]  = 0x4F;
  seg[4]  = 0x66;
  seg[5]  = 0x6D;
  seg[6]  = 0x7D;
  seg[7]  = 0x07;
  seg[8]  = 0x7F;
  seg[9]  = 0x67;
  seg[10] = 0x77;
  seg[11] = 0x7C;
  seg[12] = 0x39;
  seg[13] = 0x5E;
  seg[14] = 0x79;
  seg[15] = 0x71;
  
  digit = 0;
}

void main( void )
{
 unsigned int n;
 init();

 n = 0;
  
 while (1)
 {
   n++;
   display_BCD(n);
   delay(DELAY);
 }
 
}
Notes

1) In order to multiplex the digits I have used the Timer module to generate regular interrupts. Review the tutorial on Timer Interrupts here:

http://forum.allaboutcircuits.com/blog.php?b=549

I have simply copied the code to initialize the Timer module.

To avoid flickering of the displays the code must cycle through all digits within 15ms. For three digits, I have set the timer to interrupt every 5ms.

2) I have created two functions:

display_BCD( )

and

display_hex( )

to suit your specific application.

display_hex may come in handy when debugging your program in some situations. Note that the only difference between the two functions is the different radix, 10 or 16.

3) A new operator has been used - the MOD operator using the symbol %. This can be viewed as an integer division whereby the result returned is the integer remainder.

4) Another new operator is the bit-wise shift operator.

x << n will shift x to the left by n bits. This is the same as multiplying by 2^n.

x >> n will shift x to the right by n bits. This is the same as dividing by 2^n. Fractional parts are discarded.

5) I have changed the pin layout in the circuit diagram from the previous circuit simply to make the layout straight forward.

6) I changed the LED displays to more efficient ones so they are much brighter. The pin-outs remain the same.


Coming Next

Now that we have multiple displays, here are some sample projects you can expect to come next:

1) Digital thermometer
2) 24-hour clock
3) frequency counter

Stay tuned.

Blog entry information

Author
MrChips
Views
15,040
Comments
1
Last update

More entries in General

More entries from MrChips

Share this entry

Top