Почему мое прерывание Timer2 не работает? Я пропускаю какие-либо регистры? - PullRequest
1 голос
/ 27 апреля 2019

Я работаю над проектом с микроконтроллером pic10f322.Я сделал очень простой протокол связи - есть стартовый импульс (10 мс), за которым следует количество импульсов 5 мс (2 импульса - включает красный свет, 3 - желтый и 4 - зеленый).Таким образом, следующий код пытается прочитать протокол связи и включить соответствующий индикатор.Я использую TMR0, чтобы измерить длину импульса и посчитать его.У меня есть двухцветный светодиод (красный и зеленый), поэтому мне нужно чередовать два, чтобы создать желтый.Я надеялся использовать TMR2 в качестве прерывания, чтобы позволить мне пульсировать желтый свет отдельно от остальной части кода, чтобы он не мешал моей основной функции обнаруживать стартовые импульсы.

Понятия не имею, почему это не работает.Я проверил регистры (хотя, пожалуйста, перепроверьте, если я что-то не понимаю).Код компилируется.Я включил подсветку на разных этапах кода, чтобы проверить его, и подсветка включается в каждом операторе case, включая последний, в котором я установил для переменной перечисления LedColour соответствующий цвет.Когда я пытаюсь включить свет в функции прерывания, он никогда не включается.

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <pic.h>
#include <stdbool.h>
#include <pic10f322.h>

// crystal oscilator 
define _XTAL_FREQ 1000000

 // CONFIG
#pragma config FOSC = INTOSC    // Oscillator Selection bits 
#pragma config BOREN = OFF      // Brown-out Reset disabled
#pragma config WDTE = OFF       // WDT disabled
#pragma config PWRTE = OFF      // PWRT disabled
#pragma config MCLRE = OFF      // MCLR pin function
#pragma config CP = OFF         // Code Protection disabled
#pragma config LVP = ON         // Low-voltage programming enabled
#pragma config LPBOR = OFF      // Brown-out Reset disabled
#pragma config BORV = LO        // Brown-out Reset Voltage, low trip point
#pragma config WRT = OFF        // Flash Memory Write protection off

void timer2_isr(void);

#pragma code high_vector=0x08;
void interrupt (void)
{
    asm("GOTO timer2_isr");
}
#pragma code

#pragma interrupt timer2_isr

#define RED_LED    0x01
#define GREEN_LED  0x02

#define SetBit(bit) (PORTA |= bit )
#define ClearBit(bit) (PORTA &= ~bit)
#define TestBit(bit)   ( PORTA&bit)

int clkval = 0;

int pulsecnt = 0;

    enum {
        Red,
        Green,
        Yellow,
        Off,
    } LedColor = Off;


void timer2_isr (void)
{
    PORTA = 0b1101; //This turns a green light on if it enters this function
    if (PIR1 == 0x02)
    {
        PIR1 = 0x00;
    }
}


void main(int argc, char** argv) 
{    
    OSCCON = 0x30; //1MHz Clk
    TRISA = 0x0C;
    ANSELA = 0x00;
    PORTA = 0x0C;
    OPTION_REG = 0x06;
    T2CON = 0x04; //Timer2 Registers Prescaler= 1 - TMR2 PostScaler = 1 - PR2 = 254 - Freq = 980.39 Hz - Period = 0.001020 seconds
    PIE1 = 0x02;
    PIR1 = 0x00;
    TMR0 = 0;
    TMR2 = 0;
    PR2 = 254;
    INTCON = 0xC0;

    __delay_ms(2000);

    enum {
        WaitForStart,
        CountPulses,
        SelectColor,
    } State = WaitForStart;

    while (1) 
    {
        switch (State) 
        {
            case WaitForStart: //wait for start pulse
                if ( (PORTA & 0x04) != 0x04 )
                {
                    TMR0 = 0;
                    while ((PORTA & 0x04) != 0x04) 
                    {
                        clkval = TMR0;
                    }
                    if (18 < clkval < 22)
                    {
                        State = CountPulses;
                        pulsecnt = 0;
                    } 
                }
                break;

            case CountPulses: // found start pulse, now count pulses or reset
                if ( (PORTA & 0x04) != 0x04 )
                {
                    TMR0 = 0;
                    while ((PORTA & 0x04) != 0x04) 
                    {
                        clkval = TMR0;
                    }
                    if (8 < clkval < 12)
                    {
                        pulsecnt++;
                    }
                }
                if ((PORTA & 0x04) == 0x04)
                {
                    clkval = 0;
                    TMR0 = 0;

                    while ((PORTA & 0x04) == 0x04 && clkval < 45) 
                    {
                        clkval = TMR0;
                        if ((44 < clkval) || (pulsecnt > 4)) //no pulses noticed in over 22ms comparison or if you have surpassed the max number of pulses you are supposed to reach
                        {
                            if (pulsecnt > 0) 
                            { 
                                State = SelectColor;                             
                            } //if there has been a long delay,  and pulses have been detect (so pulsecnt is greater than 0) then move to next case
                            else 
                            {
                                State = WaitForStart;
                            } // if long delay and no pulses have been detected, restart and check for start pulse again
                        } 
                    }
                }
                break;

            case SelectColor: // if pulses have been detected, this state will be visited after long delay ( >22ms)

                if (pulsecnt == 2) 
                {
                    LedColor = Red;
                    //PORTA = 0b1110;
                    State = WaitForStart;
                }
                else if (pulsecnt == 3) 
                {
                    LedColor = Yellow;
                    State = WaitForStart;
                } 
                else if (pulsecnt == 4)
                {
                    LedColor = Green;
                    //PORTA = 0b1101;
                    State = WaitForStart;
                }
                else 
                {
                    LedColor = Off; 
                    State = WaitForStart;
                }
                break;

            default:
                State = WaitForStart;
                break;
        }

    } 
}

Я использовал «PORTA = 0b1101», который включает зеленый свет.в качестве тестовой строки, чтобы пройти через код и убедиться, что он достигает определенных точек.Прямо сейчас оно находится в начале прерывания, поэтому оно должно включиться и остаться на правом после первого прерывания, которое произойдет примерно через 2,5 мс, я думаю?Или, во всяком случае, относительно быстро, но он никогда не попадет внутрь функции прерывания или функции, которая раньше использовала ассемблер, чтобы сказать ей перейти к этой функции.

Ответы [ 2 ]

0 голосов
/ 29 апреля 2019

PIC 10 имеет только один вектор прерывания, который находится по адресу 0x04 (а не 0x08, как вы ожидали).

Попробуйте что-то вроде этого:

void interrupt myISR(void)
{
........
}
0 голосов
/ 27 апреля 2019

В PIC16 вам нужно запускать таймер отдельно от остальной части конфига, например:

T2CONbits.TMR2ON = 1;

Также убедитесь, что вы включили прерывания:

INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;

Я предлагаю использовать вышеуказанные обозначения для инициализации; что у тебя сложно проверить.

...