SDCC целочисленное сравнение неожиданное поведение

Я пытаюсь начать проект с использованием PIC18F24J10. Попытка использовать SDCC для этого. На данный момент я сократил свой код до простой попытки пригвоздить происходящее, так как я уже некоторое время вижу странное поведение и не могу продолжать, пока не выясню, что происходит. Не уверен, что это моя единственная проблема на данный момент, но я понятия не имею, почему это происходит. Прерывание по таймеру срабатывает, в сочетании с #defined для цикла заставляет светодиоды на PORTC мигать, возможно, два раза в секунду. Если я просто сделаю 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)
        {

        }
    }

В приведенном выше коде четыре светодиода должны мигать, а остальные четыре остаются включенными. Вместо этого светодиоды остаются в схеме 10101010, которая происходит в блоке "else", что должно происходить, когда вызывается "Why" с любым значением, отличным от HI или LO. Я никогда не называю это чем-то еще, так почему это когда-либо достигает этого?

ОБНОВЛЕНИЕ - дальнейшее сокращение, больше никаких прерываний или неопределенных включений / определений. Теперь это полная программа, и я до сих пор наблюдаю такое же поведение. Изменен шаблон с 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);
        }
    }

1 ответ

Как только прерывание установлено, оно никогда не очищается. Это приводит к тому, что timer_isr() вызывается повторно. Никакой другой код никогда не достигается. Бит TMR0IF должен быть очищен программно программой обработки прерываний.

Имейте в виду, что вам нужно не только тратить меньше времени на ISR, чем период таймера - это хорошая практика - тратить минимально необходимое количество времени.

Удалите задержки и просто переключите флаг или увеличьте регистр. В вашем главном цикле while (1) следите за флагом или счетчиком и звоните почему () оттуда.

Другие вопросы по тегам