Monday, March 23, 2009

7Segment LED Display

After getting the micro controller (uC) work, now it is time to start building small modules for later use in bigger projects. 7Segment LED is one of the common ways of output when the data is numerical.

I have a common anode 7Segment LED (Red). The 7Seg has seven segments each having to be separately lit up by grounding the appropriate cathode for that segment (actually not necessarily ground, any potential lesser than anode by ~1.5-5V). So, to control 7 segments (using a simple enough circuit), we need to have 7 bits of info, each driving one segment. As the segments are controlled through the cathode, the uC has to sink current from the 7Seg to light up a segment. This is achieved by outputting a logical 0 at the corresponding bit in the uC's output port.

The ideal thing is to connect each of those 7 cathodes to their corresponding output pins through a current limiting resistor of 330ohms. For ease of use and testing, I've positioned the resistor between the 5V supply and the anode. This is much simpler for the proof of concept and easy to wire on the breadboard. The drawback of this approach however is that, the current gets split into each of the lit segments, as a result the brightness of the segments vary based on the number of segments lit (1 being the brightest and 8 being the dimmest). I don't really care at this moment, given that I know the reason.

That's all the about the hardware side. The software needs to output the correct bits at the output port to display a digit on the 7Seg. Each digit is displayed by lighting 2 or more segments in the 7Seg. I've created a static mapping between the digits (0-9) and their corresponding segments-to-be-lit. Now, based on the number to be shown, the software outputs the bits and the digits appear on the 7seg. To keep it appealing, I've made the program to display the last digit of a running counter (as usual, a sleep between the increments to keep it visible to the eye).

Here is the code:

/* Author: Gerald Naveen A (ageraldnaveen at gmail dot com) */

#include <avr/io.h>

#define F_CPU 1000000 // 1MHz
#include <util/delay.h>
#define G_SEGA (1 << 0)
#define G_SEGB (1 << 1)
#define G_SEGC (1 << 2)
#define G_SEGD (1 << 3)
#define G_SEGE (1 << 4)
#define G_SEGF (1 << 5)
#define G_SEGG (1 << 6)

uint8_t seg7_map[10]= {
G_SEGA | G_SEGB | G_SEGC | G_SEGD | G_SEGE | G_SEGF, // 0
G_SEGB | G_SEGC, // 1
G_SEGA | G_SEGB | G_SEGG | G_SEGE | G_SEGD, // 2
G_SEGA | G_SEGB | G_SEGG | G_SEGC | G_SEGD, // 3
G_SEGF | G_SEGG | G_SEGB | G_SEGC, // 4
G_SEGA | G_SEGF | G_SEGG | G_SEGC | G_SEGD, // 5
G_SEGA | G_SEGF | G_SEGG | G_SEGC | G_SEGD | G_SEGE, // 6
G_SEGA | G_SEGB | G_SEGC, // 7
G_SEGA | G_SEGB | G_SEGC | G_SEGD | G_SEGE | G_SEGF | G_SEGG, // 8
G_SEGA | G_SEGB | G_SEGC | G_SEGD | G_SEGF | G_SEGG // 9
};

void seg7_write_digit(uint8_t d)
{
if(d > 9)
d = d % 10;

PORTD = 0xFF ^ (seg7_map[d] & 0xFF); // output logical 0 to light that segment
}

int main()
{
DDRD = 0xFF;
int i = 0;
while(1)
{
seg7_write_digit(i++);
_delay_ms(400);
}
return 0;
}
Here is the circuit in action:



This code I wrote is useful to drive one 7Seg LED; the next job is to drive more than one 7Seg LED -- yes it is different. See you then.

No comments:

Post a Comment