为什么我的Timer2中断不起作用?我是否缺少任何寄存器配置?

时间:2019-04-26 23:53:23

标签: c pic mplab

我正在使用pic10f322微控制器进行项目。我已经制定了一个非常基本的通信协议-有一个启动脉冲(10 ms),然后是多个5ms脉冲(2个脉冲-点亮红灯,3个黄色点亮,而4-绿色)。因此,以下代码试图读取通信协议并打开相应的灯。我正在使用TMR0来测量脉冲的长度并对其进行计数。我有一个双色LED(红色和绿色),所以我需要将两者交替显示以产生黄色。我希望将TMR2用作中断,以使我可以将黄光与代码的其余部分分开发出脉冲,以便不会妨碍我的主要功能检测启动脉冲。

我不知道为什么它不起作用。我已经检查了寄存器(尽管请仔细检查以防万一我看不到东西)。代码会编译。 我在代码的各个阶段打开了灯以进行检查,并且在每种情况下都打开了灯,包括最后一个将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.5ms内会发生?还是相对较快,但是它永远不会进入中断函数或之前使用汇编指令告诉它转到该函数的函数内部。

3 个答案:

答案 0 :(得分:0)

在PIC16中,您需要与其余配置分开启动定时器,如下所示:

T2CONbits.TMR2ON = 1;

此外,请检查是否已启用中断:

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

我建议使用以上表示法进行初始化;您拥有的东西很难验证。

答案 1 :(得分:0)

PIC 10仅具有一个中断向量,该中断向量位于地址SELECT sold_ticket.date, SUM (sold_ticket) AS sold_ticket, SUM(customer_winner.win_ticket), SUM (win_ticket) AS lottery_win FROM sold_ticket INNER JOIN customer_winner ON sold_ticket.date= customer_winner.date GROUP BY sold_ticket.date; 上(而不是您期望的0x04上)。

尝试这样的事情:

0x08

答案 2 :(得分:0)

此初始化函数获得TMR2高优先级中断 在PIC18F25K80上

void pwm_mosfet_stepper_init() {
    
    TMR2 = 0;
    RCON |= (1<<7);    // IPEN = 1;
    PR2 = 100; // 100; // 100==@16uS 1.6ms
    //       
    INTCON |= ( (1<<6) | (1<<7) ); // GIE/GIEH PEIE/GIEL i.e. both low and high enabled
     
    // .......................... post4  ON pre4
    //T2CON = 0x1D; // 2us tick ON   11    1  01

    // .......................... post4  ON pre16
    T2CON = 0x1F; // 16us tick ON   11    1  1X

    IPR1 |= (1<<1); // TMR2IP = 1; HIGH PRIORITY
    PIE1 |= (1<<1); // TMR2IE = 1; // interrupts are GO!
}