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 Réponses :
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.
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) { ........ }
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! }
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