hopefully it's obvious that such displays are multiplexed to minimize the use of pins. Multiplexed means that one digit is active at a time and each digit is repeatedly turned on quickly enough displayed just as tv screens were refreshed 60 times/sec
here's code for displays driven with shift registers and an interrupt on a Multi-function board.
// drive 7-seg displays on MultiFuction boardj
#include <TimerOne.h>
#include "seg7disp.h"
// -------------------------------------
// constants for multiplexed 7-segment display
#define Latch 4
#define Clock 7
#define Data 8
#define LED0 10
#define LED1 11
byte pins [] = { Latch, Clock, Data, LED0, LED1 };
// a d
// f b c e
// g g
// e c b f
// d h a
//
// h g f e d c b a
const byte SEGMENT_MAP_DIGIT[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90
};
const byte SEGMENT_MAP_DIGIT_F [] = {
0xC0, 0xCF, 0xA4, 0x86, 0x8B, 0x92, 0x90, 0xC7, 0x80, 0x82
};
const byte DISP_MAP [] = { 1, 2, 4, 8 };
#define N_DISP sizeof(DISP_MAP)
byte disp [N_DISP] = {SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF};
int flag;
// -----------------------------------------------------------------------------
// shift 16-bits from data into the shift register
void output (
uint16_t data)
{
digitalWrite (Latch, LOW);
for (unsigned i = 0; i < 16; i++, data <<= 1) {
digitalWrite (Data, 0 != (data & 0x8000));
digitalWrite (Clock, HIGH);
digitalWrite (Clock, LOW);
}
digitalWrite (Latch, HIGH);
}
// -----------------------------------------------------------------------------
// repeatedly display one digit
// lower 8-bits selects the digit
// upper 8-bits species the segments
void isr (void)
{
static byte idx = 0;
uint16_t val = (disp [idx] << 8) + DISP_MAP [idx];
output (val);
if (N_DISP <= ++idx)
idx = 0;
}
// -----------------------------------------------------------------------------
// update the value of each digit
void seg7segs (
int val,
byte segs )
{
for (int i = N_DISP-1; i >= 0; i--, val /= 2)
disp [i] = val & 1 ? segs : SEGMENT_OFF;
}
// -----------------------------------------------------------------------------
// update the value of each digit
void seg7disp (
int valX10,
int flip )
{
Serial.println (__func__);
int i;
if (flip) {
for (i = 0; i < (int)N_DISP; i++, valX10 /= 10)
disp [i] = SEGMENT_MAP_DIGIT_F [valX10 % 10];
// blank leading zeros
i = N_DISP-1;
while (SEGMENT_MAP_DIGIT [0] == disp [i])
disp [i--] = SEGMENT_OFF;
}
else {
for (i = N_DISP-1; i >= 0; i--, valX10 /= 10)
disp [i] = SEGMENT_MAP_DIGIT [valX10 % 10];
disp [N_DISP-2] &= SEGMENT_DEC; // decimal pt
// blank leading zeros
i = 0;
while (SEGMENT_MAP_DIGIT [0] == disp [i])
disp [i++] = SEGMENT_OFF;
}
}
// -----------------------------------------------------------------------------
// update the value of each digit
void seg7off (void)
{
Serial.println (__func__);
for (int i = N_DISP-1; i >= 0; i--)
disp [i] = SEGMENT_OFF;
}
void seg7on (void)
{
Serial.println (__func__);
for (int i = N_DISP-1; i >= 0; i--)
disp [i] = 0;
}
// -----------------------------------------------------------------------------
void seg7init (void)
{
Serial.println (__func__);
for (unsigned i = 0; i < sizeof(pins); i++) {
digitalWrite (pins [i], HIGH);
pinMode (pins [i], OUTPUT);
}
Timer1.initialize(5000);
Timer1.attachInterrupt (isr); // blinkLED to run every 0.15 seconds
}
-
higher level function, seg7disp(), translates the digits in an integer value into the index of SEGMENT_MAP_DIGIT [] for displaying that digit on a display
-
an interrupt service routine copies the segment display value along with another 8-bit value indicating which digit to turn on into a 16-bit value, calls output() to shift that 16-bit value into to shift registers and then increments the index indicating whichdigit to display
-
output() just clocks out the bits from the 16-bit value
-
an interrupt is used in the above to determine when to "refresh" a digit, but a timer could be used as well
-
you're circuits uses individual i/o pins to turn on/off each segment. you can use an array of pins #s and a loop that sets each pin using the segment value for each digit being displayed
-
first turn off the current display, turn on/off the segment pins, then turn on the display being refreshed
there should be resistors in series with each segment (not each display).
since those resistors will typically be smaller in value to make the segment brighter. look at the values used on the multifunction shield
write code to
- get a timer running at 50 hz (20 msec)
- sequentially turn on/off each digit using the timer
- sequence thru an array of differnt value for each display
- write a function that maps the value to segments