макрос дает неверное значение на языке c - PullRequest
0 голосов
/ 29 апреля 2018

Я пытаюсь написать подпрограмму, которая генерирует задержку 1000 мс, используя Timer1 PIC18F4321 в 16-битном режиме в MPLAB X IDE с компилятором XC8. Эта задержка используется для переключения светодиода. Моя проблема в том, что я не могу получить требуемую задержку (1000 мс). Я попытался отладить программу, которую я заметил, что значение "count", вычисленное с помощью макроса, неверно. это дает значение 0x4000, а не 0x0F42. Я не знаю, что не так с макросом:

#define count (((timeDelay) * 1000) / (timerPeriod) * 256)

// C-program using polled I/O:
#include <P18F4321.h>
#define timeDelay (1000) // 1000 ms
#define Fosc (4) // 4 MHz
#define timerPeriod (1 / ((Fosc) / 4)) // us
#define count (((timeDelay) * 1000) / (timerPeriod) * 256)
#define countInit ((0xFFFF - (count)) + 1)
#define countInitHigh ((countInit & 0xFF00) >> 8)
#define countInitLow (countInit & 0x00FF)

void T0Delay(); // A subroutine that generates a delay of 1000 ms

void main()
{
    OSCCON = 0x60; // 4MHz Internal Oscillator
    TRISC = 0x00; // Port C output
    T0CON = 0x07; // 16-bit, 1:256 prescaler, internal clock
    for(;;) // loop forever
    {
        PORTCbits.RC0 = 0; // turn LED OFF
        T0Delay(); // Wait 10 seconds
        PORTCbits.RC0 = 1; // turn LED ON
        T0Delay(); // Wait 10 seconds
    }
}

void T0Delay(void)
{
    TMR0H = countInitHigh;
    TMR0L = countInitLow;
    INTCONbits.TMR0IF = 0; // clear timer overflow flag
    T0CONbits.TMR0ON = 1; // start Timer0
    while(!INTCONbits.TMR0IF); //polling, wait until timer finishes counting
    T0CONbits.TMR0ON = 0; // Stop Timer0
}

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Наконец-то я смог решить проблему, большое спасибо, ребята. Проблема заключалась в том, что в определении макроса #define count (((timeDelay) * 1000) / ((timerPeriod) * 256)) результат в числителе переполняется более чем на 16 бит. Поэтому решение состоит в том, чтобы использовать 32-разрядную арифметику, изменив (1000) на (1000UL). Окончательный код, который работает, исправляет это следующим образом:

// C-program using polled I/O:
#include <P18F4321.h>
#define timeDelay (1000UL) // 1000 ms
#define Fosc (4) // 4 MHz
#define timerPeriod (1 / ((Fosc) / 4)) // us  
#define count (((timeDelay) * 1000UL) / ((timerPeriod) * 256))
#define countInit ((0xFFFF - (count)) + 1)
#define countInitHigh ((countInit & 0xFF00) >> 8)
#define countInitLow (countInit & 0x00FF)

void T0Delay(); // A subroutine that generates a delay of 1000 ms

void main()
{
    OSCCON = 0x60; // 4MHz Internal Oscillator
    TRISC = 0x00; // Port C output
    T0CON = 0x07; // 16-bit, 1:256 prescaler, internal clock
    for(;;) // loop forever
    {
        PORTCbits.RC0 = 0; // turn LED OFF
        T0Delay(); // Wait 10 seconds
        PORTCbits.RC0 = 1; // turn LED ON
        T0Delay(); // Wait 10 seconds
    }
}

void T0Delay(void)
{
    TMR0H = countInitHigh;
    TMR0L = countInitLow;
    INTCONbits.TMR0IF = 0; // clear timer overflow flag
    T0CONbits.TMR0ON = 1; // start Timer0
    while(!INTCONbits.TMR0IF); //polling, wait until timer finishes counting
    T0CONbits.TMR0ON = 0; // Stop Timer0
}
0 голосов
/ 29 апреля 2018

Если вы добавите скобки вокруг (timerPeriod) * 256, вы получите желаемый результат:

#define count (((timeDelay) * 1000) / ((timerPeriod) * 256) /*<=parentheses here*/ )

Mutliplication и деление имеют одинаковый приоритет в C (как и в математике), поэтому, если вы хотите разделить на (timerPeriod) * 256, вам нужно заключить его в скобки.

...