In this experiment, we are going to learn how to interface more than one 7-segment LED display to a PIC Port using multiplexing technique. We are going to interface a 4-digit common cathode seven segment display to our PIC board. The multiplexing circuit is already built up in the board using 4 transistors and few resistors (Read Make Your Own PIC Development Board). The basic idea of multiplexing is that all seven segment displays are connected to the microcontroller in parallel and the microcontroller alternately prints ones, tens, hundreds, and thousands digits, selecting one at a time. The switching among the digits is so fast that it gives an impression of simultaneous light emission.
Experimental Setup:
1. Connect RA0 through RA3 to 7-Segment Digit Select headers DG1, DG2, DG3, and DG4 using jumper wires.
2. Insert 7FR5641AS 4-Digit Seven Segment module in to its place on the board.
Software:
/*
* Project name:
4-Digit UP Counter with Four 7-Segment Display Multiplexing
* Copyright:
(c) Rajendra Bhatt, 2009.
* Description:
This code is an example of multiplexing 4 Seven Segment Displays.
* Test configuration:
MCU: PIC16F628A
The common cathode of four seven segment dispalys are
connected to RA0, RA1, RA2 and RA3
*/
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
} //case end
}
unsigned short i, DD0, DD1, DD2, DD3, NUM ;
void main() {
CMCON |= 7; // Disable Comparators
TRISB = 0x00; // Set PORTB direction to be output
PORTB = 0xff; // Turn OFF LEDs on PORTB
TRISA0_bit = 0; // RA.0 to RA3 Output
TRISA1_bit = 0;
TRISA2_bit = 0;
TRISA3_bit = 0;
TRISA4_bit = 1; // RA.4 is Input only
NUM = 0; // Initial Value of Counter
do {
DD0 = NUM%10; // Extract Ones Digit
DD0 = mask(DD0);
DD1 = (NUM/10)%10; // Extract Tens Digit
DD1 = mask(DD1);
DD2 = (NUM/100)%10; // Extract Hundreds Digit
DD2 = mask(DD2);
DD3 = (NUM/1000); // Extract Thousands Digit
DD3 = mask(DD3);
for (i = 0; i<=50; i++) {
PORTB = DD0;
RA0_bit = 1; // Select Ones Digit
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD1;
RA0_bit = 0;
RA1_bit = 1; // Select Tens Digit
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD2;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 1; // Select Hundreds Digit
RA3_bit = 0;
delay_ms(5);
PORTB = DD3;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 1; // Select Thousands Digit
delay_ms(5);
}
NUM = NUM + 1 ;
} while(1); // endless loop
}
Experimental Output Video:
Experimental Setup:
1. Connect RA0 through RA3 to 7-Segment Digit Select headers DG1, DG2, DG3, and DG4 using jumper wires.
2. Insert 7FR5641AS 4-Digit Seven Segment module in to its place on the board.
Software:
/*
* Project name:
4-Digit UP Counter with Four 7-Segment Display Multiplexing
* Copyright:
(c) Rajendra Bhatt, 2009.
* Description:
This code is an example of multiplexing 4 Seven Segment Displays.
* Test configuration:
MCU: PIC16F628A
The common cathode of four seven segment dispalys are
connected to RA0, RA1, RA2 and RA3
*/
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
} //case end
}
unsigned short i, DD0, DD1, DD2, DD3, NUM ;
void main() {
CMCON |= 7; // Disable Comparators
TRISB = 0x00; // Set PORTB direction to be output
PORTB = 0xff; // Turn OFF LEDs on PORTB
TRISA0_bit = 0; // RA.0 to RA3 Output
TRISA1_bit = 0;
TRISA2_bit = 0;
TRISA3_bit = 0;
TRISA4_bit = 1; // RA.4 is Input only
NUM = 0; // Initial Value of Counter
do {
DD0 = NUM%10; // Extract Ones Digit
DD0 = mask(DD0);
DD1 = (NUM/10)%10; // Extract Tens Digit
DD1 = mask(DD1);
DD2 = (NUM/100)%10; // Extract Hundreds Digit
DD2 = mask(DD2);
DD3 = (NUM/1000); // Extract Thousands Digit
DD3 = mask(DD3);
for (i = 0; i<=50; i++) {
PORTB = DD0;
RA0_bit = 1; // Select Ones Digit
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD1;
RA0_bit = 0;
RA1_bit = 1; // Select Tens Digit
RA2_bit = 0;
RA3_bit = 0;
delay_ms(5);
PORTB = DD2;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 1; // Select Hundreds Digit
RA3_bit = 0;
delay_ms(5);
PORTB = DD3;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 1; // Select Thousands Digit
delay_ms(5);
}
NUM = NUM + 1 ;
} while(1); // endless loop
}
Hi Raj this project is very helpfull for me in stepping into programming BCD 7 segment project .I manage to run this code well on my board, thanks a lot. Raj, i am also looking to apply timers/interrupt concept to run the same project, could you please post any codes on for this projects applying timers/interrupts?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteI built a dev board based on your posting but my 4 7-segment leds show 4 zero's and counts to 255 then resets and starts over.... any idea?
ReplyDeleteThis is because the variable NUM is defined as unsigned short (which is 8-bit), so it can hold values only up to 255. Try replacing
ReplyDeleteunsigned short i, DD0, DD1, DD2, DD3, NUM ;
with
unsigned short i, DD0, DD1, DD2, DD3;
int NUM;
and see what happens.
How to drive only using MPLAB assembly code?
ReplyDeleteHello RAJ
ReplyDeleteCan you please tell me what changes are to be made in above program while using a common anode multiplexed seven segment display?
For common anode display, first you need to make some changes in the circuit (which I hope you would be able to do). Next you have to redefine the return values in the mask() function. Here are the changes:
ReplyDeleteunsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0xC0;
case 1 : return 0xF9;
case 2 : return 0xA4;
case 3 : return 0xB0;
case 4 : return 0x99;
case 5 : return 0x92;
case 6 : return 0x7D;
case 7 : return 0x82;
case 8 : return 0x80;
case 9 : return 0x90;
} //case end
}
Thanks for telling changes in software. In hardware, I used NPN transistors to switch all segments of the seven segment Display and I connected the selector pins directly to PORTA pins. Can you please tell me whether I changed my hardware correctly or there are to be some further modifications in the hardware?
ReplyDeleteThanks in anticipation.
Sorry, I have made mistake with number 6 & 7. The correct numbers for Common Anode are
ReplyDeleteswitch (num) {
case 0 : return 0xC0;
case 1 : return 0xF9;
case 2 : return 0xA4;
case 3 : return 0xB0;
case 4 : return 0x99;
case 5 : return 0x92;
case 6 : return 0x82;
case 7 : return 0xF8;
case 8 : return 0x80;
case 9 : return 0x90;
} //case end