c++ - 带 pic18f445k22 的 7 段显示数字时钟

标签 c++ c pic18 seven-segment-display

有人可以帮我吗? 我编写了下面的代码来运行数字时钟,但是当我在 proteus 中进行模拟时,LED 只闪烁,显示屏只显示 00:00,而且永远不会计数。我使用定时器 0 和定时器 1 来生成 1 秒的延迟

有什么建议吗?

函数和变量

 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;

中断(定时器0和定时器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

主要功能

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

时钟功能

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

显示功能

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

最佳答案

我真的不知道你正在使用的具体PIC,但作为嵌入式系统的一般规则,中断应该由简短的代码组成。中断机制将调用该代码,并且预计会在短时间内完成,因为另一个中断可能会出现并被错过(即使是同一个 ISR)。因此,常见的做法是在 ISR 回调内部进行一些处理(例如,将中断标记为已处理)并更改标记已生成中断的标志,并在 main() 中完成大部分工作。或其他功能。这并不总是可能的,因为这有点像池化而不是使用回调,但这对于低端微 Controller 来说很常见。

除了对于 ISR 来说较大的代码之外,您还应该避免在中断回调中调用其他函数,因为它会增加开销。此外,在这种特殊情况下,您正在使用模运算符 % ,这意味着除法:如果 PIC 没有硬件除法器,则操作速度非常慢。

您要做的就是移出 ISR void interrupt interrupcao () 内的代码到另一个函数,只留下必须更改其中寄存器的代码,并标记中断已发生。然后检查主循环内的该标志并进行处理。

<小时/>

当中断回调很长时,另一个曾经把一切搞乱的事情是分配给函数的空间,即物理内存。使其变大会使代码溢出到另一个中断空间;但我怀疑这种情况发生在你身上,因为我只看到它在汇编中编码(编译器会将代码放在正确的位置,但我不知道你是如何编译的;))。

关于c++ - 带 pic18f445k22 的 7 段显示数字时钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56814042/

相关文章:

c++ - 我正在尝试学习使用 SDL 制作游戏。我的书讲授 SDL1.2.3,但我无法让它在 Visual Studio 上运行。谁能帮忙?我的错误 :

c - 通过 fscanf() 读取的值未打印出来

c - 反转字符串时长度增加

c - 在 Microchip C18 中,为什么插入 NOP 会导致更大的代码?

port - PIC 18F 上 PORT 和 LATCH 的区别

c++ - 用构造函数初始化一个n维 vector 不好吗?

c++ - 如何创建对模板类执行操作的静态模板成员函数?

c++ - 当 unique_ptr 超出范围时,它如何不破坏/释放它指向的内存?

c - 有效地使一个 1 全为 1 但为 0 的 int 保持为 0

c - 强制 printf 使用两个字符