Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronic Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Register Log in

[SOLVED] Multiplexed 7segment display simulation problem in proteus

Mithun_K_Das

Advanced Member level 3
Joined
Apr 24, 2010
Messages
849
Helped
23
Reputation
46
Reaction score
21
Trophy points
1,308
Location
Dhaka, Bangladesh, Bangladesh
Activity points
7,909
I had several 7segment based meters which works fine in hardware. Most of these are regular products, no display problem found yet in last 7yrs+.
Today, I was trying to make a simple simulation based on 7segment display in proteus 8.9. But I found that, it can not display 7segment properly.
Either it shows still non-digits or flickering. I tried changing timing for multiplexing. But can't find the problem.

Can anyone tell me whats wrong here? Again I'm mentioning that, it works in hardware with this 5ms refresh interval. Sometimes little adjustment may required.
It is not working properly in proteus only.

Here is the simplified code which I was testing.

Code:
unsigned short mask(int 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 0x82;
       case 7 : return 0xF8;
       case 8 : return 0x80;
       case 9 : return 0x90;
   }
}
unsigned short  portb_index;
unsigned int digit,number;
unsigned short portb_array[5];

void display_digits()
{
  PORTB = portb_array[portb_index];
  if(portb_index==3)
  {
     RC0_bit = 1;
     RC1_bit = 0;
     RC2_bit = 0;
     RC3_bit = 0;
  }
  if(portb_index==2)
  {
     RC0_bit = 0;
     RC1_bit = 1;
     RC2_bit = 0;
     RC3_bit = 0;
  }
  if(portb_index==1)
  {
     RC0_bit = 0;
     RC1_bit = 0;
     RC2_bit = 1;
     RC3_bit = 0;
  }
  if(portb_index==0)
  {
     RC0_bit = 0;
     RC1_bit = 0;
     RC2_bit = 0;
     RC3_bit = 1;
  }
   portb_index ++ ;
   Delay_ms(5);
   if (portb_index > 3)portb_index = 0;
}


 void Digit_seperation()
 {
     digit = (number / 1u) % 10u;
     portb_array[0] = mask(digit);
     digit = (number / 10u) % 10u;
     portb_array[1] = mask(digit);
     digit = (number / 100u) % 10u;
     portb_array[2] = mask(digit);
     digit = number / 1000u;
     portb_array[3] = mask(digit);
 }


void main()
{
  TRISA = 0xFF; // all input.
  TRISB = 0x00; // Set PORTB direction to be output
  TRISC = 0x00; // Set PORTB direction to be output
  PORTC = 0x00;
  PORTB = 0x00;
  ADCON1 = 0x00;// all analog in
  while(1)
  {

    number = 5432;
    Digit_seperation();
    display_digits();

  }//Endless loop;
}//End.



// end

And the proteus file:

- - - Updated - - -

This is happening most of the time.
Capture.PNG
 

Attachments


betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,110
Helped
4,674
Reputation
9,362
Reaction score
4,414
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
120,586
Ugh!
Please use a timer to set the multiplexing rate, it is the only way you will get the digits to have equal brightness. Ideally, use a timer to create an interrupt and cycle through the digits at each call to the ISR.

Why are you using that switch/case statement when a simple array would suffice and take up far less space, and more importantly a constant time to execute regardless of the index?

Brian.
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
46,758
Helped
13,880
Reputation
28,008
Reaction score
12,519
Trophy points
1,393
Location
Bochum, Germany
Activity points
272,893
1. Delay_ms() statement isn't simulated in real time. Your code has to be corrected for this fact.
2. Muxed LCD component in Proteus is working as a one shot with configurable pulse width. The parameter can be adjusted.
3. Your display_digits() procedure has a fault that might not show in real hardware. You need to disable the digit driver first, then write the new segment value, then enable the new digit.
 

Mithun_K_Das

Advanced Member level 3
Joined
Apr 24, 2010
Messages
849
Helped
23
Reputation
46
Reaction score
21
Trophy points
1,308
Location
Dhaka, Bangladesh, Bangladesh
Activity points
7,909
In main program I used timer. As it was not working properly, I simplified the code to check if there is any mistake in timer ISR. With timer ISR, it work fine in real hardware. But that same code in simulation can not display segment properly.

Switch-case issue: This code was first developed in around 2010. As it is not making any trouble so I did not changed later. If array consume less memory, I'll change to array.

Muxed LCD component: I tried changing the response time; Either it shows in flickering, or in non-digit. Even I've collected one ready file from libstock.com to check. It is also not displaying properly. I've attached the video here.
Also file is attached here:

- - - Updated - - -

The other simulation file in the last uploaded project file works.
 

Attachments


betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,110
Helped
4,674
Reputation
9,362
Reaction score
4,414
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
120,586
For clarification - are you using 7-segment LEDs or LCDs? They require completely different drive signals, the code and schematic are for LEDs but your text mentions "Muxed LCD component".

I can't verify your simulation, Proteus only runs under Windows.

Brian.
 

Mithun_K_Das

Advanced Member level 3
Joined
Apr 24, 2010
Messages
849
Helped
23
Reputation
46
Reaction score
21
Trophy points
1,308
Location
Dhaka, Bangladesh, Bangladesh
Activity points
7,909
Oh sorry, Muxed LCD component may be wrong. It should be LED for sevensegment. I copied from previous post of FVM.

Anyway, I solved this problem.

There was a timing problem for Data pins in interrupt ISR.

Finally modified code:
Code:
char segment_array[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6  F};//cmmon cathode_non dot

sbit digit0 at RC0_bit;
sbit digit1 at RC1_bit;
sbit digit2 at RC2_bit;
sbit digit3 at RC3_bit;

char digits[5];
void display_7segment(int number)
{
   digits[3]=number/1000u;
   digits[2]=(number/100u)%10u;
   digits[1]=(number/10u)%10u;
   digits[0]=(number/1u)%10u;
}

void InitTimer0()
{
  OPTION_REG     = 0x85;
  TMR0           = 100;
  INTCON         = 0xA0;
}

int position=0;
void Interrupt() iv 0x0004 ics ICS_AUTO
{
  if (TMR0IF_bit)
  {
    TMR0IF_bit   = 0;
    TMR0         = 100;
    
    digit0 = 1;
    digit1 = 1;
    digit2 = 1;
    digit3 = 1;
    if(position>3)position=0;
    
    if(position==1)PORTB = segment_array[digits[position]]+128; //dot point
    else PORTB = segment_array[digits[position]];
    
    if(position==3)
    {
        digit0 = 0;
        digit1 = 1;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==2)
    {
        digit0 = 1;
        digit1 = 0;
        digit2 = 1;
        digit3 = 1;
    }
    else if(position==1)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 0;
        digit3 = 1;
    }
    else if(position==0)
    {
        digit0 = 1;
        digit1 = 1;
        digit2 = 1;
        digit3 = 0;
    }
    position++;
  }
}



unsigned int cnt=0;
void main()
{
 TRISB=0x00;//all output
 TRISC=0x00;//all output
 PORTB=0x00;
 PORTC=0x00;//clear ports
 InitTimer0();//5ms timer
 while(1)
 {

    display_7segment(cnt);
    cnt++; Delay_ms(200);
    if(cnt>9999)cnt=0;
 }
}












//
- - - Updated - - -

If you have any further suggestion for this code to make it more professional please share. Thanks.
 

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
14,110
Helped
4,674
Reputation
9,362
Reaction score
4,414
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
120,586
Technically you shouldn't enable the GIE bit in INTCON at the same time as the interrupt itself but it wouldn't make any difference the performance in your program.

You can further simplify it by using an array for the digit drive signals as well and in real life you probably need to allow for some 'dead' time between digits, a brief period when all the segments are turned off before setting the next pattern, or you may see some 'ghosting'. A trick here is to combine the two suggestions, by turning all the digits off before changing the segments then turning the new digit on.

Brian.
 

Toggle Sidebar

Part and Inventory Search


Welcome to EDABoard.com

Sponsor

Sponsor

Design Fast


×
Top