0

could someone please help me? I wrote the code bellow, to run a digital clock, but when i simulate in proteus the led only blink and the display only show 00:00, and it never count. I used timer 0 and timer 1 to generate 1 sec of delay

ANy suggestion??

FUNCTIONS AND VARIABLES

 int display(int num);
 int clock_PIC();

    /*VARIAVEIS GLOBAIS*/
    char controlador = 0x01;
    int unidade, dezenas, centenas, milhares;

    char  segundos   = 0x00;
    char  minutos    = 0x00;
    char  horas      = 0x00;
    char  clck_cont  = 0x00;
    char flags_min = 0x00;
    char flags_hor = 0x00;

INTERRUPT (TIMER 0 AND TIMER 1)

void interrupt interrupcao ()
{
//    int a;
//    display(a);

    if(INTCONbits.TMR0IF)
        {           
            if(!digito_milhares && controlador == 1)
            {
                controlador    = 0x02;
                digito_unidade = 0x00;
                digito_dezenas  = 0x00;
                digito_centenas = 0x00;
                PORTC = 0x00;
                milhares = (horas%100)/10;
                digito_milhares = 0x01;
                PORTC = display(milhares);
            }//end if digito milhares


            else if(!digito_centenas && controlador == 2)
            {
                controlador    = 0x03;
                digito_unidade = 0x00;
                digito_dezenas  = 0x00;
                digito_milhares = 0x00;
                PORTC = 0x00;
                centenas = horas%10;
                digito_centenas = 0x01;
                PORTC = display(centenas);
            }//end if digito centenas


            else if(!digito_dezenas && controlador == 3)
            {
                controlador    = 0x04;
                digito_unidade = 0x00;
                digito_centenas = 0x00;
                digito_milhares = 0x00;
                PORTC = 0x00;
                dezenas = (minutos%100)/10;
                digito_dezenas = 0x01;
                PORTC = display(dezenas);
            }//end if digito dezenas


            else if(!digito_unidade && controlador == 4)
            {
                controlador    = 0x01;
                digito_dezenas  = 0x00;
                digito_centenas = 0x00;
                digito_milhares = 0x00;
                PORTC = 0x00;
                unidade = minutos%10;
                digito_unidade = 0x01;
                PORTC = display(unidade);
            }//end if digito unidade

            // clear the TMR0 interrupt flag
            INTCONbits.TMR0IF = 0x00;

        }//end if TMR0IF

    if(PIR1bits.TMR1IF)
    {
        LATBbits.LATB7 = ~ LATBbits.LATB7;

        clck_cont ++;

        if(clck_cont == 0x02)
        {
            clck_cont = 0x00;
            segundos++;

        }//end clck_cont 

        // clear the TMR1 interrupt flag
        PIR1bits.TMR1IF = 0x00;

        //TMR1H 11; 
        TMR1H = 0x0B;

        //TMR1L 220; 
        TMR1L = 0xDC;

    }//end TMR1IF

}//end interrupcao

MAIN FUNCTION

void main(void)
{

    PORTB = 0x4F;
    PORTC = 0x3F;

    /**
    TRISx registers
    */

    TRISB = 0x70;
    TRISC = 0x80;
    /**
    ANSELx registers
    */

    ANSELC = 0x00;
    ANSELB = 0x00;

    // SCS FOSC; IRCF 4MHz_HFINTOSC/4; IDLEN disabled; 
    OSCCON = 0x50;
    // PRISD enabled; SOSCGO disabled; MFIOSEL disabled; 
    OSCCON2 = 0x04;
    // INTSRC disabled; PLLEN disabled; TUN 0; 
    OSCTUNE = 0x00;


    // TMR0H 0; 
    TMR0H = 0x00;
    // TMR0L 6; 
    TMR0L = 0x06;
    // T0PS 1:16; T08BIT 8-bit; T0SE Increment_hi_lo; T0CS FOSC/4; TMR0ON enabled; PSA assigned; 
    T0CON = 0xD3;


    //T1GSS T1G_pin; TMR1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled; 
    T1GCON = 0x00;

    //TMR1H 11; 
    TMR1H = 0x0B;

    //TMR1L 220; 
    TMR1L = 0xDC;

    // Clearing IF flag before enabling the interrupt.
//    PIR1bits.TMR1IF = 0;

    // T1CKPS 1:8; T1OSCEN disabled; T1SYNC do_not_synchronize; TMR1CS FOSC/4; TMR1ON enabled; T1RD16 enabled; 
    T1CON = 0x37;

    INTCONbits.GIE = 1;     //Habilita a interrupcao global
    PIE1bits.TMR1IE = 1;    //Habilita a interrupcao do timer 1
    INTCONbits.TMR0IE = 1;  //Habilita a interrupcao do timer 0  
    INTCON2bits.nRBPU = 0;  //Habilita o pull up interno do port B

    while (1)
    {  
        clock_PIC();
    }//end while
}//end void

CLOCK FUNCTION

int clock_PIC()
{

    if (segundos > 59)
    {
        segundos = 0x00;
        minutos++;

        if(minutos > 59)
        {
            minutos = 0x00;
            horas++;

                    if (horas > 23)
                    {
                        horas = 0x00;

                    }//end horas

        }//end minutos

    }//end segundos

    if(!butt_minutos) flags_min = 0x01;
    if(!butt_horas) flags_hor = 0x01;

    if(butt_minutos && flags_min)
    {
        flags_min = 0x00;
        minutos++;
        if(minutos > 59) minutos = 0x00;
    }

    if(butt_horas && flags_hor)
    {
        flags_hor = 0x00;
        horas++;
        if(horas > 23) horas = 0x00;
    }

}//end clock_PIC

DISPLAY FUNCTION

int display(int num)
{
    int cathode;                               //armazena código BCD

// -- Vetor para o código BCD --
    int SEGMENTO[10] = {0x3F,                  //BCD zero   '0'
                        0x06,                  //BCD um     '1'
                        0x5B,                  //BCD dois   '2'
                        0x4F,                  //BCD três   '3'
                        0x66,                  //BCD quatro '4'
                        0x6D,                  //BCD cinco  '5'
                        0x7D,                  //BCD seis   '6'
                        0x07,                  //BCD sete   '7'
                        0x7F,                  //BCD oito   '8'
                        0x67};                 //BCD nove   '9'

    cathode = SEGMENTO[num];                   //para retornar o cathode

    return(cathode);                           //retorna o número BCD

} //end display
Barmar
  • 741,623
  • 53
  • 500
  • 612
Ntampata
  • 1
  • 1
  • Welcome to SO! I would try to reduce the size of the interrupt function: move the body of `interrupcao()` to another function and, when the interrupt rises, flag it. In main, call the function that you moved out from `interrupcao()`. – Mance Rayder Jun 29 '19 at 01:56
  • It is working .... – Ntampata Jun 29 '19 at 20:43

1 Answers1

0

I really don't know for the specific PIC you are using, but as a general rule in embedded systems, interrupts should consist of short concise code. The interrupt mechanism will call that code and it's expected to finish in a short time, as another interrupt may rise and be missed (even the one same ISR). So, a common practice is to do a little bit of the processing inside the ISR callback (for example, marking the interrupt as attended) and changing a flag marking that the interrupt was generated, and doing most of the work in main() or other function. This is not always possible, as this is somewhat like pooling instead of using a callback, but it's common for low-end microcontrollers.

Besides the code, that is large for an ISR, you should avoid calling other functions inside the interrupt callback, because of the overhead it adds. Also, in this particular case, you are using the modulus operator, %, that implies divisions: if the PIC does not have a hardware divider, it is a really slow operation.

What you have to do, is move out the code inside the ISR void interrupt interrupcao () to another function and leave only the code that must change register inside it, and flag that the interrupt was risen. Then check that flag inside the main loop and do the processing.


Another thing that used to mess up everything, when the interrupt callback was lengthy, is the space, physical memory, that was assigned to the function. Making it large made the code overflow to another interrupt space; but I doubt of this happening to you, as I've only seen it coding in assembly (the compiler will put the code in the right place, but I don't know how you are compiling ;)).

Mance Rayder
  • 353
  • 2
  • 10