2
votes

Pourquoi mon interruption Timer2 ne fonctionne-t-elle pas? Est-ce que je manque des configurations de registre?

Je travaille sur un projet avec le microcontrôleur pic10f322. J'ai créé un protocole de communication très basique - il y a une impulsion de démarrage (10 ms) suivie d'un certain nombre d'impulsions de 5 ms (2 impulsions - allume une lumière rouge, 3 allume en jaune et 4 - verte). Le code suivant tente donc de lire le protocole de communication et d'allumer la lumière correspondante. J'utilise TMR0 pour mesurer la longueur de l'impulsion et la compter. J'ai une LED bicolore (rouge et verte) donc je dois alterner les deux pour créer le jaune. J'espérais utiliser TMR2 comme interruption pour me permettre d'impulser la lumière jaune séparément du reste du code, de sorte que cela ne gêne pas ma fonction principale de détection des impulsions de démarrage.

Je ne sais pas pourquoi cela ne fonctionne pas. J'ai vérifié les registres (bien que veuillez faire une double vérification au cas où je suis aveugle à quelque chose). Le code se compile. J'ai allumé la lumière à différentes étapes du code pour le vérifier, et la lumière s'allume dans chaque déclaration de cas, y compris la dernière où j'ai défini la variable enum LedColour sur la couleur respective. Lorsque j'essaye d'allumer la lumière dans la fonction d'interruption, elle ne s'allume jamais.

#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;
        }

    } 
}

J'ai utilisé "PORTA = 0b1101", qui allume le feu vert. comme ligne de test pour parcourir le code et s'assurer qu'il atteint certains points. À l'heure actuelle, il est au début de l'interruption, il devrait donc s'allumer et rester allumé après la première interruption qui se produirait dans environ 2,5 ms je pense? Ou relativement rapidement de toute façon, mais il n'entre jamais dans la fonction d'interruption ou dans la fonction avant qui utilise l'assembly pour lui dire d'accéder à cette fonction.


3 commentaires

J'ai utilisé un PIC il y a des décennies pour certains projets. Plus tard, un étudiant est tombé sur le réglage du chien de garde (une case à cocher dans l'interface de programmation PIC). Il avait son chien de garde activé et son programme a fait une "boucle étrange" qu'il ne pouvait pas expliquer jusqu'à ce que je lui ai montré ce réglage de chien de garde et qu'il a éteint le chien de garde. Peut-être que vous avez aussi "eu de la chance" :)


@BitTickler malheureusement je ne pense pas que je suis si chanceux, mon chien de garde est déjà éteint: (mais j'apprécie que vous partagiez votre expérience car je suis sûr que j'aurais facilement pu faire cette erreur, je suis très débutant avec les PIC !


il y a aussi des trucs produisant des avertissements, comme par exemple if (18 < clkval < 22) (se produit plusieurs fois dans le code) "somain.c: 106: 37: avertissement: la comparaison de la constante 22 avec une expression booléenne est toujours vraie [-Wtautologique -constant-out-of-range-compare] "et quelques autres choses. J'ai compilé en utilisant l'IDE en ligne de MPLab. mplabxpress.microchip.com/mplabcloud/ide


3 Réponses :


1
votes

Dans PIC16, vous devez démarrer le minuteur séparément du reste de la configuration, comme ça:

T2CONbits.TMR2ON = 1;

Vérifiez également que vous avez activé les interruptions:

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

Je suggère d'utiliser la notation ci-dessus pour l'initialisation; ce que vous avez est difficile à vérifier.


0 commentaires

0
votes

Le PIC 10 n'a qu'un seul vecteur d'interruption et c'est à l'adresse 0x04 (pas 0x08 comme vous vous y 0x08 ).

Essayez quelque chose comme ça:

void interrupt myISR(void)
{
........
}


0 commentaires

0
votes

Cette fonction init obtient une interruption TMR2 à haute priorité sur un 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!
}


0 commentaires