November 13, 2011
by claesz
|
Hi guys!
I had this 4 digit LED display laying around and decided to write a short lib for it.

These displays are available on ebay and elsewhere for less than $1 and are quite useful for displaying time and other numbers.
The display requires 12 pins, but since it runs on interrupt, you can use the pins for other stuff outside the interrupts. Just keep the LOW pin for each digit off.
My display is marked "5461AS" but all the similar looking displays I found on ebay had the same basic structure. The only thing that differed was whether the pin controlling each digit should be LOW or HIGH. This display requires this pin to be LOW and each "line controlling pin" to be HIGH. But depending on your display you may have to switch this around.
Anyway, the library was hammered together in about an hour, so I am sure there is room for improvement. However, it seems to work.
You can use fprintf to display data. Since these displays have no diagonal lines you really cannot display anything other than numbers (letters like "K", "R" and "H" would be impossible), so this lib is limited to numbers and decimal points. You can print f ex "12.00" or "12,00", "1,200", "120,0" or "1234".
I included a LED brightness setting, so you can easily dim or increase the LED light. Might be useful for f ex an alarm clock where you want to dim the light during night hours.
If someone has written a similar lib before, I apologize. If not, hopefully some of you may find it useful.
This is the lib:
#include <stdio.h>
#include "../libnerdkits/delay.h"
#include <avr/interrupt.h>
// You need to define the pins you have used for the LED display. 12 pins in total
// LED pin 12, 9, 8 and 6 control the LOW of each digit. The rest controls each line in the
// digit. Outside interrupts you can use the other pins for whatever you want, as long as
// 12, 9, 8 and 6 are kept LOW.
#define LEDPN1 (1<<PC0)
#define LEDPO1 PORTC
#define LEDDDR1 DDRC
#define LEDPN2 (1<<PC1)
#define LEDPO2 PORTC
#define LEDDDR2 DDRC
#define LEDPN3 (1<<PC2)
#define LEDPO3 PORTC
#define LEDDDR3 DDRC
#define LEDPN4 (1<<PC3)
#define LEDPO4 PORTC
#define LEDDDR4 DDRC
#define LEDPN5 (1<<PC4)
#define LEDPO5 PORTC
#define LEDDDR5 DDRC
#define LEDPN6 (1<<PC5)
#define LEDPO6 PORTC
#define LEDDDR6 DDRC
#define LEDPN7 (1<<PD6)
#define LEDPO7 PORTD
#define LEDDDR7 DDRD
#define LEDPN8 (1<<PB5)
#define LEDPO8 PORTB
#define LEDDDR8 DDRB
#define LEDPN9 (1<<PB4)
#define LEDPO9 PORTB
#define LEDDDR9 DDRB
#define LEDPN10 (1<<PB3)
#define LEDPO10 PORTB
#define LEDDDR10 DDRB
#define LEDPN11 (1<<PB2)
#define LEDPO11 PORTB
#define LEDDDR11 DDRB
#define LEDPN12 (1<<PB1)
#define LEDPO12 PORTB
#define LEDDDR12 DDRB
int LED5461_char[] = { 0b11111100, 0b01100000, 0b11011010, 0b11110010, 0b01100110, 0b10110110, 0b10111110, 0b11100000, 0b11111110, 0b11100110 }; // defines each number ABCDEGH-DP as defined in datasheet
int LED5461_display[] = {0, 0, 0, 0}; // stores the display data (what to display in digit 1,2,3 and 4 respectively
int LED5461_decimal[] = {0, 0, 0, 0}; // stores the decimal point data (1 = ON, 2 = OFF) for decimal points 1,2,3,4
int LED5461_pos = 0; // Stores the current write position
int LED5461_brightness = 300; // used to set how long the light is kept on for each interrupt
void LED5461_refresh(d) {
switch(d) {
case 1: // digit 1 is LEDPN12
LEDDDR12 |= LEDPN12; // so set 12 to on
LEDPO12 &= ~LEDPN12; // and to low
LEDDDR9 &= ~LEDPN9; // and 9,8,6 to off
LEDDDR8 &= ~LEDPN8;
LEDDDR6 &= ~LEDPN6;
break;
case 2:
LEDDDR12 &= ~LEDPN12;
LEDDDR9 |= LEDPN9;
LEDPO9 &= ~LEDPN9;
LEDDDR8 &= ~LEDPN8;
LEDDDR6 &= ~LEDPN6;
break;
case 3:
LEDDDR12 &= ~LEDPN12;
LEDDDR9 &= ~LEDPN9;
LEDDDR8 |= LEDPN8;
LEDPO8 &= ~LEDPN8;
LEDDDR6 &= ~LEDPN6;
break;
case 4:
LEDDDR12 &= ~LEDPN12;
LEDDDR9 &= ~LEDPN9;
LEDDDR8 &= ~LEDPN8;
LEDDDR6 |= LEDPN6;
LEDPO6 &= ~LEDPN6;
break;
}
d--; // adjust as digit starts on 1 while array starts on 0.
if ( LED5461_char[LED5461_display[d]] & (1<<7) ) { LEDPO11 |= LEDPN11; } else { LEDPO11 &= ~LEDPN11; }
if ( LED5461_char[LED5461_display[d]] & (1<<6) ) { LEDPO7 |= LEDPN7; } else { LEDPO7 &= ~LEDPN7; }
if ( LED5461_char[LED5461_display[d]] & (1<<5) ) { LEDPO4 |= LEDPN4; } else { LEDPO4 &= ~LEDPN4; }
if ( LED5461_char[LED5461_display[d]] & (1<<4) ) { LEDPO2 |= LEDPN2; } else { LEDPO2 &= ~LEDPN2; }
if ( LED5461_char[LED5461_display[d]] & (1<<3) ) { LEDPO1 |= LEDPN1; } else { LEDPO1 &= ~LEDPN1; }
if ( LED5461_char[LED5461_display[d]] & (1<<2) ) { LEDPO10 |= LEDPN10; } else { LEDPO10 &= ~LEDPN10; }
if ( LED5461_char[LED5461_display[d]] & (1<<1) ) { LEDPO5 |= LEDPN5; } else { LEDPO5 &= ~LEDPN5; }
if ( LED5461_decimal[d] ) { LEDPO3 |= LEDPN3; } else { LEDPO3 &= ~LEDPN3; }
}
ISR(TIMER0_COMPA_vect) {
//interrupt handler
int i;
for(i = 1; i<5; i++) {
LED5461_refresh(i);
delay_us(LED5461_brightness);
}
LEDDDR12 &= ~LEDPN12;
LEDDDR9 &= ~ LEDPN9;
LEDDDR8 &= ~LEDPN8;
LEDDDR6 &= ~LEDPN6;
}
void LED5461_start() {
//Timer interrupt
TCCR0A |= (1<<WGM01);
TCCR0B |= (1<<CS02) | (1<<CS00);
OCR0A = 143;
TIMSK0 |= (1<<OCIE0A);
sei();
// set all line pins to output
LEDDDR1 |= LEDPN1;
LEDDDR2 |= LEDPN2;
LEDDDR3 |= LEDPN3;
LEDDDR4 |= LEDPN4;
LEDDDR5 |= LEDPN5;
LEDDDR7 |= LEDPN7;
LEDDDR10 |= LEDPN10;
LEDDDR11 |= LEDPN11;
// set the 4 chr pins to off
LEDDDR12 &= ~LEDPN12;
LEDDDR9 &= ~LEDPN9;
LEDDDR8 &= ~LEDPN8;
LEDDDR6 &= ~LEDPN6;
}
int LED5461_print(char line, FILE *stream) {
if (line == '.' || line == ',') {
LED5461_decimal[LED5461_pos-1] = 1;
} else {
int outp = line - '0';
LED5461_display[LED5461_pos] = outp;
LED5461_pos++;
}
return 0;
}
void LED5461_home() {
LED5461_decimal[0] = 0; LED5461_decimal[1] = 0; LED5461_decimal[2] = 0; LED5461_decimal[3] = 0;
LED5461_pos = 0;
}
Here is an example using the lib:
#define F_CPU 14745600
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/io_328p.h"
#include "./5461AS.h"
int main() {
LED5461_start();
FILE LED5461_stream = FDEV_SETUP_STREAM(LED5461_print, 0, _FDEV_SETUP_WRITE);
LED5461_brightness = 500;
while (1) {
LED5461_home();
fprintf_P(&LED5461_stream, PSTR("12,34"));
delay_ms(1000);
LED5461_home();
fprintf_P(&LED5461_stream, PSTR("1,234"));
delay_ms(1000);
LED5461_home();
fprintf_P(&LED5461_stream, PSTR("1010"));
delay_ms(1000);
LED5461_home();
fprintf_P(&LED5461_stream, PSTR("9876"));
delay_ms(1000);
}
return 0;
}
|