Bonjour,
Je vous écris par ce que j'ai écris un programme en C pour mon PIC16F876 que je teste sur ma platine d’essai easypic v2 (je précise cela pour dire que du côté hardware c’est fiable et que je pense que mon problème vient de mon programme).
Le but du programme est d’enregistrer une trame Infrarouge de type RC5 (ou similaire) sur la pin RC2 du PORTC de mon PIC16f876. Le pin RC2 est utilisé via le module CCP1 en mode capture.
Le programme détecte successivement les fronts montants et descendants sur le pin RC2 et enregistre la durée entre chaque fronts successifs dans un tableau d’entier. Puis je souhaite ensuite afficher les valeurs du tableaux sur un afficheur LCD 2*16 caractères connecté au PORTB et configuré en mode 4 bits. Pour l’affichage j’utilise la routine fournie dans un fichier exemple de mikroc (l’IDE de developpement mikroelektronika fourni avec la carte de développement).
La séquence que j’ai développée est la suivante :
1/ J’ai configuré le Pin RB0 du portB en entrée et en interruption. Et j’attend un événement sur cette broche pour exécuter le code de la routine d’interruption de RB0. Celle ci consiste à configurer le TIMER1 en interruption et à initialiser celui ci à 0. La pin RB0 est connecté à un bouton poussoir. Un appui sur le bouton poussoir lance la procédure d’acquisition en déclenchant le TIMER1. Comme le TIMER1 est déclenché et que le prescaler est réglé à 1, avec une horloge de 4Mhz, le compteur s’incrémente toute les 1 microsecondes, et compte de 0 à 65536, ce qui équivaut à 65,536 ms. Dans 1 seconde j’ai 1000 ms, donc une acquisition de 1 seconde correspond à 15 * 65.536 ms. Il faut donc 15 débordement du TIMER1 pour 1 seconde. Et donc 150 débordement pour 10 secondes. C’est pourquoi une fois le TIMER1 activer, je surveille ma durée d’acquisition grace à une variable ack_period que j’incrémente de 1 à chaque débordement, et que je compare à 150 dans les autres partie du programme.
2/ Dans la routine d’IT du CCP1 , j’enregistre la valeur du TIMER1 à chaque fois qu’un front apparaît sur la pin RC2 et j’inverse à le front declencheur.
3/ Une fois le temps d’acquisition dépassé, je désactive les interruptions et j’affiche la différence des 2 premières valeurs de mon tableau TIMER_VALUE sur l’afficheur LCD.
Lorsque je compile j’ai aucune erreur. Par contre il n’y a rien qui se passe après qu j’ai chargé mon programme sur le PIC16f876, malgré que les signaux sont bien présent en entrée sur la pin RB0 du PIC pour lancer l’acquisiton, et la trame est bien la (vérification à l’oscilloscope) lorsque j’appuie sur une touche de ma télécommande TV qui est capté par un recepteur TSOP 38 et envoyé sur la pin RC2.
Pouvez vous m’aider à débloquer la situation SVP ?
Question supplémentaire : Comment s’executent les Interruptions entre elles ? Y a t il de conflits possibles entre les IT vu que sur le PIC16f876 il n’y a pas de niveau de priorité d’interruption à programmer comme sur un Motorola MC68000 par exemple ?
Merci d’avance,
Cordialement
roland
Code Source C:
//*********DECLARATIONS********* ************************
unsigned int read_TMR1;
unsigned short i;
unsigned long TIMER_VALUE[20];
long unsigned int ack_period;
long first_pw;
char txt[10];
char *text = "1ere largeur d'impulsion:";
const RISING_EDGE = 0x05;
const FALLING_EDGE = 0x04;
//Routine d'interruption
//****************************** *************************
void interrupt() {
//*************************Routi ne d'IT sur RB0*************************** ******
if (INTCON.INTF) {
if (ack_period < 150) {
// Configuration initialisation du TIMER1
T1CON=1 ; // Configure le TIMER1 avec comme source d'horloge interne Fosc/4
TMR1L = 0x00; // Initialisation du Timer1 TMR1L = 0x00;
TMR1H = 0x00 ; // Initialisation du Timer1 TMR1H = 0x00;
PIE1.TMR1IE = 1; // Autorise les interruptions sur le TIMER1 par débordement
PIR1.TMR1IF = 0; // RAZ du flag TMR1IF (positionné à un si il y a eu debordement du TIMER1)
}
else {
PIE1.TMR1IE = 0; //
PIE1.CCP1IE = 0; // Désactive les interruptions
INTCON.INTE = 0; //
INTCON.GIE = 0; //
INTCON.PEIE = 0;
}
}
//*************************Routi ne d'IT du TIMER1************************ ******
if (PIR1.TMR1IF) {
ack_period++; // Incrémente le compteur de durée d'acquisition
PIE1.TMR1IE = 1; // Autorise les interruptions sur le TIMER1 par débordement
PIR1.TMR1IF = 0; // RAZ du flag TMR1IF (positionné à un si il y a eu debordement du TIMER1)
}
//**************************Rout ine d'IT du CCP1************************** ******
if (PIR1.CCP1IF) {
//*Etape 4 du "Measuring Pulse Width" CCP Tips 'n Tricks
read_TMR1 = CCPR1H*256; // On récupère la valeur des registre CCPR1H
read_TMR1 = read_TMR1 + CCPR1L; // et CCPR1L dans une variable unique
TIMER_VALUE[i] = read_TMR1;
i++;
//*Etape 5 du "Measuring Pulse Width" CCP Tips 'n Tricks
if (CCP1CON = FALLING_EDGE) CCP1CON = RISING_EDGE;
else CCP1CON = FALLING_EDGE;
//Etape 3 du "Measuring Pulse Width" CCP Tips 'n Tricks
PIE1.CCP1IE = 1; // autorise les interruptions sur CCP1
PIR1.CCP1IF = 0; // RAZ du flag CCP1IF
}
//**********************Fin de la routine d'IT du CCP1**************************
}
void main(void)
{
//****************************** ****************************** ****************************** ********************//
//Configuration des registres
// On utilise CCP1/RC2 (pin13)
// On configure le PORTC en entrée
// Oncongigure le PORTB en entrée
TRISC=0b00000100 ; //configure RC2 en entrée
TRISB=0b00000001; //configure RB0 en entrée
PORTC=0b00000000 ; // reinitialise le PORTC
PORTB=0b00000000 ; // rénitialise le PORTB
//Configuration du PORTB en interruption
INTCON.INTE = 1; // Autorise les interruptions sur RB0
INTCON.INTF = 0; // RAZ du flag d'IT sur RB0
// Autorise les interruptions périphériques et sur CCP1
INTCON.GIE = 1; // Positionne les bits GIE, PEIE à 1 pour autoriser les interruptions
INTCON.PEIE = 1;
PIE1.CCP1IE = 1; // autorise les interruptions sur CCP1
PIR1.CCP1IF = 0; // RAZ du flag CCP1IF
//Configuration du module CCP1
// Choix du mode du CCP
CCP1CON = FALLING_EDGE ; // capture sur chaque front descendant, PRESCALER=1
//****************Initialisation des variables********************* **********
i=0; //index du tableau de valeur pointe sur la première valeur à enregistrer
ack_period = 0; // initialise la variable qui compte la durée de l'acquisition
do{
if (ack_period >= 150) {
first_pw = TIMER_VALUE[1]-TIMER_VALUE[0]; //calcule la première largeur d'impulsion
LongToStr(first_pw, txt ); //convertit l'entier first_pw en chaine de caractère
Lcd_Init(&PORTB); // Affiche la différence entre les 2
LCD_Cmd(LCD_CLEAR); // premières valeurs de TIMER_VALUE sur l'afficheur
LCD_Cmd(LCD_CURSOR_OFF); // LCD 2*16 caractères.
Delay_ms(1000);
LCD_Out(1,1, text); //
Delay_ms(1000);
LCD_Out(2,6,txt); //
}
} while(1);
}
-----