IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Générer une interruption PIC18F458


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut Générer une interruption PIC18F458
    Bonjour à tous,

    je cherche à me familiariser avec les interruptions sur PIC18F,

    j'ai fait un bout de code qui ne fonctionne pas correctement en simulation sur MPLAB, je n'arrive plus à ressortir de l'interruption.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #include <p18f458.h>
     
     
    #define led1 PORTAbits.RA0
    #define led2 PORTAbits.RA1	
    #define led3 PORTAbits.RA2
    #define led4 PORTAbits.RA3
    #define inter1 PORTBbits.RB5
     
     
    void InterruptHandlerHigh (void);
     
     
    //---------------------------------interruption------------------------
    #pragma code InterruptVectorHigh = 0x08
    void
    InterruptVectorHigh (void)
    {
      _asm
        goto InterruptHandlerHigh //jump to interrupt routine
      _endasm
    }
     
    //------------------------------------------------------------------------
    // High priority interrupt routine
     
    #pragma code
    #pragma interrupt InterruptHandlerHigh
     
    void
    InterruptHandlerHigh ()
    {
      if (INTCONbits.RBIF)
        {                                   
          INTCONbits.RBIF = 0;            // mise à 0 du flag c'est ici le pb !
    	led3=1;
    	led4=1;
    	led1=0;
    	led2=0;
        }
    }
     
     
     
     
    //------------programme_principal------------------------------------------
     
    void main (void)
    {
    	TRISB=0xFF*; // PORTB en entrée
    	ADCON1=0x07; // PORTA en digital
    	TRISA=0x00; // PORTDA en sortie
    	PORTA=0x00;
     
    	INTCON=0b10001000; // autorisation des interruptions sur RB4 à RB7
    	while(1)
    	{
    	led3=0;
    	led4=0;
    	led1=1;
    	led2=1;
    	}
     
     
    }
    une petite explication du fonctionnement supposé, à la mise sous tension les LEDS 1 et 2 s'allument, dés qu'il y a une interruption sur RB5 par exemple les LEDS 1 et 2 s'éteignent et les LEDS 3 et 4 s'allument.

    mon problème est que cette action INTCONbits.RBIF = 0; ne s'effectue pas, j'arrive pas à remettre RBIF à 0 donc je peux pas ressortir de mon interruption.

    avez vous une idée ?

    merci.

  2. #2
    Membre expérimenté
    Inscrit en
    Septembre 2006
    Messages
    414
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 414
    Par défaut
    ne devrais tu pas autoriser de nouvelles interruption qu'a la fin de ta routine :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    void
    InterruptHandlerHigh ()
    {
      if (INTCONbits.RBIF)
        {                                   
     
    	led3=1;
    	led4=1;
    	led1=0;
    	led2=0;
        }
      INTCONbits.RBIF = 0;            // mise à 0 du flag c'est ici le pb !
    }

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut
    tout d'abord merci de ta réponse,

    j'avais déjà essayer de supprimer le flag en fin de routine mais cela n'a pas marché,

    j'ai même essayé de le répéter plusieurs fois

    INTCONbits.RBIF=0;
    INTCONbits.RBIF=0;
    INTCONbits.RBIF=0;

    rien à faire ce satané RBIF reste à 1.

  4. #4
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Salut,

    Es-tu sûr que ça compile sans erreur? Un goto vers un label hors de la fonction courante me parait un peu violent. En plus un goto n'empile pas d'adresse de retour. Est-ce qu'en pas par pas dans ta simulation tu entres bien dans InterruptHandlerHigh ?

    A+

    Pfeuh

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut
    je compile sans erreurs,

    pour le goto j'ai juste utilisé la syntaxe qui est donné dans un fichier type de C18 pour definir les interruptions.

    je rentre bien dans InterruptHandlerHigh dés l'interruption sur RB5, j'ai verifié en mode pas à pas, par contre après impossible d'en sortir, j'observe RBIF avec le watch et il reste à 1 malgré l'instruction de remise à 0.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut
    toujours pas trouvé

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut ((())))
    bonjour

    le pic execute un millon d'instructuions par secunde avec un quarz de 4mhz
    ton code ne marche pas sans temporisateur meme s'il est juste car impossible de voir ton led alume et sétein dans un tems de un microsecunde il faut inclure le fichier delay.h et utilise les fonction delay(); voir le fichier joint
    Fichiers attachés Fichiers attachés

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut
    Merci de ta réponse,

    je simule le programme avec MPLAB SIM en mode pas à pas, donc pas besoin de tempo,

    j'ai trouvé le problème, pour pouvoir effacer le flag RBIF il faut auparavant lire ou écrire dans le PORTB, ensuite ça marche, c'est clairement expliqué dans le datasheet mais je ne l'avais pas étudié assez attentivement.

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2010
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 6
    Par défaut
    je profite de ce fil pour vous faire part d'un autre problème,

    je réalise une tempo qui est censé durer 0.5 sec, mais elle en fait 26 fois plus, c'est à dire 13 sec,

    j'ai utilisé un exemple qui est repris dans beaucoup de documents sur le net

    # include <p18f458.h>
    # include <delays.h>
    # define duree 1250000
    void tempo (long compte);
    int value;
    long compte;

    void main (void)
    {

    TRISA=0;
    PORTA=0;
    ADCON1=0x07;
    value=0;

    while(1)
    {
    value=value+1;
    PORTA=value;
    tempo(duree);
    }
    }
    void tempo(long compte)
    {
    compte--;

    }

    je vous explique comment j'ai calculé ma tempo,

    j'ai un quartz de 10MHz, donc un cycle d'horloge de 0.1us,

    un temps de cycle = 4 cycle d'horloge = 0.4us,

    je veux une tempo de 0.5sec donc 0.5/0.4us = 1 250 000 cycles,

    c'est pour cela que j'ai utilisé une variable "long" pour définir ma durée de 1 250 000 cycles qui est censé prendre 0.5sec,

    le pb est que quand j'arrive dans ma fonction tempo, quand ma variable "compte" est décrémentée cela prend 26 cycles pour décrémenter de 1, j'ai vérifié en mode pas à pas,

    je pige pas pourquoi il faut 26 cycles pour décrémenter de "1", je pensais qu'il n'en fallait qu'un.

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 502
    Par défaut
    Citation Envoyé par Alberto_to Voir le message
    je pige pas pourquoi il faut 26 cycles pour décrémenter de "1", je pensais qu'il n'en fallait qu'un.
    − Les attentes actives en C, c'est le « mal » ! Vois si une de tes bibliothèques ne propose pas déjà sleep(). Autrement, tu as quatre timers disponibles sur ce circuit. Utilise l'un d'eux ;
    − Pourquoi fais-tu ta boucle en dehors de ta fonction tempo() ?
    − Un « compte-- » à l'intérieur de ta fonction n'a aucun effet. Ta variable, passée en argument, est une variable locale, perdue dès que tu sors de ta fonction. Je ne comprends même pas, à vrai dire, comment le programme que tu nous as présenté arrive à se terminer ;
    − Tu ne peux pas déterminer à l'avance, en C, comment le compilateur va s'y prendre pour décrémenter une variable ;
    − Ton micro-processeur a un bus de données de 8 bits. Même s'il peut décrémenter un registre en un seul cycle, il en faut quatre pour coder un long ;
    − Tu négliges le temps qu'il faut pour appeler la fonction, et pour en revenir ;
    − Les interruptions ne sont probablement pas inhibées sur dans ton programme, ce qui fait que ton micro-processeur va faire quelques tours ailleurs à intervalles réguliers.

    Cherches sleep(). À défaut, utilises un timer, sinon écris ta routine en assembleur. C'est le seul moyen, en prenant en compte les interruptions, de pouvoir garantir une routine au cycle près.

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut ((())))
    bonjour

    moi je connais pas le langage C j'ai presque un mois que j'ai découveré le site des developpez.net juste pour apprendre ce langage mais je pense que ta fonction ne fait rien car tu va sotire de la fonction d'aprés la premiere decrimentation et pense que la t'as besoins de la fonction for();

    je suis débutant et je ne suis pas sur a ce que j'ai dis

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut ((())))
    bonjour

    c'est comme ça comment je fais les boucle mais en assembleur
    ce code n'est pas commplet a toi le finir aller aussi voir les registres de timer
    friscal et postdiviseur bonne courrage

    void deley(int unsigned x);
    int main(void)
    {

    deley(x); /** appel deley **/
    /**>**>*> /* programme principal */
    deley(x); /** appel deley **/
    }

    void deley(unsigned char x)
    {
    /**>**>*> /** ici je ne sais pas comment fait la fonction X pour prendre le paramétre d'entrer
    sinon tu peux appel a la fonction avec un deley vaiable **/
    int unsigned char a,b,c;
    for(a = 0,a < 255,a++);
    {
    for(b = 0,b < 255,b++);
    {
    for(c = 0,c < 255,c++);
    {
    nop(); /** ici ajauter des nop nop() pour modifier la boucle**/
    return 0;
    }
    return 0;
    }
    } return 0;
    } return 0;
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. [ImageMagick] Générer une image à partir de plusieurs images ?
    Par fichtre! dans le forum Bibliothèques et frameworks
    Réponses: 8
    Dernier message: 16/02/2005, 15h32
  2. Détournement d'une interruption
    Par Invité dans le forum Assembleur
    Réponses: 18
    Dernier message: 16/02/2005, 13h49
  3. [ImageMagick] Comment générer une image d'un code à entrer ?
    Par MiJack dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 16/01/2005, 21h29
  4. Réponses: 2
    Dernier message: 14/07/2004, 16h55
  5. Générer une liste
    Par pfredin dans le forum Langage SQL
    Réponses: 6
    Dernier message: 02/04/2003, 15h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo