Interupt timer 1 en C
Répondre à la discussion
Affichage des résultats 1 à 16 sur 16

Interupt timer 1 en C



  1. #1
    thundertom

    Interupt timer 1 en C


    ------

    Bonsoir,

    Je me suis remis au C sur PIC depuis hier, jusqu'à maintenant tout allait bien. Mais pour éviter l'attente active, j'aimerais utiliser le TIMER1 en interruption.
    J'ai donc cherché des exemple de code donné par microchip (je sais je suis feignant) et j'ai essayé de les adaptés quelque peu affin d'obtenir ce que je veux.

    Seulement, ça ne fonctionne malheureusement pas. Je code sous MPLAB, et j'utilise un compilateur qui est fourni dans la dernière version: HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode) V9.70

    Voici mon bout de code, pour l'initialisation du Timer1, et la fonction interruption.
    Code:
    #include <pic.h>
    /*  cADC - Display the PICkit Pot Input Value on the built in LEDs
    
    This program samples the voltage on RA0 using the ADC and Displays the 
      value on the 8 LEDs using "cLEDDisp 2" as a base.  
    
    myke predko
    04.10.03
    
    */
    
    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
      & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    
    
    int i, j,iEnd=230;
    int FLAG=0;
    int ADCState = 0;               //  Keep Track of ADC Operation
    int ADCValue = 0;
    int Dlay = 63;                  //  LED Time on Delay Variable
    
    
    #pragma origin 4
    void interupt(void)
    {
    	if(TMR1IF==1)
    	{
    		TMR1IF=0;
    		FLAG=1;
    	}
    }
    
    void TMR1Setup(void)
    {
    //  Use TMR1 for a 300 ms delay
    
        T1CON = 0b00110001;                   //  TMR1 On/Internal Clock, 8x Prescaler
        TMR1H = (65536 - (300000 / 8)) >> 8;  //  Initialize a 300 ms delay
        TMR1L = (65536 - (300000 / 8)) & 0xFF;
        PEIE = 1;                             //  Enable Peripheral Interrupts
    	GIE = 1;							  //  Global Interupt Enable
        TMR1IF = 0;                           //  Turn off Pending Interrupt Requests
        TMR1IE = 1;                           //  Enable TMR1 Overflow to Request Ints
    }
    
    main()
    {
    	TMR1Setup();
    	TRISA = 0xff;
    	TRISC0=0;
        PORTA = 0;
        ANSEL = 1;                  //  Just RA0 is an Analog Input
    
        ADCON0 = 0b00000001;        //  Turn on the ADC
                                    //   Bit 7 - Left Justified Sample
                                    //   Bit 6 - Use VDD
                                    //   Bit 4:2 - Channel 0
                                    //   Bit 1 - Do not Start
                                    //   Bit 0 - Turn on ADC
        ADCON1 = 0b00010000;        //  Selemct the Clock as Fosc/8
    
        while(1 == 1)               //  Loop Forever
        {
            switch (ADCState)       //  ADC State Machine
            {
                case 0:             //  Finished, Start Next Sample
                    GODONE = 1;
                    ADCState++;
                    break;
                case 1:             //  Wait for ADC to complete
                    if (!GODONE)
                        ADCState++; //  Sample Finished
                    break;
                case 2:             //  Save Sample Value in "ADCValue" 
                    ADCValue = ADRESH;
    				
    				for (i = 0; i < iEnd; i++)  //  Delay Loop
                		for (j = 0; j < (ADCValue+10); j++);
    
           		 			NOP();                  //  Breakpoint Here
    
            				RC0 = RC0 ^ 1;          //  Toggle LED
    
                    ADCState = 0;
    
    				if(FLAG==0)
    				{
    					NOP();
    				}
                    break;
    
            }  // hctiws
        }  //  elihw
    }  //  End cADC
    Mon principal souci, c'est que je doute que le #pragma origin 4 soit juste. Seulement, je n'ai pas d'autre idée pour atteindre le vecteur d'interruption.

    Voila, merci à ceux qui m'aideront

    -----

  2. #2
    invite7a49d0d5

    Cool Re : Interupt timer 1 en C

    Bonsoir thundertom,

    si tu n'as pas l'habitude de manipuler les timers,
    je te conseille de commencer par faire clignoter
    une led grâce à l'interruption du Timer1...
    pour te familliariser avec le principe...

    un exemple fonctionnel (post #12),
    pas en C, mais court et commenté :
    http://forums.futura-sciences.com/el...ht=vede+Timer1

    vede
    ;O]

  3. #3
    thundertom

    Re : Interupt timer 1 en C

    Hello,

    J'ai pas mal bossé avec les timer il y a maintenant plus de 2ans, du coup c'est pas facile facile de m'y remettre.
    J'ai baissé les bras un peu trop vite, car maintenant ça tourne =)
    Plutôt que de prendre des bout de code chez microchip, j'ai tout fais moi même au final, ça prend moins de temps et c'est beaucoup plus compréhensible.
    En tout cas, merci de ton intérêt =)

  4. #4
    blurpy

    Re : Interupt timer 1 en C

    Bonsoir,

    Pour declarer ta routine d'interruption avec hi tech C, tu as juste besoin de declarer une fonction de type void interrupt

    en reprenant ton code

    Code:
    #include <pic.h>
    /*  cADC - Display the PICkit Pot Input Value on the built in LEDs
    
    This program samples the voltage on RA0 using the ADC and Displays the 
      value on the 8 LEDs using "cLEDDisp 2" as a base.  
    
    myke predko
    04.10.03
    
    */
    
    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
      & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    
    
    int i, j,iEnd=230;
    int FLAG=0;
    int ADCState = 0;               //  Keep Track of ADC Operation
    int ADCValue = 0;
    int Dlay = 63;                  //  LED Time on Delay Variable
    
    
    void interrupt my_isr(void)
    {
    	if(TMR1IF==1)
    	{
    		TMR1IF=0;
    		FLAG=1;
    	}
    }
    
    void TMR1Setup(void)
    {
    //  Use TMR1 for a 300 ms delay
    
        T1CON = 0b00110001;                   //  TMR1 On/Internal Clock, 8x Prescaler
        TMR1H = (65536 - (300000 / 8)) >> 8;  //  Initialize a 300 ms delay
        TMR1L = (65536 - (300000 / 8)) & 0xFF;
        PEIE = 1;                             //  Enable Peripheral Interrupts
    	GIE = 1;							  //  Global Interupt Enable
        TMR1IF = 0;                           //  Turn off Pending Interrupt Requests
        TMR1IE = 1;                           //  Enable TMR1 Overflow to Request Ints
    }
    
    main()
    {
    	TMR1Setup();
    	TRISA = 0xff;
    	TRISC0=0;
        PORTA = 0;
        ANSEL = 1;                  //  Just RA0 is an Analog Input
    
        ADCON0 = 0b00000001;        //  Turn on the ADC
                                    //   Bit 7 - Left Justified Sample
                                    //   Bit 6 - Use VDD
                                    //   Bit 4:2 - Channel 0
                                    //   Bit 1 - Do not Start
                                    //   Bit 0 - Turn on ADC
        ADCON1 = 0b00010000;        //  Selemct the Clock as Fosc/8
    
        while(1 == 1)               //  Loop Forever
        {
            switch (ADCState)       //  ADC State Machine
            {
                case 0:             //  Finished, Start Next Sample
                    GODONE = 1;
                    ADCState++;
                    break;
                case 1:             //  Wait for ADC to complete
                    if (!GODONE)
                        ADCState++; //  Sample Finished
                    break;
                case 2:             //  Save Sample Value in "ADCValue" 
                    ADCValue = ADRESH;
    				
    				for (i = 0; i < iEnd; i++)  //  Delay Loop
                		for (j = 0; j < (ADCValue+10); j++);
    
           		 			NOP();                  //  Breakpoint Here
    
            				RC0 = RC0 ^ 1;          //  Toggle LED
    
                    ADCState = 0;
    
    				if(FLAG==0)
    				{
    					NOP();
    				}
                    break;
    
            }  // hctiws
        }  //  elihw
    }  //  End cADC

  5. A voir en vidéo sur Futura
  6. #5
    thundertom

    Re : Interupt timer 1 en C

    Salut blurpy,
    Tu as l'air de connaitre le compilo, tu peux me dire si il gère automatiquement la sauvegarde du WREG et de STATUS?
    Ou s'il faut le gérer manuelement?
    J'ai essayé pushsys() et popsys(), mais le second n'est pas reconnu.

    merci de ton aide

  7. #6
    blurpy

    Re : Interupt timer 1 en C

    J'utilise la version pour PIC18, mais je suppose que la version pour les PIC16 fait la meme chose.

    Si ton pic a des fonction de sauvegarde automatique de registres, le compilo les utilisera automatiquement (je crois que certain pic16 sauvent W entre autre tout seul). Ensuite le compilo sauvegardera automatiquement tout registre qui serait modifié par ton code de maniere non intentionnelle (W Status, ...). Ceci est valable pour ta routine principale ainsi que les sous-routines eventuelles.

    Je sais pas si j'ai été bien clair

    Mais en resumé, la reponse est oui, c'est géré en auto

  8. #7
    invite7a49d0d5

    Cool Re : Interupt timer 1 en C

    re ;O]

    il faut "sauvegarder" les registres W, STATUS et FSR...
    puis les "restaurer" après l'interruption...

    la plupart des compilos le font automatiquement...
    pour le vérifier, jettes un oeil au code .asm généré...

    à l'adresse 4 (vecteur d'interruption), ça doit
    commencer par la sauvegarde de ces 3 registres...

    vede
    ;O]

  9. #8
    thundertom

    Re : Interupt timer 1 en C

    hummmm fichtrement malin vede, j'était parti dans la lecture de la doc du compilateur.
    Mais par contre pas de fichier asm généré par mon compilo....
    Jvais essayé de farfouillé encore un peu pour le trouvé.

  10. #9
    invite7a49d0d5

    Cool Re : Interupt timer 1 en C

    Citation Envoyé par thundertom Voir le message
    hummmm fichtrement malin vede, j'était parti dans la lecture de la doc du compilateur.
    Mais par contre pas de fichier asm généré par mon compilo....
    Jvais essayé de farfouillé encore un peu pour le trouvé.
    re ;O]

    il se trouve théoriquement dans le dossier de ton projet...
    exemple : monprogramme.asm

  11. #10
    blurpy

    Re : Interupt timer 1 en C

    view -> dissassembly listing dans mplab pour voir le code généré.

    Il faut peut-etre activer mplab sim pour qu'il charge automatiquement le dernier fichier généré, mais je ne suis pas sur.

    Sinon le fichier .lst généré contient un pseudo listing asm

  12. #11
    thundertom

    Re : Interupt timer 1 en C

    visiblement il me les sauve pas....jme trompe?

    Code:
    ---  D:\MesDocuments\Tracker\ASM\test\Untitled.c  ------------------------------------------------
    1:                 #include <pic.h>
    2:                 /*  cADC - Display the PICkit Pot Input Value on the built in LEDs
    3:                 
    4:                 This program samples the voltage on RA0 using the ADC and Displays the 
    5:                   value on the 8 LEDs using "cLEDDisp 2" as a base.  
    6:                 
    7:                 myke predko
    8:                 04.10.03
    9:                 
    10:                */
    11:                
    12:                __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
    13:                  & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    14:                
    15:                
    16:                int i, j,iEnd=230;
    17:                int ADCState = 0;               //  Keep Track of ADC Operation
    18:                int ADCValue = 0;
    19:                int INT_CPT1 = 0;
    20:                int INT_CPT2 = 0;
    21:                
    22:                
    23:                
    24:                interrupt timer (void)
    25:                {
    26:                	if(TMR1IF=1)
       0A5    1283     BCF 0x3, 0x5
       0A6    1303     BCF 0x3, 0x6
       0A7    140C     BSF 0xc, 0
       0A8    1C0C     BTFSS 0xc, 0
       0A9    28AB     GOTO 0xab
       0AA    28AC     GOTO 0xac
       0AB    28BD     GOTO 0xbd
    27:                	{
    28:                		TMR1L  = 0b11011110;         
       0AC    30DE     MOVLW 0xde
       0AD    008E     MOVWF 0xe
    29:                	    TMR1H  = 0b00001011;  
       0AE    300B     MOVLW 0xb
       0AF    008F     MOVWF 0xf
    30:                		INT_CPT1++;
       0B0    3001     MOVLW 0x1
       0B1    07F4     ADDWF 0x74, F
       0B2    1803     BTFSC 0x3, 0
       0B3    0AF5     INCF 0x75, F
       0B4    3000     MOVLW 0
       0B5    07F5     ADDWF 0x75, F
    31:                		INT_CPT2++;
       0B6    3001     MOVLW 0x1
       0B7    07F6     ADDWF 0x76, F
       0B8    1803     BTFSC 0x3, 0
       0B9    0AF7     INCF 0x77, F
       0BA    3000     MOVLW 0
       0BB    07F7     ADDWF 0x77, F
    32:                		TMR1IF = 0;		
       0BC    100C     BCF 0xc, 0
    33:                	}	
    34:                }
    35:                void main (void)
    36:                {
    37:                	PORTC  = 0b00000000;	//initialisation PortC
       011    1003     BCF 0x3, 0
       012    3000     MOVLW 0
       013    1803     BTFSC 0x3, 0
    Je dois dire que c'est quelque peu indigeste

  13. #12
    invite7a49d0d5

    Cool Re : Interupt timer 1 en C

    rere ;O]

    en effet ce code asm généré est indigeste ;O]

    et on voit pas de sauvegarde...
    mais on voit pas non plus l'"adresse 4"...

    ps : le plus simple, fait clignoter une led
    avec l'int du Timer1... si elle clignote "bien"...
    c'est que les registres ont été sauvegardé...

  14. #13
    blurpy

    Re : Interupt timer 1 en C

    void interrupt timer (void)

    a la place de juste

    interrupt timer (void)

    et verifie l'adresse de la routine

  15. #14
    RISC

    Re : Interupt timer 1 en C

    Salut,

    Pour une programmation plus "robuste" une petite suggestion :
    Code:
        TMR1IF = 0;   /*  TOUJOURS nettoyer un flag AVANT d'autoriser les interruptions pour éviter de partir aussitot en interruption sur un evenement du...passé */
        TMR1IE = 1;  
        PEIE = 1;             //  Enable Peripheral Interrupts
        GIE = 1;              //  Global Interupt Enable
    2e point :
    Le TIMER1 n'est pas autoreload...il faut donc impérativement le recharger dans l'interruption sans quoi la prochaine interruption se fera après 65536 coups d'horloge TIMER1...
    il faut donc ajouter ces lignes :
    Code:
        TMR1H = (65536 - (300000 / 8)) >> 8;  //  Initialize a 300 ms delay
        TMR1L = (65536 - (300000 / 8)) & 0xFF;
    3e point :
    Le compilateur C doit sauvegarder les registres mentionnés par Vede. Si ce n'est pas le cas, la seule chose que je peux imaginer c'est que le compilateur n'a pas compris que cette fonction est associée à l'interruption, si ta syntaxe de déclaration de l'interruption n'est pas correcte.
    ..Vérifier que le vecteur d'interruption pointe bien sur ta fonction de traitement de l'interruption...

    a+

  16. #15
    thundertom

    Re : Interupt timer 1 en C

    Hello RISC,
    je viens de corrigé ta 1ère remarque, je n'ai pas du tout pensé à l'ordre dans lequel j'initialisait.
    Pour la 2ème, j'ai "corrigé" le reload, je ne l'avais pas mis au début pour ne pas trop chargé un code dont je n'était pas sur.
    pour le dernier point, d'après la doc du compilateur, il fait la sauvegarde et ma fonction est déclarée correctement. Mais ça me turlupine de ne pas pouvoir allé regardé à l'adresse 4 pour voir si c'est réelement fait.

    Pour vede, la LED clignotte =)

  17. #16
    RISC

    Re : Interupt timer 1 en C

    Salut,

    J'ai vérifié sur le compilo HiTech, il sauvegarde bien les registres.

    Tu peux voir le code complet dans la fenêtre Disassembly Listing (le code du Reset et des interruptions se trouve tout à la fin de la fenêtre).

    Ensuite, tu peux aussi vérifier d'autres fenêtres :
    View > Program Memory > onglet [Symbolic] en bas de la fenêtre.

    Tu verras l'astuce du compilateur : la ou se trouve le vecteur, au lieu de sauter à ta fonction il sauvegarde les registres utilisés :
    Code:
     Line  Address  Opcode  Label                Disassembly              
    
         5   0004    00FF          MOVWF 0x7f                             
         6   0005    0803          MOVF STATUS, W                         
         7   0006    00F3          MOVWF 0x73                             
         8   0007    0804          MOVF FSR, W                            
         9   0008    00F4          MOVWF 0x74                             
        10   0009    080A          MOVF PCLATH, W                         
        11   000A    00F5          MOVWF 0x75                             
        12   000B    087E          MOVF 0x7e, W                           
        13   000C    00F6          MOVWF 0x76                             
        14   000D    120A          BCF PCLATH, 0x4                        
        15   000E    118A          BCF PCLATH, 0x3                        
        16   000F    28DE          GOTO my_isr
    Et à la fin de ta fonction, la restauration ;=)

    Code:
       223   00DE    1283  my_isr  BCF STATUS, 0x5                        
       224   00DF    1303          BCF STATUS, 0x6                        
       225   00E0    1C0C          BTFSS PIR1, 0                          
       226   00E1    28E3          GOTO 0xe3                              
       227   00E2    28E4          GOTO 0xe4                              
       228   00E3    28E9          GOTO 0xe9                              
       229   00E4    100C          BCF PIR1, 0                            
       230   00E5    3001          MOVLW 0x1                              
       231   00E6    00F8          MOVWF 0x78                             
       232   00E7    3000          MOVLW 0                                
       233   00E8    00F9          MOVWF 0x79                             
       234   00E9    0876          MOVF 0x76, W                           
       235   00EA    00FE          MOVWF 0x7e                             
       236   00EB    0875          MOVF 0x75, W                           
       237   00EC    008A          MOVWF PCLATH                           
       238   00ED    0874          MOVF 0x74, W                           
       239   00EE    0084          MOVWF FSR                              
       240   00EF    0873          MOVF 0x73, W                           
       241   00F0    0083          MOVWF STATUS                           
       242   00F1    0EFF          SWAPF 0x7f, F                          
       243   00F2    0E7F          SWAPF 0x7f, W                          
       244   00F3    0009          RETFIE                     
                
       245   00F4    3031  TMR1Setup MOVLW 0x31
    a+

Discussions similaires

  1. save et restore pour interupt en c pour pic
    Par vinowan dans le forum Électronique
    Réponses: 3
    Dernier message: 18/03/2010, 10h02
  2. plusieur interupt sur pic16F628A
    Par vinowan dans le forum Électronique
    Réponses: 3
    Dernier message: 03/02/2010, 09h11
  3. timer
    Par invite04c4fc21 dans le forum Électronique
    Réponses: 2
    Dernier message: 24/02/2007, 13h00
  4. Timer....??
    Par bimo dans le forum Logiciel - Software - Open Source
    Réponses: 14
    Dernier message: 15/09/2006, 15h18
  5. Timer
    Par invite7814d6c5 dans le forum Électronique
    Réponses: 3
    Dernier message: 13/04/2006, 14h36
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...