Hot!7 segment display driving

Page: 123 > Showing page 1 of 3
Author
john_ive
Junior Member
  • Total Posts : 106
  • Reward points : 0
  • Joined: 2017/05/22 22:22:08
  • Location: 0
  • Status: offline
2018/09/15 19:48:25 (permalink)
0

7 segment display driving


 
#include <xc.h>
#define    XTAL_FREQ    20MHZ        /* Crystal frequency in MHz */
#include "delay.h"
#include "eeprom.h"

// CONFIG1H
#pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = ON       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 3         // Brown Out Reset Voltage bits (Minimum setting)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)


#define zero 0X40
#define one 0Xf9
#define two 0X24
#define three 0X30
#define four 0X19
#define five 0X12
#define six 0X02
#define seven 0XF8
#define eight 0X00
#define nine 0X10


#define segment1 PORTDbits.RD2
#define segment2 PORTDbits.RD3
#define segment3 PORTDbits.RD4
#define segment4 PORTDbits.RD5

int first_digit;
int tm1_change_timer, run_digit;
int temp1_counter, temp2_counter, temp3_counter, temp4_counter, temp5_counter, temp6_counter;

void one_display() {//1st digit
    switch (first_digit) {
        case 0:
            PORTB = zero;
            break;
        case 1:
            PORTB = one;
            break;
        case 2:
            PORTB = two;
            break;
        case 3:
            PORTB = three;
            break;
        case 4:
            PORTB = four;
            break;
        case 5:
            PORTB = five;
            break;
        case 6:
            PORTB = six;
            break;
        case 7:
            PORTB = seven;
            break;
        case 8:
            PORTB = eight;
            break;
        case 9:
            PORTB = nine;
            break;
        default:
            PORTB = zero;
            break;
    }
}

void System_init(void) {

    TRISA = 0b00000000;
    PORTA = 0b00000000;

    ADCON1 = 0XFF;
    CMCON = 0X07;

    TRISB = 0b00000000;
    PORTB = 0b11111111;

    TRISC = 0b00000000;
    PORTC = 0b11111111;

    TRISD = 0b00000000;
    PORTD = 0b11111111;

    TRISE = 0b00000111;
    PORTE = 0b00000111;
}

/**************************************************************
                    Main Program
 **************************************************************/


void main(void) {

    System_init();
    ee_init(); //EEPROM initialize


    while (1) {
        run_digit++;
        DelayMs(100);

        temp1_counter = run_digit / 1000;
        temp2_counter = run_digit % 1000;

        temp3_counter = temp2_counter / 100;
        temp4_counter = temp2_counter % 100;

        temp5_counter = temp4_counter / 10;
        temp6_counter = temp4_counter % 10;

        segment1 = 0;
        segment2 = 1;
        segment3 = 1;
        segment4 = 1;
        first_digit = temp1_counter;
        one_display();
        DelayMs(1);

        segment1 = 1;
        segment2 = 0;
        segment3 = 1;
        segment4 = 1;

        first_digit = temp3_counter;
        one_display();
        DelayMs(1);

        segment1 = 1;
        segment2 = 1;
        segment3 = 0;
        segment4 = 1;

        first_digit = temp5_counter;
        one_display();
        DelayMs(1);

        segment1 = 1;
        segment2 = 1;
        segment3 = 1;
        segment4 = 0;

        first_digit = temp6_counter;
        one_display();
        DelayMs(1);

        ee_write(1, 1);
        ee_write(2, 2);
        ee_write(3, 3);
    }

}


 

 
For displaying the values tried to use 7 SEGMENT display instead of LCD.When tried to display the value,first 3 digit are not showing properly it blinking...
I bought  the 7 SEGMENT display from online its common anode....
Connected the display board  directly to pic controller on PORTB and PORTD.
I have to store the datas in EEPROM,so I tired with simple values...
Like EEPROM operation,I have to do lot of operations,while executing the display will not show the correctly
 
I dono how to how to drive the display.Please help to solve this issue
 
post edited by john_ive - 2018/09/15 19:52:19

Attached Image(s)

#1

40 Replies Related Threads

    jtemples
    Super Member
    • Total Posts : 11006
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: 7 segment display driving 2018/09/15 19:57:04 (permalink)
    0
    One issue is you're writing to PORT instead of LAT with your segment* values.
    #2
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 20:16:31 (permalink)
    0
    As jtemples said.
    It doesn't matter when you write the whole port, as you are doing for PORTB in the one_display() function,
    but it DOES matter when you twiddle bits, as for the "segment#" bits.
    Change:
    #define segment1 PORTDbits.RD2
    #define segment2 PORTDbits.RD3
    #define segment3 PORTDbits.RD4
    #define segment4 PORTDbits.RD5

    to

    #define segment1 LATDbits.LATD2
    #define segment2 LATDbits.LATD3
    #define segment3 LATDbits.LATD4
    #define segment4 LATDbits.LATD5



     
    Also, your code will be more efficient => run faster if you use the correct size variables.
    e.g. There's no need for "first_digit" to be an "int". Change it to "unsigned char" for much more efficient code.
    That function could be even faster if you just created a 10 element array in RAM populated with your values, rather than using  a switch/case block.
     
     
    post edited by qhb - 2018/09/15 20:21:49
    #3
    jtemples
    Super Member
    • Total Posts : 11006
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: 7 segment display driving 2018/09/15 20:28:38 (permalink)
    0
    It doesn't matter when you write the whole port, as you are doing for PORTB

     
    ...but it's a bad habit that should be avoided.
    #4
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 20:40:18 (permalink)
    0
    Agree. Get into the habit of "Write to LAT, read from PORT." :)
    #5
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 21:03:01 (permalink)
    0
    Also, I'd drop including "Delay.h" (which is an oldC18 compatible library), and change:
    DelayMs(1);

    to
    __delay_ms(1);

     
    #6
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 21:11:46 (permalink)
    +1 (1)
    john_ive
    When tried to display the value,first 3 digit are not showing properly it blinking...

    That will be because you are only energising the first three digits for one millisecond, then you are energising the fourth digit for 1 millisecond plus the time it takes to write three bytes to EEPROM, which will be considerably longer than 1ms.
     
    I would suggest extending the digit delay to 10ms.
    That would give you a 40ms loop time (if the eep writing wasn't there), which would be 25 Hz, which is still fast enough to not see flickering.
     

    Like EEPROM operation,I have to do lot of operations,while executing the display will not show the correctly

    If you need to run some slow code, then you should do the LED driving inside a timer interrupt instead.
     
    #7
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/15 21:13:07 (permalink)
    0
    qhb
    As jtemples said.
    It doesn't matter when you write the whole port, as you are doing for PORTB in the one_display() function,
    but it DOES matter when you twiddle bits, as for the "segment#" bits.
    Change:
    #define segment1 PORTDbits.RD2
    #define segment2 PORTDbits.RD3
    #define segment3 PORTDbits.RD4
    #define segment4 PORTDbits.RD5

    to

    #define segment1 LATDbits.LATD2
    #define segment2 LATDbits.LATD3
    #define segment3 LATDbits.LATD4
    #define segment4 LATDbits.LATD5



     
    Also, your code will be more efficient => run faster if you use the correct size variables.
    e.g. There's no need for "first_digit" to be an "int". Change it to "unsigned char" for much more efficient code.
    That function could be even faster if you just created a 10 element array in RAM populated with your values, rather than using  a switch/case block.
     
     





     
    Changed everything as per your advice but facing the same issue,the first three digits are blinking
    #8
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 21:14:54 (permalink)
    +1 (1)
    Check my most recent post.
     
    #9
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/15 21:27:43 (permalink)
    0

     

    #define    MHZ    *1000L            /* number of kHz in a MHz */
    #define    KHZ    *1            /* number of kHz in a kHz */

    #if    XTAL_FREQ == 20MHZ

        #define    DelayUs(x)    { unsigned int _dcnt; \
            _dcnt = (x)/3; \
            while(--_dcnt != 0) \
        continue; }

    #elif XTAL_FREQ == 16MHZ

        #define    DelayUs(x)    { unsigned int _dcnt; \
            _dcnt = (x)/3.75; \
            while(--_dcnt != 0) \
        continue; }

    #elif XTAL_FREQ == 8MHZ

        #define    DelayUs(x)    { unsigned int _dcnt; \
            _dcnt = (x)/7.5; \
            while(--_dcnt != 0) \
        continue; }

    #elif XTAL_FREQ == 4MHZ

        #define    DelayUs(x)    { unsigned int _dcnt; \
            _dcnt = (x)/15; \
            while(--_dcnt != 0) \
        continue; }

    #else
        #error Please define XTAL_FREQ - 20MHZ/16MHZ/8MHZ/4MHZ
    #endif

    void DelayMs(unsigned int cnt){
        do {
            DelayUs(1000);
        } while(--cnt);
    }
     

     
    This my delay code which is used for every delay operation
    #10
    jtemples
    Super Member
    • Total Posts : 11006
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: 7 segment display driving 2018/09/15 21:29:23 (permalink)
    +1 (1)
    Not related to your issue, but writing to EEPROM ~10 times/second isn't a good idea.  That would probably destroy it in 24 hours or so.
    post edited by jtemples - 2018/09/15 23:09:33
    #11
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/15 21:35:59 (permalink)
    0
    john_ive
    ...
    This my delay code which is used for every delay operation

    And is totally pointless when XC8 has a more reliable routine already built in, which is what I suggested you use.
     
    #12
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/16 01:39:05 (permalink)
    0
    qhb
    john_ive
    When tried to display the value,first 3 digit are not showing properly it blinking...

    That will be because you are only energising the first three digits for one millisecond, then you are energising the fourth digit for 1 millisecond plus the time it takes to write three bytes to EEPROM, which will be considerably longer than 1ms.
     
    I would suggest extending the digit delay to 10ms.
    That would give you a 40ms loop time (if the eep writing wasn't there), which would be 25 Hz, which is still fast enough to not see flickering.
     

    Like EEPROM operation,I have to do lot of operations,while executing the display will not show the correctly

    If you need to run some slow code, then you should do the LED driving inside a timer interrupt instead.
     





     
    I tried it with previous discussion

    TMR2IE = 1; //Enable timer interrupt bit in PIE1 register
        GIE = 1; //Enable Global Interrupt
        PEIE = 1; //Enable the Peripheral Interrupt

        T2CON = 0b01001110;
        TMR2 = 0;
        PR2 = 124;

     
    but facing the same problem...
    have to change something in timer function too..?
    #13
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/16 01:43:34 (permalink)
    0
    You just showed some code to setup the timer interrupt.
    What did you put in the interrupt service?
     
    #14
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/16 01:52:01 (permalink)
    0

    void interrupt isr(void) {
        tm1_count++;
        if (tm1_count == 1) {
            tm1_count = 0;
            segment1 = 0;
            segment2 = 1;
            segment3 = 1;
            segment4 = 1;

            LATB = displ[temp1_counter];
            DelayMs(1);

            segment1 = 1;
            segment2 = 0;
            segment3 = 1;
            segment4 = 1;
            LATB = displ[temp3_counter];
            DelayMs(1);

            segment1 = 1;
            segment2 = 1;
            segment3 = 0;
            segment4 = 1;
            LATB = displ[temp5_counter];
            DelayMs(1);

            segment1 = 1;
            segment2 = 1;
            segment3 = 1;
            segment4 = 0;
            LATB = displ[temp6_counter];
            DelayMs(1);
        }
        TMR2IF = 0;
    }

    void System_init(void) {

        TRISA = 0b00000000;
        PORTA = 0b00000000;

        ADCON1 = 0XFF;
        CMCON = 0X07;

        TRISB = 0b00000000;
        PORTB = 0b11111111;

        TRISC = 0b00000000;
        PORTC = 0b11111111;

        TRISD = 0b00000000;
        PORTD = 0b11111111;

        TRISE = 0b00000111;
        PORTE = 0b00000111;

        TMR2IE = 1; //Enable timer interrupt bit in PIE1 register
        GIE = 1; //Enable Global Interrupt
        PEIE = 1; //Enable the Peripheral Interrupt

        T2CON = 0b01001110;
        TMR2 = 0;
        PR2 = 124;
    }
    void main(void) {

        System_init();
        ee_init(); //EEPROM initialize


        while (1) {
            run_digit++;
            DelayMs(100);
            temp1_counter = run_digit / 1000;
            temp2_counter = run_digit % 1000;

            temp3_counter = temp2_counter / 100;
            temp4_counter = temp2_counter % 100;

            temp5_counter = temp4_counter / 10;
            temp6_counter = temp4_counter % 10;

            ee_write(1, 1);
            ee_write(2, 2);
            ee_write(3, 3);

        }

    }

    #15
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/16 02:04:55 (permalink)
    0
    Never ever put a time delay inside an interrupt service.
    If you think you should, you are approaching it the wrong way.
    Try this:

    void interrupt isr(void) {
        static unsigned char phase=0;

        TMR2IF = 0;
        switch (phase)
        {
            case 0:
                segment1 = 0;
                segment2 = 1;
                segment3 = 1;
                segment4 = 1;
                LATB = displ[temp1_counter];
                break;
            case 1:
                segment1 = 1;
                segment2 = 0;
                segment3 = 1;
                segment4 = 1;
                LATB = displ[temp3_counter];
                break;
            case 2:
                segment1 = 1;
                segment2 = 1;
                segment3 = 0;
                segment4 = 1;
                LATB = displ[temp5_counter];
                break;

            default:
                segment1 = 1;
                segment2 = 1;
                segment3 = 1;
                segment4 = 0;
                LATB = displ[temp6_counter];
        }
        phase = ++phase & 3;    //count through 0, 1, 2, & 3
    }

     
     
     
    #16
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/16 02:26:24 (permalink)
    0
    qhb
    Never ever put a time delay inside an interrupt service.
    If you think you should, you are approaching it the wrong way.
    Try this:

     
    void interrupt isr(void) {
        static unsigned char phase=0;

        TMR2IF = 0;
        switch (phase)
        {
            case 0:
                segment1 = 0;
                segment2 = 1;
                segment3 = 1;
                segment4 = 1;
                LATB = displ[temp1_counter];
                break;
            case 1:
                segment1 = 1;
                segment2 = 0;
                segment3 = 1;
                segment4 = 1;
                LATB = displ[temp3_counter];
                break;
            case 2:
                segment1 = 1;
                segment2 = 1;
                segment3 = 0;
                segment4 = 1;
                LATB = displ[temp5_counter];
                break;

            default:
                segment1 = 1;
                segment2 = 1;
                segment3 = 1;
                segment4 = 0;
                LATB = displ[temp6_counter];
        }
        phase = ++phase & 3;    //count through 0, 1, 2, & 3
    }

     
     
     



    It working fine thank you
    Like to use TIMER0 for display operation and TIMER2 for clock purpose.
    Is it correct to use..?
    #17
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/16 02:51:34 (permalink)
    0
    It's usually cleaner to use one timer for both purposes.
    Otherwise you could have synchronisation issues between the two timers.
    Just use another variable to count enough timer2 interrupts, for one second.
    #18
    john_ive
    Junior Member
    • Total Posts : 106
    • Reward points : 0
    • Joined: 2017/05/22 22:22:08
    • Location: 0
    • Status: offline
    Re: 7 segment display driving 2018/09/16 03:02:56 (permalink)
    0
    qhb
    It's usually cleaner to use one timer for both purposes.
    Otherwise you could have synchronisation issues between the two timers.
    Just use another variable to count enough timer2 interrupts, for one second.





     
    I tried like that the display is still blinking.So i changed the PR2 value to 50 then the blinking is stopped...
    But I need PR2 as 125 for timer operation...
     
    So i choose another timer...
    #19
    qhb
    Superb Member
    • Total Posts : 7535
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: 7 segment display driving 2018/09/16 03:10:53 (permalink)
    0
    Vague descriptions like that make it difficult to help you.
    If you show the actual code you used, I'm sure I could show how to make it work with one timer.
     
    #20
    Page: 123 > Showing page 1 of 3
    Jump to:
    © 2018 APG vNext Commercial Version 4.5