4 digit up counter for seven segment

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
Hi,

I have PIC18F45K80. I am using MPLABX 5.40 and XC8 2.30.

1602239277652.png

I want to make 4 digit up counter using seven segment display Here is my plan to make counter (0-9999)

1602238929397.png

any help would be appreciated
 

jpanhalt

Joined Jan 18, 2008
11,087
Your flow chart makes no sense:

1602239534805.png

1) You have decisions with only one choice indicated. What if answer is "no?"
2) You have two "no" decisions running each other and no circuit breaker for that impasse.
3) How are you planning to convert a binary value into a 7-segment display decimal value?
 

MrChips

Joined Oct 2, 2009
30,706
You have chosen an approach that makes no sense.
Here is how I would do it.

Convert N (binary) to four BCD (binary-coded decimal) digits, D3, D2, D1, D0.
Display D3-D0.

Edit: John beats me to it.
 

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I have written code that display digit 0 to 5 on one display
Look up table

1602257168641.png


Program display digit 0 to 5

Code:
#define _XTAL_FREQ 8000000
#include <xc.h>
// PIC18F45K80 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1L
#pragma config RETEN = OFF      // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = HIGH   // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF       // Extended Instruction Set (Enabled)
// CONFIG1H
#pragma config FOSC = INTIO2    // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF     // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF     // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS  // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576  // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTB    // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF        // Code Protect 00800-01FFF (Disabled)
#pragma config CP1 = OFF        // Code Protect 02000-03FFF (Disabled)
#pragma config CP2 = OFF        // Code Protect 04000-05FFF (Disabled)
#pragma config CP3 = OFF        // Code Protect 06000-07FFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF        // Code Protect Boot (Disabled)
#pragma config CPD = OFF        // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF       // Table Write Protect 00800-01FFF (Disabled)
#pragma config WRT1 = OFF       // Table Write Protect 02000-03FFF (Disabled)
#pragma config WRT2 = OFF       // Table Write Protect 04000-05FFF (Disabled)
#pragma config WRT3 = OFF       // Table Write Protect 06000-07FFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF       // Config. Write Protect (Disabled)
#pragma config WRTB = OFF       // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF       // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protect 00800-01FFF (Disabled)
#pragma config EBTR1 = OFF      // Table Read Protect 02000-03FFF (Disabled)
#pragma config EBTR2 = OFF      // Table Read Protect 04000-05FFF (Disabled)
#pragma config EBTR3 = OFF      // Table Read Protect 06000-07FFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF      // Table Read Protect Boot (Disabled)

#define S1            LATBbits.LATB0
#define S2            LATBbits.LATB1
#define S3            LATBbits.LATB2
#define S4            LATBbits.LATB3

// Initialize the device
void Port_pins_Initialized (void)
{
    LATA = LATB = LATC = LATD = LATE =  0; // set all to 0

    TRISA = 0b0000000;// all are output, Unused
    TRISB = 0b0000000;// control signal S1, S2, S3, S4 (0-3))
    TRISC = 0b0000000;// All are output, Unused
    TRISD = 0b0000000;//  segment board connected
    TRISE = 0b0000000;// All are output, Unused

    ANCON0 = 0; // digital port
    ANCON1 = 0; // digital port
    CM1CON = 0; // Comparator off
    CM2CON = 0; // Comparator off
    ADCON0 = 0; // A/D conversion Disabled
}

void main(void)  // main program start
{
   Port_pins_Initialized (); //// Initialize the device
 
    S1 = 1;    S2 = 1;     S3 = 1;    S4 = 1; // select all
    
    while(1)  //Run forever
    {
        S1 = 1; S2=S3=S4 =0; // select only  1st segment
        LATD = 0x3F;         // Display 0
        __delay_ms(1000);    // Wait 1 seconds
      
        LATD = 0x06;          // Display 1
        __delay_ms(1000);     // Wait 1 seconds
      
        LATD = 0x5B;         // Display 2
        __delay_ms(1000);    // Wait 1 seconds
        
        LATD = 0x4F;           // Display 3
        __delay_ms(1000);// Wait 1 seconds
        
        LATD = 0x66;           // Display 4
        __delay_ms(1000);// Wait 1 seconds
        
        LATD = 0x6D;           // Display 5
        __delay_ms(1000);// Wait 1 seconds
      }
    
    return ;
}
IMG_20201009_205839.jpg
 

jpanhalt

Joined Jan 18, 2008
11,087
Good to see it works for a single digit. I second a next step to show different digits. Maybe 60 would be a place to start.

Edit: Make that 6.0 ;)
 
Last edited:

Thread Starter

Djsarakar

Joined Jul 26, 2020
489
I think nested for loop will use to display two digit UP counter. I am not good at flow chart, I am showing my idea that should be work

1602271073872.png
 

jpanhalt

Joined Jan 18, 2008
11,087
Isn't this step going to present a problem printing any value >9? How about 6.0?

1602272023131.png

Try it and see what you can print. Remember, in real use, this print "subroutine" will receive any number within its range. If the number is out of range, do you want to let your program get stuck in that loop?

Edit: spelling
 
Last edited:
You can approach the problem archaicall by counting in characters. Yuk.

Batter is to use integers so they can easily be incremented and decremented.

You then have a "display" with a few properties.
e.g.
leading zero blanking.
Decimal point placement.
Brightness
the blink property for overrange.
"OL" for overload
SIGN if needed. "-" if negative.

Possibly a few others, You could essentially develop a generic BCD display, but as your writing consider the later options.
e.g. DISPLAY("12.4f");


If your multiplexing the display there are a few tricks:
one is interdigit-blanking
Without it, the previous digit ghosts. You have to completely turn off a digit and then set the value and then enable it again.
That interval i the interdigit blanking.
 
Last edited:

MrChips

Joined Oct 2, 2009
30,706
Suppose that you have a 4-digit number 1234.
Can you display "1" on the first 7-segment LED display (the one on the left)?
 

jpanhalt

Joined Jan 18, 2008
11,087
There are multiple ways to do it depending on the number of decimal digits. It is quite easy with just 2 or 3 decimal digits. Four decimal digits is 14-bit binary. The methods I have seen are for 16-bit or 17-bit binary. The latter will give a full 5-digit decimal. The former will give 5-digit decimal and up to only 65536. If you search on it, RADIX conversion is one term you can use. BIN2BCD or BIN2ASCII are alternative search terms.

As I use Assembly, the methods I use are in Assembly. Here is a link to 16-bit Assembly: http://www.piclist.com/techref/microchip/math/radix/b2bu-16b5d.htm
The 1's, 10's, 100's, and 1000's correspond to your S1,S2,..S4, respectively. Code in C for 17-bit is here: http://www.piclist.com/techref/microchip/math/radix/b2bu-17b5d.htm

The value in the 1's, 10's, etc. registers are what you can enter into your jump table to get the appropriate 7-segment display output.

As with many things, there is a trade off between lines of code and speed. Some short programs take lots of time. The links in PICList are relatively short and quite fast compared to other methods.
 

MrChips

Joined Oct 2, 2009
30,706
Back at post #3 I said:

Convert N (binary) to four BCD (binary-coded decimal) digits, D3, D2, D1, D0.
Display D3-D0.

These are two separate tasks. Do them one at a time. Do the second one first. This will allow you to test the first task.

In other words, display "1234" on the seven-segment displays.
If you can display "1" on the first (MSD) display then you are "almost" finished with task 2.
 

jpanhalt

Joined Jan 18, 2008
11,087
I interpret the title, "4 digit up counter," to mean you do not want to enter individual decimal numbers, such as 1,2,3, and 4, but rather you want to count up from 0 to 1000 or more. One could write a relatively simple routine to detect "9" in the 1's digit ("S1") and create carry to the next digit and so forth. That would have a limited use.

Based on your earlier posts, I assumed you had a counter based on one of the timers and wanted to print at various times the result of such a count. Your display will accomodate 0x270F (d.9999). Unless you want to show "270F" (i.e., binary to hex ),* or count from 0 to "n" each time, you will need to convert binary to BCD. As mentioned, going from 8-bit binary to BCD is quite easy and quick. But, going from 16-bit to BCD is a little more complex. Nevertheless, the result will be a useful subroutine for the future, rather than a single-purpose count-up routine.

*There are times I actually do that when I want only to view a register's contents for troubleshooting. Your display can be used to show hex or decimal.
 

MrChips

Joined Oct 2, 2009
30,706
@jpanhalt makes a very good point.

Once you have been able to show "1234" on the display we will move on to showing hexadecimal values on the display, for example, "12AB"
 

djsfantasi

Joined Apr 11, 2010
9,156
Testing counter values from 0 - 9999 where the counter increments every second will take almost 7 days to complete!

Your content value can be treated as either binary or decimal. If you think of it as decimal, a few lines of code can convert it into the equivalent digits. Then, display those digits. May not be efficient, but should work for your test.

Code:
int counter=-1;
int temp;
byte digits[]={0,0,0,0};
// . . .
counter++
temp=counter;
for (int i=0; i<4; i ++) {
digit[i] = temp % 10;
temp = temp /10;
}
 

JohnInTX

Joined Jun 26, 2012
4,787
Your content value can be treated as either binary or decimal. If you think of it as decimal, a few lines of code can convert it into the equivalent digits. Then, display those digits. May not be efficient, but should work for your test.
Code:
int counter=-1;
int temp;
byte digits[]={0,0,0,0};
// . . .
counter++
temp=counter;
for (int i=0; i<4; i ++) {
digit[i] = temp % 10;
temp = temp /10;
}
That method is as good as any but your digits are backwards. This will fix it.
C:
temp=counter;
i = 4;
do{
  i--;
  digits[i] = temp % 10;
  temp = temp /10;
}while(i);
Regards,
J

EDIT: You could argue that the order does not matter since you need to process those digits as indexes into the segment decoder anyway. Either way, the MOD/DIV method solves the problem.
 

MrChips

Joined Oct 2, 2009
30,706
Forget the idea of a 4-digit counter going from 0 to 9999. This is not important. The solution is a general solution for all applications.

Do as I said. Show "1" in the leftmost digit.

Edit: You fellas are jumping the gun. TS needs to learn how to put digits out to the display first.
 
Top