1

我正在尝试使用 PIC18F24J10 开始一个项目。尝试为此使用 SDCC。在这一点上,我已经将我的代码简化为只是试图确定正在发生的事情,因为我已经看到了一段时间的奇怪行为并且在我弄清楚发生了什么之前无法真正继续。不确定这是否是我目前唯一的问题,但我不知道为什么会这样。定时器中断触发,加上#defined for 循环会导致 PORTC 上的 LED 每秒闪烁两次。如果我只是做一个 PORTC=0xFF 和 PORTC=0 这工作正常。但是当我试图超越这一点时,它变得很奇怪。

    ...
    #define _RC0 31
    #define _RC1 32
    #define _RC2 33
    #define _RC3 34
    #define _RC4 35
    #define _RC5 36
    #define _RC6 37
    #define _RC7 38

    #define HI  1
    #define LO  0

    void why(unsigned char p, int z)
    {
        if(z == HI)
        {
            if(p == _RC0) PORTCbits.RC0 = 1;
            else if(p == _RC1) PORTCbits.RC1 = 1;
            else if(p == _RC2) PORTCbits.RC2 = 1;
            else if(p == _RC3) PORTCbits.RC3 = 1;
            else if(p == _RC4) PORTCbits.RC4 = 1;
            else if(p == _RC5) PORTCbits.RC5 = 1;
            else if(p == _RC6) PORTCbits.RC6 = 1;
            else if(p == _RC7) PORTCbits.RC7 = 1;
        }
        else if(z == LO)
        {
            PORTC = 0b11110000;
        }
        else
        {
            PORTC = 0b10101010;
        }
    }

    void timer_isr (void) __interrupt(1) __using (1)
    {
        TMR0H=0;
        TMR0L=0;
        why(_RC0, LO);
         why(_RC1, LO);
          why(_RC2, LO);
        WAIT_CYCLES(5000);
        why(_RC0, HI);
         why(_RC1, HI);
          why(_RC2, HI);
          WAIT_CYCLES(5000);
    }

    void main(void)
    {
        WDTCONbits.SWDTE = 0;
        WDTCONbits.SWDTEN = 0;
        TRISC = 0b00000000;
        PORTC=0b00000000;

        INTCONbits.GIE = 1;
        INTCONbits.PEIE = 1;
        INTCONbits.TMR0IF = 0;
        INTCONbits.TMR0IE = 1;
        T0CONbits.T08BIT = 0;
        T0CONbits.T0CS = 0;
        T0CONbits.PSA = 1;
        TMR0H = 0;
        TMR0L = 0;
        T0CONbits.TMR0ON = 1;

        while(1)
        {

        }
    }

在上面的代码中,四个 LED 应该闪烁,而其他四个保持亮起。相反,LED 以 10101010 模式保持亮起,该模式发生在“else”块中,当使用 HI 或 LO 以外的任何值调用“why”时应该发生这种情况。我从来没有用其他任何东西来调用它,那么为什么它会达到那个呢?

更新 - 进一步减少,不再有中断或未指定的包含/定义。这现在是整个程序,我仍然看到相同的行为。将模式从 10101010 更改为 10101011,以便我可以验证芯片实际上是否正在使用新代码进行编程,而且看起来确实如此。

    #include "pic16/pic18f24j10.h"

    #define WAIT_CYCLES(A)  for(__delay_cycle = 0;__delay_cycle < A;__delay_cycle++)
    int __delay_cycle;

    #define HI 1
    #define LO 0

    void why(int z)
    {
        if(z == HI)
        {
            PORTC = 0b11111111;
        }
        else if(z == LO)
        {
            PORTC = 0b11110000;
        }
        else
        {
            PORTC = 0b10101011;
        }

    }

    void main(void)
    {
        TRISC = 0b00000000;
        PORTC=0b00000000;

        while(1)
        {
        why(LO);
        WAIT_CYCLES(5000);
        why(HI);
        WAIT_CYCLES(5000);
        }
    }
4

1 回答 1

1

一旦中断被断言,它就永远不会被清除。这导致 timer_isr() 被重复调用。没有达到任何其他代码。TMR0IF 位必须由中断服务程序用软件清零。

请记住,您不仅需要在 ISR 中花费的时间少于计时器的时间 - 花费最少的必要时间是一个好习惯。

消除延迟并简单地切换一个标志或增加一个寄存器。在您的主 while (1) 循环中,监视标志或计数器,并从那里调用Why()。

于 2015-04-22T16:47:07.503 回答