Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Forum général sur le langage C !

Modérateur : Jérémy

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#1 Message par albertdela » lun. 15 mai 2023 22:05

Bonsoir.
Enfin ! Merci pour ce forum sur les PIC en Français !!!
Je suis plutôt nouveau en C et un noob en PIC mais bon, je me défend très bien en Python donc finalement ben ça passe. Reste juste à savoir quoi mettre où et c'est bon.
Donc voilà. Le projet, c'est un allumage électronique pour un monocylindre à partir d'un 18F26K22. Concept assez facile, on écoute une broche qui passe à un moment à l'état haut, c'est un Top. A partir de là, on commence à compter sur deux TIMERs. Le premier sera arrêté par le prochain top et donnera la vitesse de rotation, le second va provoquer l'allumage quand il déborde, on le remet à la bonne valeur et on éteint l'étincelle au bout de la valeur prédéfinie et on recharge avec une valeur qui correspond à l'avance à l'allumage calculé par la boucle principale. Comme il faut aussi communiquer avec l'extérieur, on active une PWM sur une broche qui sera l'image de la vitesse de rotation. 0%: 1000tr/min, 100% 10.000tr/min (avec coupure d'allumage).
Jusque là, facile tout va bien. Je compile, deux trois warnings à cause de mauvais changement de type de variable (ben oui C, c'est pas Python :-) ). Mais quand je veux faire la simulation, je m'aperçois qu'en fait, le TIMER2 (donc la PWM) ne démarre pas. Comme je suis un peu une buse en PIC, je m'étais fait conseillé par ChatGPT (je vous conseille d'ailleurs parce que comme il fait des erreurs, faut être vigilant mais ça être beaucoup pour les structures et la prog en générale). Seulement, lui me dit que c'est bon d'après le datasheet, j'ai fait un translate et je trouve les mêmes infos et c'est bien ce qui est fait dans ma fonction d'initialisation. Donc, soit je me suis trompé quelque part et je ne trouve pas soit je n'ai pas configuré le simulateur correctement soit il y a vraiment un problème de programmation... Je suis sous MPLAB X parce que ça me paraît plus conviviale pour l'instant et je n'ai pas envie de revenir à l'ASM tout de suite (oui j'en ai fait sur AMSTRAD CPC464 :-D ). Du coup, est-ce que quelqu'un aurait la gentillesse de ce pencher sur ce bout de code pour voir si j'ai pas merder quelque part ?
J'ai oublié de préciser que ça ne démarre pas parce que ça ne passe pas le while qui attend le débordement. En fait, d'après le simulateur, TIMER2 reste coincé sur une seul valeur "fantaisiste" (parce que pas toujours la même en fonction de je ne sais pas quoi ...).
Merci beaucoup si quelqu'un s'en sort. @+

Edit : pour les pressés, allez au #13 pour avoir le code qui fonctionne. Si vous voulez comprendre, il faudra lire les réponses qu'il y a avant :langue:
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Modifié en dernier par albertdela le mer. 17 mai 2023 21:57, modifié 1 fois.

TIMER2 qui ne démarre pas ...
Jérémy
Administrateur du site
Administrateur du site
Messages : 2723
Âge : 45
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#2 Message par Jérémy » lun. 15 mai 2023 22:25

Bonjour et bienvenu albertdela,

Merci de mettre ton code entre les balises [code] . Le téléchargement d'un code attire que peu de monde et tu auras bien moins de réponse.

Voici un lien explicatif :
viewtopic.php?p=1020#p1020

Merci à toi
C'est en faisant des erreurs, que l'on apprend le mieux !!!

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#3 Message par albertdela » lun. 15 mai 2023 23:02

effectivement, en plus le code n'est pas très long...
le main:

Code : Tout sélectionner

/* 
 * File:   newmain.c
 * Author: Albert
 *
 * Created on 11 mai 2023, 00:18
 */

#include <stdio.h>
#include <stdlib.h>
#include "config.h"
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>

/*
 * Ce programme doit permettre de créer un allumage éléctronique type CDI
 * à partir d'un 18F26K22 (configuré à 64MHz)en boitier SOIC ou SSOP.
 * RB0(21) : entrée top vilbrequin supposé à 270° du PMH (ENTREE_TOP)
 * RB2(23) : sortie PWM image de la vitesse (0% : 1000; 100% : 10.000)
 * RC2(13) : sortie led de contrôle de fonctionnement 
 * RC3(14) : sortie de commande de HT (1: géné HT; 0: bloquée) (SORTIE_HT)
 * RC4(15) : sortie Top Allumage (1: commande bobine; 0: bloquée) (SORTIE_ALL)
 * Rupture d'allumage à 10.000tr/min
 * Avance est calée à 0 jusqu'à 1500tr/min.
 * Variation linéaire de 1.500 à 10.000 pour 0 à 30° d'avance.
 */

volatile uint16_t vitesse_rotation = 0; //
volatile bool change_vit = false; // on a pas changé la vitesse de rotation
volatile uint16_t avance = 0; // avance nulle par défaut
volatile uint16_t attente_on = 0; // compteur d'attente pour éviter de chauffer la bobine
volatile bool flag_on_all = false; // au début allumage OFF
volatile bool coupure_all = false; // au début on est pas au rupteur
volatile uint16_t compteur = 0 ; // clignotant de la led de débug

void __interrupt() isr(void) {
    static uint8_t valeur_timer = 0;
    if (INTCONbits.TMR0IF == 1 ) { // Débordement de timer0. On coupe la HT si >5s
        attente_on += 65; // on ajoute 65ms au compteur
        if (attente_on > 5000) { // on dépasse 5.000 ms
            SORTIE_HT = 0;
            attente_on = 5000;
        }        
        TMR0H 
= 0; // Timer0 à 0
        TMR0L = 0; // et on repart pout le comptage
        INTCONbits.TMR0IF = 0; // On efface le flag
        return; // on sort
    }
    
    
/* On utilise le Timer1 pour la gestion de l'étincelle
     * le flag_on_all sert à determiner dans quel état on est.
     *  si ON l'étincelle est en court si OFF on est post-allumage
     * L'étincelle unique est prévue de durer 10us
     * Ensuite on recharge avec la valeur "avance" prévue et le ENTREE_TOP déclenchera
     */
    if (PIR1bits.TMR1IF) { // on est à la fin du Timer1 car débordement
        SORTIE_HT = 1; // on active la HT
        // Réinitialiser Timer2
        T1CONbits.TMR1ON = 0; // Désactiver Timer1
        flag_on_all = !flag_on_all; // si on étincelle on arrête sinon on commence
        if (flag_on_all) {     
            if 
(!coupure_all) {  
            SORTIE_ALL 
= 1; // Allumage si pas au rupteur
            }
            TMR1 = 0x14; // 10 microsecondes d'allumage
            T1CONbits.TMR1ON = 1; // Activer Timer2
        }
        else { // on a fini l'étincelle, on prépare la suivante
            TMR1 = avance; // Précharger Timer1 avec la valeur "avance"
            SORTIE_ALL = 0; // stop allumage
        }
        PIR1bits.TMR1IF = 0; // Effacer le flag d'interruption de Timer2
    }
    /* Quand le TOP arrive sur la broche 21 (RB0), on capture le TIMER0
     * et on fait le calcul l'intègre pour la mesure de vitesse.
     * Le TIMER0 est paramètré pour compter toutes les 1us. La variable
     * vitesse_rotation est mise à jour et le flag change_vit passe à ON.
     * On profite de la mesure pour limiter à 10.000tr/min par coupure d'allumage
     */
    if (INTCONbits.INT0IF) { // calcul de la vitesse de rotation au top HALL
        INTCONbits.INT0IE = 0; // Désactiver l'interruption externe
        unsigned int valeur_timer = (unsigned int)((TMR0H << 8) + TMR0L); // Capturer la valeur de TMR0
        if (valeur_timer > 800) { // Anti-rebond à 800 us
            if (valeur_timer > 6000) { // Limite à 10.000 tr/min
                valeur_timer = 6000;
                coupure_all = true;
            }
            else {
                coupure_all = false;
                T1CONbits.TMR1ON = 1; // on active le TIMER1 pour faire le TOP avance
            }
            vitesse_rotation = valeur_timer; // temps sur un tour en ms
            change_vit = true ; // on a changé la vitesses de rotation
            TMR0H = 0; // Timer0 à 0
            TMR0L = 0; // et on repart pout le comptage
        }
        INTCONbits.INT0IF = 0; // Effacer le flag d'interruption externe
        INTCONbits.INT0IE = 1; // Réactiver l'interruption externe
    }    
}


int main(int argc, char** argv) {
config_ports();
config_timer0();
config_timer1();
config_interrupt_externe ();
config_interrupt();
configure_pwm();
printf("La valeur de compteur est : %d\n", compteur);
while (1) {    // Boucle principale
    if (change_vit) {   // Un top PMH a eû lieu, 
        avance = calcul_avance(vitesse_rotation);   // on actualise "avance" pour le prochain tour
        change_vit = !change_vit;   // On a bien pris en compte le changement
        CCPR1L = duty(vitesse_rotation);    // On actualise la PWM
    }
    compteur++;
    if (PORTCbits.RC1 == 1) {
        PORTCbits.RC1 = 0 ;
        }
        else {
            PORTCbits.RC1 = 1;
        }
    printf("La valeur de compteur est :", compteur);
    };
}


et la config :

Code : Tout sélectionner

/* 
 * File:   config.h
 * Author: Albert
 *
 * Created on 10 mai 2023, 22:02
 */

#ifndef CONFIG_H
#define    CONFIG_H

#include <xc.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillateur interne, broches 6 et 7 sont des entrées/sorties
#pragma config PLLCFG = ON      // Active l'oscillateur PLL (x4)
#pragma config PRICLKEN = ON    // Active le verrouillage de la clock périphérique
#pragma config FCMEN = OFF      // Désactive le moniteur de la clock
#pragma config PWRTEN = OFF     // Désactive le Power-up Timer
#pragma config BOREN = OFF      // Désactive le Brown-out Reset
#pragma config BORV = 0         // Niveau de tension de Brown-out Reset à 4.0V
#pragma config WDTEN = OFF      // Désactive le Watchdog Timer
#pragma config MCLRE = EXTMCLR  // Active le reset MCLR externe
#pragma config DEBUG = OFF      // Désactive le mode de débogage
#pragma config STVREN = ON      // Active le stack overflow reset

#define _XTAL_FREQ 64000000     // Définit la fréquence de l'oscillateur interne

// Configuration des ports
void config_ports(void) {
    TRISB = 1;
    TRISBbits.TRISB0 = 1; // RB0 est en entrée pour la détection du top
#define ENTREE_TOP PORTBbits.RB0
    TRISC = 0xFF;
    TRISCbits.TRISC1 = 0; // RC2 est en sortie pour une LED de debug
    // Sortie pour la HT en RC3
    TRISCbits.TRISC3 = 0; // RC3 est en sortie pour commande de HT
#define SORTIE_HT LATCbits.LATC3
    TRISCbits.TRISC4 = 0; // RC4 est en sortie pour commande d'allumage
#define SORTIE_ALL LATCbits.LATC4
}
// Configuration du Timer0
void config_timer0(void) {
    T0CONbits.T08BIT = 0; // 16-bit mode
    T0CONbits.T0CS = 0; // Utiliser l'oscillateur interne pour TIMER0
    T0CONbits.PSA = 0; // Activer le prédiviseur pour TIMER0
    T0CONbits.T0PS = 0b010; // Prédiviseur de 1:64 pour TIMER0
    TMR0H = 0; // Timer0 à 0
    TMR0L = 0;
}
   

    
// Configuration du Timer1
void config_timer1(void) {
    T1CONbits.TMR1CS = 0; // Clock interne (Fosc/4): 16MHz
    T1CONbits.T1CKPS = 0b11; // Division de fréquence par 8 : 2Mhz
    T1CONbits.TMR1ON = 0; // Désactivation en attente du PMH
    PIE1bits.TMR1IE = 1; // Activation de l'interruption de débordement
}
        
    
// Configuration de l'interruption externe INT0
void config_interrupt_externe(void) {
    INTCON2bits.INTEDG0 = 1; // Détection sur front montant
    INTCONbits.INT0IF = 0; // Effacer le flag d'interruption externe
    INTCONbits.INT0IE = 1; // Activation de l'interruption externe
}

    // Configuration des interruptions
void config_interrupt(void) {
    PIE1bits.TMR2IE = 1; // Activer l'interruption de Timer2
    INTCONbits.PEIE = 1; // Activation des interruptions périphériques
    INTCONbits.GIE = 1; // Activation générale des interruptions
}

// Configuration des registres CCP1CON1 et CCP1CON2 pour générer une PWM 5KHz
// Sortie sur RB2
void configure_pwm() {
    // Configurer le mode PWM sur le CCP1
    TRISCbits.TRISC2 = 1; // désactiver la sortie CCP1
    CCP1CONbits.CCP1M = 0b1100; // Configurer CCP1 pour mode PWM
    CCP1CONbits.P1M = 0b00; // Configurer CCP1 pour mode PWM
    CCPTMRS0bits.C1TSEL = 0b01; // Sélectionner Timer2 pour CCP1
    
    
// Configurer le timer 2 pour générer une interruption toutes les 200µs (5kHz)
    T2CONbits.T2CKPS = 0b11;    // Prédivision par 16
    T2CONbits.T2OUTPS = 0;      // Pas de postdivision
    PR2 = 199;                  // Période de 200µs (64MHz / 4 / 199)
    
    
// Configurer le rapport cyclique initial à 0%
    CCPR1L = 0;
    CCP1CONbits.DC1B = 0;
    
    
// Finalisation
    T2CONbits.TMR2ON = 1;   // Activer le timer 2
    while (PIR1bits.TMR2IF == 0); // Attendre le débordement
    TRISCbits.TRISC2 = 0;   // Activer la sortie
}

unsigned int calcul_avance(unsigned int x) {
    return (unsigned int)(0.2624 * x - 744);
}

uint8_t duty(uint16_t x) {
    return (uint8_t) ((0.004722 * x) - 28.332);
}

#endif /* CONFIG_H */


A priori, ça plante là : "while (PIR1bits.TMR2IF == 0); // Attendre le débordement" parce que le TIMER2 ne déborde jamais...

C'est a priori, l'application de ceci (p181 du datasheet) :
14.3.2 SETUP FOR PWM OPERATION
The following steps may be taken when configuring the CCP module for standard PWM operation:
1. Disable the CCPx pin output driver by setting the associated TRIS bit.
2. Select the 8-bit TimerX resource, (Timer2, Timer4 or Timer6) to be used for PWM generation by setting the CxTSEL<1:0> bits in the CCPTMRSx register.(1)
3. Load the PRx register for the selected TimerX with the PWM period value.
4. Configure the CCP module for the PWM mode by loading the CCPxCON register with the appropriate values.
5. Load the CCPRxL register and the DCxB<1:0> bits of the CCPxCON register, with the PWM duty cycle value.

Note 1: The corresponding TRIS bit must be cleared to enable the PWM output on the CCPx pin.
2: Clearing the CCPxCON register will relinquish control of the CCPx pin.

6. Configure and start the 8-bit TimerX resource:
• Clear the TMRxIF interrupt flag bit of the PIR2 or PIR4 register. See Note 1 below.
• Configure the TxCKPS bits of the TxCON register with the Timer prescale value.
• Enable the Timer by setting the TMRxON bit of the TxCON register.

7. Enable PWM output pin:
• Wait until the Timer overflows and the TMRxIF bit of the PIR2 or PIR4 register is set. See Note 1 below.
• Enable the CCPx pin output driver by clearing the associated TRIS bit

Note 1: In order to send a complete duty cycle and period on the first PWM output, the above steps must be included in the setup sequence. If it is not critical to start with a complete PWM signal on the first output, then step 6 may be ignored.

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#4 Message par satinas » mar. 16 mai 2023 06:41

Bonjour à tous,
Source bien présenté et commenté, cela simplifie grandement la compréhension.
Quelques remarques :

Pas de code dans un fichier .h
TRISCbits.TRISC1 = 0; // RC2 est en sortie pour une LED de debug (C1 ou C2 ?)
T0CONbits.T0PS = 0b010; // Prédiviseur de 1:64 pour TIMER0 (1:8 plutôt ?)
CCPTMRS0bits.C1TSEL = 0b01; // Sélectionner Timer2 pour CCP1 (sûr ?)

Pour le timer2 qui ne démarre pas, si il démarre.
Lire le post plus bas sur l'I2C, le flag IE était on, pas nécessaire et non bloquant ni plantant par chance, le flag GIE était à 0. Dans ton cas cela devient bloquant.
Les flags IF sont levés lorsque des évènements se produisent sur les périphériques ou depuis l'extérieur du pic. Le programme doit les remettre à 0 pour réarmer la prochaine détection, si cette info l'intéresse.

Ensuite il est possible de mettre en place une routine d'interruption (ISR) qui démarre lorsqu'un flag IF est levé, pour cela on met IE à 1, et c'est dans l'ISR que l'on remet à 0 le flag IF. Tu as mis TMR2IE à 1, ce n'était pas nécessaire car tu ne prévois pas de traiter le cas dans l'ISR. Le problème, dès que TMR2IF passe à 1, le pic attaque aussitôt l'ISR. Or dans celle-ci tu ne le remets pas à 0, donc la condition de démarrage de l'iSR est toujours vraie, et elle boucle en permanence, pic bloqué, non planté.

Avec TMR2IE = 0, le flag TMR2IF passera une seule fois à 1, et ne sera pas remis à 0, ce n'est pas grave car ce flag n'est pas utilisé par l'application. Les flags dits d'interruption sont des flags d'évènement :)

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#5 Message par albertdela » mar. 16 mai 2023 08:18

Bonjour,
merci d'avoir pris le temps d'analyser le code et de répondre. C'est appréciable.

Pas de code dans un fichier .h

J'en prend bonne note (je n'ai certainement pas encore toutes les bonnes pratiques...). Du coup, si on veut clarifier son projet, le code associé aux routines va où? On fait un autre fichier .h que l'on intègre par un #include ?

TRISCbits.TRISC1 = 0; // RC2 est en sortie pour une LED de debug (C1 ou C2 ?)
T0CONbits.T0PS = 0b010; // Prédiviseur de 1:64 pour TIMER0 (1:8 plutôt ?)
CCPTMRS0bits.C1TSEL = 0b01; // Sélectionner Timer2 pour CCP1 (sûr ?)

:roll: trompage, à recalculer, à vérifier (j'ai pas le datasheet sous la main). Merci pour l'alerte.

Lire le post plus bas sur l'I2C, le flag IE était on, pas nécessaire et non bloquant ni plantant par chance, le flag GIE était à 0. Dans ton cas cela devient bloquant.
Les flags IF sont levés lorsque des évènements se produisent sur les périphériques ou depuis l'extérieur du pic. Le programme doit les remettre à 0 pour réarmer la prochaine détection, si cette info l'intéresse.

Ensuite il est possible de mettre en place une routine d'interruption (ISR) qui démarre lorsqu'un flag IF est levé, pour cela on met IE à 1, et c'est dans l'ISR que l'on remet à 0 le flag IF. Tu as mis TMR2IE à 1, ce n'était pas nécessaire car tu ne prévois pas de traiter le cas dans l'ISR. Le problème, dès que TMR2IF passe à 1, le pic attaque aussitôt l'ISR. Or dans celle-ci tu ne le remets pas à 0, donc la condition de démarrage de l'iSR est toujours vraie, et elle boucle en permanence, pic bloqué, non planté.


Il m'a fallu plusieurs relectures pour comprendre :) et surtout sortir de ce que je pensais avoir compris du fonctionnement.
Arrêtes-moi si je me trompe mais les flags sont indépendants des IE ? La différence sera dans le traitement. Si IE <ON> lors du flag on traite en ISR, si IE<OFF> on traite rien sauf si on regarde l'état du IF. Est-ce que j'ai bien compris ?

Avec TMR2IE = 0, le flag TMR2IF passera une seule fois à 1, et ne sera pas remis à 0, ce n'est pas grave car ce flag n'est pas utilisé par l'application. Les flags dits d'interruption sont des flags d'évènement :)

Ca semble corroborer ce que j'ai compris... Donc je passe le IE du Timer2 à <OFF> et le IF à 0, je refais mon paramétrage et j'attends le débordement, ça doit fonctionner...
Si j'ai bien compris, il faudra que je me méfie de ne pas remettre IE du Timer2 à <ON> sinon on passe en ISR et comme tu le dis, je n'ai pas prévu de traiter l'info..

Si j'ai tout bon, merci bien pour cette précieuse aide ! De 1, je comprends enfin comment vraiment ça fonctionne et de 2 je vais avancer un peu plus dans ce petit projet !

Merci !

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#6 Message par satinas » mar. 16 mai 2023 08:54

Je ne suis pas un grand puriste du C. Soit tu prévois plusieurs fichiers source .c à placer dans le projet MPLABX, soit tu mets tout dans le même fichier main.c, tant que l'appli ne grossit pas trop. Ok pour la config hardware du pic en fichier .h car ce n'est pas du code.

Arrêtes-moi si je me trompe mais les flags sont indépendants des IE ? La différence sera dans le traitement. Si IE <ON> lors du flag on traite en ISR, si IE<OFF> on traite rien sauf si on regarde l'état du IF. Est-ce que j'ai bien compris ?

C'est cela, avec quelques cas particuliers, la réception uart par exemple. On ne remet pas à 0 directement le flag IF, c'est quand on lit le buffer de réception que le pic le remet à 0 automatiquement. Là on ne peut pas se passer de traiter l'octet reçu, sinon les flags d'erreur seront de la partie à la prochaine réception.

Donc je passe le IE du Timer2 à <OFF> et le IF à 0, je refais mon paramétrage et j'attends le débordement, ça doit fonctionner...

Au reset tous les flags IE sont à 0, et tous les flags IF sont à 0 :)

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#7 Message par albertdela » mar. 16 mai 2023 10:08

Re,
en fait, en y refranchissant (je n'ai pas encore essayer, il faut que j'attende ce soir...), il me semble qu'il y a toujours un problème (ou alors, je n'ai pas compris...).

Si j'ai mis le IE à <ON> et que je teste "while (PIR1bits.TMR2IF == 0);" soit IF est à 0 et quand il passe à 1 on passe en ISR, soit il est déjà à 1 et on sort direct.
Vu ce qu'il ce passe (en l’occurrence rien ...), c'est que l'on ne passe pas au travers. Donc, on est à 0 et "au bout d'un moment", IF passe à 1 et donc comme IE est à <ON> on va dans l'ISR. Mais comme rien n'est fait dans l'ISR, on devrait ressortir et revenir sur le while (PIR1bits.TMR2IF == 0); qui lui devrait laisser la main puisque IF=1 ?!?
Donc en fait IE à 1 ou 0, on devrait tout de même passer me semble-t-il. Sauf si je n'ai pas compris l'ISR et qu'on boucle jusqu'à sortir sur une condition que je ne connais pas...

C'est certainement un petit point de détail mais ça me chiffonne et je crains de ne pas avoir les bons réflexes sur un autre projet car j'aurais mal compris...

Merci encore et @+

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#8 Message par satinas » mar. 16 mai 2023 11:21

Je n'ai pas été assez précis, la condition de démarrage de l'ISR, ce n'est pas TMR2IF passe à 1, c'est TMR2IF = 1 (avec GIE = PEIE = TMR2IE = 1).
L'ISR démarre quand TMR2IF passe à 1 durant le while. Pas le temps de sortir du while car l'ISR s'exécute aussitôt. A la sortie de l'ISR, TMR2IF est toujours à 1, donc elle redémarre aussi sec, elle se relance en permanence, tant que TMR2IF reste à 1. Le programme n'a pas la main pour sortir du while bien que la condition de sortie du while est vérifiée.

TIMER2 qui ne démarre pas ...
albertdela
Membre
Membre
Messages : 12
Enregistré en : mai 2023

#9 Message par albertdela » mar. 16 mai 2023 11:34

Ah...
On peut avoir GIE = 1 et PEIE = 1 et TMR2IE=0 ?
Il me faut les interruptions générales et les interruptions périphériques.

Sinon, ok, compris pour l'affaire de l'ISR qui ne sort pas. En fait, faut se mettre d'accord avec soit même:
soit : traitement ISR donc on efface l'IF et un flag pour sortir de la boucle pour la configuration de la PWM
soit : pas d'ISR mais on pense bien à changer l'IF

Vu la position de la configuration PWM dans le déroulé du programme, je ne crois pas que ce soit une bonne idée de rajouter un traitement ISR. C'est pas utile puisque TIMER2 n'est utilisé que pour une seule PWM...

Merci. J'essaie ça ce soir et je te dit ce qu'il en est. @+

PS: je reposterais le code qui fonctionne correctement.

TIMER2 qui ne démarre pas ...
satinas
Expert
Expert
Messages : 1225
Enregistré en : novembre 2015

#10 Message par satinas » mar. 16 mai 2023 11:45

albertdela a écrit :Source du message On peut avoir GIE = 1 et PEIE = 1 et TMR2IE=0 ?

Il faut les trois flags à 1 pour que l'ISR démarre, un seul à 0 et elle ne démarre pas. Par contre le flag TMR2IF se lèvera (ou restera à 1) dans tous les cas lors du débordement du timer.

Pour PEIE, cela dépend du timer, il est nécessaire pour les timers 1/3/5, pas sûr pour les timers 2/4/6, voir datasheet ou tester insitu.

Le test de TMR2IF au démarrage, c'est pour avoir une première période PWM précise, cela dépend de l'appli, on peut sen passer.
Vu le domaine de l'appli, le watchdog s'impose, à voir une fois qu'elle sera au point.


Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 12 invités