PIC C, A Four Digit 7-Seg LED Display
// Program 5832_1.C (CCS PCM - PIC16F84)
//
// Illustrates how to interface with four 7-segment LEDs using an
// Allegro UCN5832A 32 bit shift register. Note that this is a sink
// device and inverts the data in the shift register.
//
// Note that we sell the UCN5832A, common anode 7-segment LED displays
// and 330 Ohm resistors. If you want a drawing showing the connection
// of the 5832 to the four 7-seg LEDs, please ask.
//
// Program assumes the least digit first and the pattern is shifted
// out least significant bit first. Decimal point is on most significant
// bit.
//
// This concept might be used with similar Allegro devices such as the
// 5841 (8-bit, sink) and 5818 (32-bit source).
//
// PIC16F84 UCN5832
//
// RB.3 -----------------------> DAT
// RB.2 -----------------------> CLK
// RB.1 -----------------------> STB
// RB.0 -----------------------> OE
//
// Routine displays the characters '0' - 'F' on least significant digit.
// Other digits are blanked. The message "HELP is displayed" and flashed
// a number of times.
//
// Illustrates how to display four decimal digits with leading
// zero suppression, sign plus three decimal digits and four hexadecimal
// digits.
//
// Illustrates how to insert a decimal point.
//
// Copyright, Peter H. Anderson, Baltimore, MD, Apr, '99
#case
#include <16F84.h>
#include <defs_f84.h>
#define MINUS 0x01 // display a minus sign
#define BLANK 0x00 // blanks LED
#define OE rb0
#define STB rb1
#define CLK rb2
#define DAT rb3
void convert_to_dec_patt_unsigned(long val, int *patts);
void convert_to_dec_patt_signed(signed long val, int *patts);
void convert_to_hex_patt(long val, int *patts);
void display(int *patts);
long pow_10(int n);
void out_8(int patt);
// delay routines
void delay_ms(long t);
void delay_10us(int t);
// note that the patts are declared globally as they can not be passed
// by reference. That is, pointers to const arrays are not permitted.
// a table used in deriving these patterns appears at the end of this
// program.
int const hex_digit_patts[16]=
// 0 1 2 3 4 5 6 7
{0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70,
// 8 9 A B C D E F
0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47};
int const help_patts[4] = {0x37, 0x4f, 0x0f, 0x67};
// H E L P
#define ARRAY_TECNIQUE // see note at function pow_10
void main(void)
{
int disp_patts[4], n;
signed long val;
TRISB = 0xf0; // lower nibble are outputs
STB = 0; CLK = 0; OE = 0;
// set STB to 0, CLK to 0 and Output disabled
// display 0 - F on least sig 7-seq. Others are balnked.
disp_patts[1] = BLANK; //BLANK;
disp_patts[2] = BLANK;
disp_patts[3] = BLANK;// most sig digit
for (n=0; n<0x10; n++)
{
disp_patts[0] = hex_digit_patts[n]; // least sig digit
display(disp_patts);
OE = 1; // output enable
delay_ms(1000);
}
// display "HELP"
for (n=0; n<4; n++)
{
disp_patts[n] = help_patts[3-n]; // output least sig digit first
}
display(disp_patts);
for (n=0; n<10; n++) // flash the message on and off ten times
{
OE = 0; // turn it off
delay_ms(100);
OE = 1; // turn it on
delay_ms(100);
}
// display 207 in decimal format with leading zero suppression
val = 207;
convert_to_dec_patt_unsigned(val, disp_patts);
display(disp_patts);
delay_ms(5000);
// display as signed plus 3 digits with leading zero suppression
val = -7;
convert_to_dec_patt_signed(val, disp_patts);
display(disp_patts);
delay_ms(5000);
// display a value in hexadecimal format, no leading zero suppression
val = 0x3f3c;
convert_to_hex_patt(val, disp_patts);
display(disp_patts);
delay_ms(5000);
// display 98.6
val = 986;
convert_to_dec_patt_unsigned(val, disp_patts);
// ele 3 is blank, ele 2 is 9, ele 1 is 8, ele 0 is 6
disp_patts[0] = disp_patts[0] | 0x80; // left hand dec point
display(disp_patts);
delay_ms(5000);
}
convert_to_dec_patt_unsigned(long val, int *patts)
// converts val to four digits and place corresponding hex digit patterns
// in patt[]
{
int n, suppress_zero = TRUE;
long x;
for (n=0; n<4; n++)
{
x = pow_10(3-n); // calculate 1000, 100, 10, 1
if ((val/x == 0) && (suppress_zero) && (n!=3))
{
patts[3-n] = BLANK; // leading zero suppression
}
else
{
suppress_zero = FALSE;
patts[3-n] = hex_digit_patts[val/x];
}
val = val%x;
}
}
convert_to_dec_patt_signed(signed long val, int *patts)
// patt[3] is for the sign, either MINUS or BLANK
// hex patterns for the three digits are paced in elements 2, 1 and 0
{
int n, suppress_zero=TRUE; // could have used a short for suppress_zero
long x;
if (val < 0)
{
patts[3] = MINUS;
}
else
{
patts[3] = BLANK;
}
val = -val; // convert to a positive number
for (n=0; n<3; n--)
{
x = pow_10(2-n); // compute 100, 10, 1
if ((val/x == 0) && (suppress_zero) && (n!=2))
{
patts[2-n] = BLANK;
}
else
{
suppress_zero = FALSE;
patts[2-n] = hex_digit_patts[val/x];
}
val = val%x;
}
}
void convert_to_hex_patt(int val, int *patts)
// converts to four nibbles and places corresponding hex patterns
// in patts[]
{
int n;
for(n=0; n<4; n++)
{
patts[n] = hex_digit_patts[val & 0x0f];
// patt[0] is least sig digit
val = val >> 4; // next nibble
}
}
long pow_10(int n)
// Note the multiply technique was done simply to see if it could be done.
// The array technique which uses an array is far more efficient.
#ifdef ARRAY_TECHNIQUE
{
long const v[4] = {1, 10, 100, 1000};
return v[n]
}
#else
{
long v=1;
while(n)
{
v = v * 10;
--n;
}
return(v);
}
#endif
void display(int *patts)
// outputs the 4 values in patts[], beginning with patts[0].
{
int n;
STB = 0; // be sure latch is isolated from shift register
CLK = 0;
for (n=0; n<4; n++)
{
out_8(patts[n]);
}
STB = 1; // transfer shift register to latch
STB = 0;
}
void out_8(int patt)
// shifts out an 8-bit pattern, least sign bit first
{
int n;
for (n=0; n<8; n++)
{
DAT = (patt>>7)&0x01;
CLK = 1;
CLK = 0;
patt = patt << 1;
}
}
// delay routines
void delay_10us(int t)
{
#asm
BCF STATUS, RP0
DELAY_10US_1:
CLRWDT
NOP
NOP
NOP
NOP
NOP
NOP
DECFSZ t, F
GOTO DELAY_10US_1
#endasm
}
void delay_ms(long t) // delays t millisecs
{
do
{
delay_10us(100);
} while(--t);
}
// The following was used in developing the values for hex_digit_patts[]
// and help_patts[]
#ifdef XXX
P7 P6 P5 P4 P3 P2 P1 P0
Char a b c d e f g HEX
0 1 1 1 1 1 1 0 $7E
1 0 1 1 0 0 0 0 $30
2 1 1 0 1 1 0 1 $6D
3 1 1 1 1 0 0 1 $7F
4 0 1 1 0 0 1 1 $33
5 1 0 1 1 0 1 1 $5B
6 1 0 1 1 1 1 1 $5f
7 1 1 1 0 0 0 0 $70
8 1 1 1 1 1 1 1 $7F
9 1 1 1 1 0 1 1 $7B
A 1 1 1 0 1 1 1 $77
B 0 0 1 1 1 1 1 $1F
C 1 0 0 1 1 1 0 $4E
D 0 1 1 1 1 0 1 $3D
E 1 0 0 1 1 1 1 $4F
F 1 0 0 0 1 1 1 $47
H 0 1 1 0 1 1 1 $37
E 1 0 0 1 1 1 1 $4F
L 0 0 0 1 1 1 1 $0F
P 1 1 0 0 1 1 1 $67
- 0 0 0 0 0 0 1 $01
blank 0 0 0 0 0 0 0 $00
#endif