# Multiplexing 2-Seven Segment Displays using ARM 7

I am currently trying to control two seven segment displays from the same 7 pins (P0.0 - P0.6) of an ARM 7 micro-controller. I am first testing this on Proteus simulation software.

I am following the schematic from this 8051 multiplexing tutorial, however my 7 segment displays are connected from Port 0.0 to Port 0.6 and the two controlling transistors are connected at P0.7 and P0.8.

I am pretty sure that the seven-segment display and transistors from my simulation are connected correctly, and that the problem is arising from the following code. I have also tested my code to make sure I am displaying the correct numbers and that the transistor pins are configured as required.

The problem I am encountering is that both digits are being printed on both displays, instead of the first display showing 1 and the second display showing 2.

 #include <LPC21xx.h>
#define a 0x00000001
#define b 0x00000002
#define c 0x00000004
#define d 0x00000008
#define e  0x00000010
#define f 0x00000020
#define g 0x00000040
#define T2 0x00000080
#define T1 0x00000100

void small_delay (void);

int main (void)
{

PINSEL0 = 0;                        //Set P0.0 - P0.15 as GPIOS
PINSEL1 = 0;                        //Set P0.16 - P0.31 as GPIOS
IO0DIR  = 0xFFFFFFFF;               //Set all port0 pins as outputs

while (1){

IO0SET = e;      //displaying number 1
IO0SET = f;      //displaying number 1
IO0SET = T1;     //switching on first display
small_delay();   //calling short delay
IO0CLR = T1;     //clearing first display

IO0SET = a;       //displaying number 2
IO0SET = b;       //displaying number 2
IO0SET = g;       //displaying number 2
IO0SET = e;       //displaying number 2
IO0SET = d;       //displaying number 2
IO0SET = T2;      //switching on first display
small_delay();    //calling small delay
IO0CLR = T2;      //clearing second display
}

}

void small_delay (void)
{
unsigned int i, j;

for (i=0; i<10; i++)
{
//do nothing
}
}


This is what I am trying to achieve with the above code:

1. Send data 1 to both displays.
2. Enabling left seven segment by using IO0SET = T1;
3. Calling a short delay.
4. Disabling left seven segment by using IO0CLR = T1;
5. Sending data 2 to both displays.
6. Enabling right seven segment by using IO0SET = T2;
7. Calling a short delay.
8. Disabling right seven segment by using IO0CLR = T2;
9. Repeat.

Are there any flaws in this logic ? Any suggestions/ideas regarding what I am doing wrong in my coding would be greatly appreciated.

• Apart from the answer below, your "small delay" is very, very small. Unless the core runs at a Mhz or less. I suspect it'll have to be longer to allow decent propagation and latch-up in the real world. And you may need to make it volatile, so it doesn't get optimised out as code that, as you label correctly, does nothing. Or there may be built in delay functions? (You can make it volatile with a volatile ASM("NOP") or whatever your compiler suite's code words are to insert the ASM NOP command. – Asmyldof Feb 17 '17 at 16:13
• Hi, @Asmyldof, first off thanks for your contribution. As far as I know, there are no built in delay functions. I will increase the delay time as you suggest. – Rizzo Feb 17 '17 at 16:16

You're turning individual segments on, but never turning them off again, so the result is that you show a 1 and a 2 superimposed on both displays.

Change your IO0CLR = T1 and IO0CLR = T2 statements into IO0CLR = 0x000001FF to turn off all the segments as well as both common anodes. Then your outputs will be ready for the new segment patterns to be set up.

• Thanks for your insight on this matter. I see what I am doing wrong and have proceeded to clearing all segments and common anodes. However, as pointed out earlier, my delay is very small and the digits on the simulation are not being shown properly. I will then increase the delay accordingly. – Rizzo Feb 17 '17 at 16:22
• If you make the delay long enough while debugging, you'll see each display light up separately - that can make it easier to see exactly what's happening. – Finbarr Feb 17 '17 at 16:26

This is what I am trying to achieve with the above code:

there are a lot of such examples on the net for you to search through. All fairly easy to understand.

and works better as well.

here is my version:

//display the content of vRAM[8]
void _7seg_display(void) {
static unsigned char digit=0;                       //digit to be displayed

DIG_OFF(DIGs);                                      //turn all digits off
_7SEG_ON(_7seg_font[vRAM[digit]]);                  //display the digit
//DIG_ON(1<<digit);                                 //turn on the digit
switch (digit) {
case 0:
DIG_ON(DIG0);
break;
case 1:
DIG_ON(DIG1);
break;
case 2:
DIG_ON(DIG2);
break;
case 3:
DIG_ON(DIG3);
break;
case 4:
DIG_ON(DIG4);
break;
case 5:
DIG_ON(DIG5);
break;
case 6:
DIG_ON(DIG6);
break;
case 7:
DIG_ON(DIG7);
break;
}
digit+=1;                                           //increment the digit
if (digit==_7SEG_NUMBER) digit=0;                   //reset the digit
}


it is fairly simple in that

1. it is independent of hardware -> meaning that you can simply copy it into a new project and defines certain macros for that project / platform, recompile and it will work.

2. it follows a simple logic: it inhibits the current digit, puts new data on the segments, and then turn on the next digit.

3. the code can be called periodically through a timer interrupt or even in the main loop.

4. it supports up to 8 digits -> can be expanded to more if you want.

Again, the key is to make sure that you write your code independent of the hardware so you can re-use the code.

• Hi, thanks for your contribution. I see that your code is independent of hardware, however I have been wary whilst seeing other codes since most are not independent of hardware (from what I can gather). I will implement this with my coding accordingly. – Rizzo Feb 17 '17 at 16:25