[Programmation] MSP430 : Timer
Répondre à la discussion
Affichage des résultats 1 à 21 sur 21

MSP430 : Timer



  1. #1
    harchi01

    MSP430 : Timer


    ------

    Bonjour,

    Dans le cadre d'un projet, je dois faire tourner un moteur pas à pas, que j'ai programmé comme ci-dessous. Le moteur doit effectuer 4 positions pour faire un tour complet (que je répète à l'infini). Entre chaque position, j'ai mis un délais, mais ce n'est pas une très bonne solution. A la place, je souhaiterai mettre en place un timer, pour qu'après chaque coup d'horloge, la position suivante se déclenche.

    Le problème, c'est que j'ai eu qu'un document pour m'expliquer les timers, mais je ne comprends pas. Dans ce doc, j'ai un exemple se rapprochant de mes exigences, mais je ne le comprends pas certaines parties : comment je peux dire à mon programme, d'effectuer la position suivante après qu'il ai vu un coup d'horloge ?

    Ce que je voudrais c'est :
    1. Régler les conditions de mon timer
    2. Faire tourner mon moteur à la position 1
    3. Appeler mon timer
    4. Faire tourner mon moteur à la position 2
    5. Appeler mon timer
    ...


    J'espère avoir été assez claire.
    Amicalement,

    Code:
    void Moteur_PAP_Unipolaire_Sequenceur(void)
    {
    while(1)
    {
        // Position 1
    
        P2OUT |= 0x1B;
        P2OUT &= 0x1B;
        _delay_cycles(10000);
    
        // Position 2
    
        P2OUT |= 0x1E;
        P2OUT &= 0x1E;
        _delay_cycles(10000);
    
        // Position 3
    
        P2OUT |= 0x36;
        P2OUT &= 0x36;
        _delay_cycles(10000);
    
        // Position 4
    
        P2OUT |= 0x33;
        P2OUT &= 0x33;
        _delay_cycles(10000);
    
    }
    }
    Exemple : allume la LED rouge si la durée entre 2
    fronts montants (=période) sur P1.1 est
    supérieure à 40 ms (sinon l’éteint)

    Code:
    #include <msp430.h>
    unsigned int memo_capt=0;
    unsigned int capt;
    unsigned int diff_capt;
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD;
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;
    TA0CTL |= TASSEL_2 + MC_2; // source horloge SMCLK + mode continu
    TA0CCTL0 |= CM_1 + CCIS_0; // front montant + CCI0A
    TA0CCTL0 |= CAP + CCIE; // mode capture + autorisation interruption
    P1DIR |= BIT0; // P1.0 (LED rouge) en sortie
    P1DIR &= ~BIT1; // P1.1 en entree
    P1SEL |= BIT1; // fonction entree capture sur P1.1 (TA0.CCI0A)
    P1SEL2 &= ~BIT1; // fonction entree capture sur P1.1 (TA0.CCI0A)
    __enable_interrupt();
    while(1);
    }
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void ma_capture(void)
    {
    capt = TA0CCR0;
    diff_capt = capt - memo_capt;
    memo_capt = capt;
    if(diff_capt>40000)
    P1OUT |= BIT0;
    else
    P1OUT &= ~BIT0;
    }

    -----

  2. #2
    Antoane
    Responsable technique

    Re : MSP430 : Timer

    Bonjour,

    As-tu bien compris le principe du timer ?
    C'est simple : une fonction particulière ("routine d'interruption") est appelée (i.e. exécutée) à intervalles réguliers. Le temps s'écoulant entre deux appels dépend du paramétrage du timer (fréquence d'horloge et seuil de déclenchement de l'appel). Ces paramètres sont réglés une fois au début du programme, puis le timer en lui-même "travaille tout seul" et appellera la routine d'interruption à intervales réguliers.
    La routine d'interruption pour le timer A est "__interrupt void Timer_A_CCR0_ISR(void)".

    As-tu compris comment fonctionne le code que tu donnes ?
    Je trouve ce code pour faire clignoter une led plus intuitif :
    Code:
    #include <msp430.h>
    #define BLINKY_DELAY_MS 500 //Change this as per your needs
    
    void initTimer_A(void);
    void delayMS(int msecs);
    
    unsigned int OFCount;
    
    int main(void)
    {
    	WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
    	P1DIR |= BIT0; //Configure P1.0 as Output
    
    	//Set MCLK = SMCLK = 1MHz
    	BCSCTL1 = CALBC1_1MHZ;
    	DCOCTL = CALDCO_1MHZ;
    
    	initTimer_A();
    	_enable_interrupt();
    
    	OFCount  = 0;
    	TACCR0 = 1000-1; //Start Timer, Compare value for Up Mode to get 1ms delay per loop
    	/*Total count = TACCR0 + 1. Hence we need to subtract 1.
    	1000 ticks @ 1MHz will yield a delay of 1ms.*/
    
    	while(1);
    }
    
    void initTimer_A(void)
    {
    	//Timer Configuration
    	TACCR0 = 0; //Initially, Stop the Timer
    	TACCTL0 |= CCIE; //Enable interrupt for CCR0.
    	TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
    }
    
    //Timer ISR
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
    	OFCount++;
    	if(OFCount >= BLINKY_DELAY_MS)
    	{
    		P1OUT ^= BIT0;
    		OFCount = 0;
    	}
    }
    La méthode sera la même pour le pas-à-pas, à ceci près que la routine d'interruption sera un peu plus complexe car il y a plus de deux états. Une solution consiste à créer une machine à états pour laquelle l'état _X correspond à la position_X, pour X compris entre 1 et 4. A chaque nouvel appel de la fonction d'interruption, il s'agit alors d'incrémenter la valeur de la variable codant l'état courant et d'appliquer les bons signaux en sortie.
    On doit pouvoir faire en utilisant directement le registre de sortie comme mémoire, mais pas sur que ce soit plus simple ou plus élégant.

    Quel µC utilises-tu ?
    Dernière modification par Antoane ; 02/03/2021 à 16h06.
    Deux pattes c'est une diode, trois pattes c'est un transistor, quatre pattes c'est une vache.

  3. #3
    harchi01

    Re : MSP430 : Timer

    Hello,

    Merci pour ta réponse.

    Ce que je ne comprends pas, c'est quand faire appel à mon programme.
    Si je reprends ton code, je vais ajouter des commentaires pour montrer ce que je pense avoir compris.
    Code:
    [...]
    void initTimer_A(void)
    {
    	//C'était déjà écrit, mais c'est la configuration du timer
    
    	TACCR0 = 0; //Initially, Stop the Timer
    	TACCTL0 |= CCIE; //Enable interrupt for CCR0.
    	TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
    }
    
    //Fait appel à la fonction d'interruption. C'est à dire, qu'à chaque coup d'horloge, les actions à l'intérieur de la fonction Timer_A_CCRO_ISR vont s'exécuter.
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
    	OFCount++;
    	if(OFCount >= BLINKY_DELAY_MS)
    	{
    		P1OUT ^= BIT0;
    		OFCount = 0;
    	}
    }
    Donc dans mon cas, je peux faire :

    Code:
    int cpt =0;
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
    	switch (cpt)
    
            {
               case 0 ; 
               // position 1
                Cpt++;
                break;
    
                case 1 ; 
               // position 2
                Cpt++;
                break;
    [...]
    }
    Pour appliquer les signaux en sortie, j'utilise pas de mémoire. Ca me prend 2 lignes pour chaque position. Et ça marche bien comme ça

    Sinon, je travaille avec une MSP430.
    Dernière modification par harchi01 ; 02/03/2021 à 20h47.

  4. #4
    harchi01

    Re : MSP430 : Timer

    Re

    Je me suis un peu précipité, car ce que j'ai proposé ne fonctionne pas.
    Une question m'est venu en tête, qui à l'air bête. Dans quelle ordre l'algorithme va fonctionner ? Pour moi, on reste dans le main et on ne fait pas appel à notre timer.

  5. A voir en vidéo sur Futura
  6. #5
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Bonjour,
    Tes commentaires sont bons et c'est bien comme cela que ça va se passer. A chaque débordement du Timer, le programme principal (main) s'arrête là il se trouve et exécute ce qui se trouve dans __interrupt void Timer_A_CCR0_ISR(void) puis le micro repart dans le programme principal.

    #pragma vector = TIMER0_A0_VECTOR signifie au compilateur de faire pointer la fonction en dessous sur le vecteur d'interruption Timer A.

    Après ça, le problème de portée des variables reste entier. Je vois que tu as déclaré cpt (que tu tests avec le switch) en variable globale, ok car sa portée s'étend au fichier mais quand est il de la variable Cpt (que tu utilises dans le switch avec les case) ?

    Penses également à déclarer tes variables globales en volatile sinon tu risques d'avoir des surprises lorsqu'elles sont utilisées par des interruptions.



    ****************************** ******

    Exemple pour l'explication mais nécessite d'avoir bien compris les notions de pile, de tas et de registres de travail pour comprendre :

    Code:
    int i; 
      
    interrupt (TIMERA0_VECTOR) irq_routine(void) // a chaque débordement du TIMERA 
    { 
        i = 42; 
    } 
      
    void func(void) // fonction attendre 
    { 
        i = 0; 
        while (i == 0);  
    }
    1. Lorsque la fonction "func" sera appelée, "i" va être mis dans un registre de travail pour manipulation, donc ce registre sera mis à 0 puis testé avec la valeur 0 dans une boucle while.
    2. Le TIMERA va déborder et la routine d'interruption va s'exécuter en stoppant tout le reste (on empile), l'emplacement mémoire de "i" va valoir 42.
    3. Enfin, on sort de l'interruption, on retourne dans le code de la fonction "func" (on dépile) et le registre de travail qui valait 0, avant, et qui est testé avec la valeur 0 n'a aucune raison de se mettre à jour avec la nouvelle valeur de "i", soit 42 ! Et c'est la boucle infinie.


    Pire encore, si jamais les options d'optimisation sont activées alors GCC va voir tout de suite une comparaison avec la valeur 0 et un registre qui est mis a 0 .... et il risque de retirer la condition qui pour lui ne sert strictement a rien et c'est vrai puisqu'on teste 0 avec 0. Ce problème se règle facilement avec le mot clé volatile qui va forcer le compilateur a aller voir l'emplacement mémoire de la variable "i" à chaque vérification ou manipulation.

    volatile int i;

    Code:
    volatile int i; 
      
    interrupt (TIMERA0_VECTOR) irq_routine(void) // a chaque débordement du TIMERA 
    { 
        i = 42; // grace au volatile, la valeur de i va être mise à jour
    } 
      
    void func(void) // fonction attendre 
    { 
        i = 0; // grace au volatile, la valeur de i va être mise à jour
        while (i == 0);  
    }
    Là où il n'y a pas de solution, il n'y a pas de problème.

  7. #6
    harchi01

    Re : MSP430 : Timer

    Hello,

    Je te remercie pour tes explications.

    J'ai essayé de faire l'algorithme grossièrement, avec l'exemple d'Antoane, mais cela ne fonctionne pas. J'ai un bruit qui sort du moteur, (comme s'il forçait) et il a réalisé une légère rotation.
    J'ai testé séparément ma séquence pour faire tourner le moteur, et ça fonctionne bien.

    J'ai regardé plus en détail le code, mais je ne sais pas où peut-être le problème.


    Code:
    #include <msp430.h> 
    
    
    /**
     * main.c
     */
    
    unsigned int OFCount;
    volatile int cpt = 0;
    int main(void)
    
    {
        P2DIR |= 0x3F; // je déf mes entrées
        WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
    
        //Set MCLK = SMCLK = 1MHz
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
    
        initTimer_A();
        _enable_interrupt();
    
        OFCount  = 0;
        TACCR0 = 1000-1; //Start Timer, Compare value for Up Mode to get 1ms delay per loop
        /*Total count = TACCR0 + 1. Hence we need to subtract 1.
        1000 ticks @ 1MHz will yield a delay of 1ms.*/
    
        while(1);
    }
    
    void initTimer_A(void)
    {
        //Timer Configuration
        TACCR0 = 0; //Initially, Stop the Timer
        TACCTL0 |= CCIE; //Enable interrupt for CCR0.
        TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
    }
    
    //Timer ISR
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        switch (cpt)
        {
    
        case 0 : // Position 1
    
          P2OUT |= 0x1B;
          P2OUT &= 0x1B;
          cpt++;
          break;
    
        case 1 : // Position 2
    
          P2OUT |= 0x1E;
          P2OUT &= 0x1E;
          cpt++;
          break;
    
        case 2 : // Position 3
    
          P2OUT |= 0x36;
          P2OUT &= 0x36;
          cpt++;
          break;
    
        case 3 : // Position 4
    
          P2OUT |= 0x33;
          P2OUT &= 0x33;
          cpt=0;
    }
    }

  8. #7
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Bonjour,
    A chaque débordement de TIMER la fonction __interrupt void Timer_A_CCR0_ISR(void) se lance. Imaginons que le TIMER déborde toutes les secondes alors il va se passer ceci toutes les secondes.

    Code:
     
    ...
    ...
        case 0 : // Position 1
    
          P2OUT |= 0x1B;
          P2OUT &= 0x1B;
          cpt++;
          break;
    ...
    ...
    Le passage de P2OUT de 1 à 0 va être super rapide puisque les instructions se suivent. Ensuite il faudra attendre la prochaine seconde pour revoir passer P2OUT de 1 à 0 en un éclair.

    Et ce que tu es sur que c'est le comportement que tu souhaitais ?
    Là où il n'y a pas de solution, il n'y a pas de problème.

  9. #8
    harchi01

    Re : MSP430 : Timer

    Bonsoir,

    Je n'ai pas bien compris. Ces deux lignes permettent d'écrire 0001 1011 sur ma sortie. Donc oui, je veux les exécutés à la suite.

    Ce que je veux faire c'est :
    1. coup d'horloge :
    2. Faire ma position 1 (donc P2OUT |= 0x1B; P2OUT &= 0x1B
    3. coup d'horloge
    4. Position 2
    ...

  10. #9
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Bonjour,
    D'accord.

    Je voulais juste mettre le doigt sur ceci : "est ce que se passage hyper rapide de P2OUT |= 0x1B à P2OUT &= 0x1B" est voulu ? Est ce que ce n'est pas trop rapide ? Si P2OUT va vers moteur pas à pas n'est ce pas bien trop rapide pour que le pauvre moteur ait le temps de tourner ?
    Là où il n'y a pas de solution, il n'y a pas de problème.

  11. #10
    harchi01

    Re : MSP430 : Timer

    Bonjour !!

    Je ne croyais pas du tout en cette solution !!
    J'ai mis un délais comme ceci :
    Code:
    P2OUT |= 0x18;
    _delay_cycles(10000);
    P2OUT &= 0x18;
    Et étonnamment, ça fonctionne du feu de dieu !

    J'ai essayé avec avec un delay de 5 000 (5µs si je ne me trompe pas) ça marche très bien. Si je mets 3 000 (3µs), ça marche mais la rotation est plus lent (le bruit est aussi différent, comme si le moteur avait du mal à fonctionner). En dessous de 3 µs, ça ne fonctionne plus.
    Je me demande si ce n'est pas lié au paramétrage de mon timer (peut-être trop rapide). Je vais tester ça ce soir.

    Je refais un point ici plus tard.

    Encore merci !

  12. #11
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Super
    Maintenant si tu prends du recul sur ton code, tu vas voir que tu peux faire quelque chose de bien plus élégant, plus efficace et plus simple a comprendre.


    Demande toi quel est le code minimal qui a besoin d'être dans la fonction d'interruption et qu'est ce que pourrait être mis sous la forme d'une machine a été dans le programme principal. Tu verras que ce _delay_cycles(10000); peut être optimisé en dehors de l'interruption.

    A+
    Là où il n'y a pas de solution, il n'y a pas de problème.

  13. #12
    Antoane
    Responsable technique

    Re : MSP430 : Timer

    Bonjour,

    Je ne comprend pas :
    Je voulais juste mettre le doigt sur ceci : "est ce que se passage hyper rapide de P2OUT |= 0x1B à P2OUT &= 0x1B" est voulu ? Est ce que ce n'est pas trop rapide ? Si P2OUT va vers moteur pas à pas n'est ce pas bien trop rapide pour que le pauvre moteur ait le temps de tourner ?
    P2OUT |= 0x1B ;
    P2OUT &= 0x1B ;

    Sert à mettre l'état du registre P2OUT à 0x00010111.
    L'état du port après la première ligne et avant la 2nd (à savoir 0xXXX1X111, où X désigne un état inconnu) est un état bâtard dont l'effet sur le hardware est inconnu. Il devrait donc durer aussi peu que possible.
    Je pencherais plutôt pour une erreur de hardware, ou de calcul des signaux à envoyer sur les sorties.

    Ou est ce que je rate qqch ?
    Deux pattes c'est une diode, trois pattes c'est un transistor, quatre pattes c'est une vache.

  14. #13
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Bonjour,
    La donnée initiale était que le moteur devait faire 1 tour en 4 grands pas de 90°, j'avais supposé que P2OUT allait sur le driver du moteur et lorsque harchi01 a décrit le comportement du moteur, j'ai compris que son code (un toggle) "P2OUT |= 0x1B ; suivi de P2OUT &= 0x1B ;" lui servait a alimenter la bobine du moteur, puis à l'éteindre mais ça allait tellement vite que le moteur n'a même pas le temps de réagir et encore moins de s'élancer.
    Là où il n'y a pas de solution, il n'y a pas de problème.

  15. #14
    harchi01

    Re : MSP430 : Timer

    Bonjour,

    Désolé pour le retard

    Pour vous répondre plus précisément à ta question Antoane, j'ai un moteur pas à pas à aimant permanent unipolaire. Il est composé de 2 bobines à point milieu. Sur ma carte de puissance, j'ai deux ponts de deux diodes. Je les utilise donc successivement. C’est-à-dire, que j'ai exploite le pont A avec les deux transistors T1 et T2 (correspondant à la première bobine), puis le pont B avec T3 et T4 (correspondant à le deuxième bobine).Img1.png

    Avec mon moteur, j'ai trois façon de le piloter. J'ai choisi celle-ci :
    Img2.png
    Img3.png

    C'est à dire, que mon moteur va avoir 4 positions "de fonctionnement". Qui correspondent à un pas (dans mon cas 1.8°) par position.

    Pour effectuer la position n°1, il faut alimenter la première demi-bobine du pont A (correspondant au transistor T1).
    Pour effectuer la position n°2, il faut alimenter la première demi-bobine du pont B (correspondant au transistor T3).
    Suivant ce principe, nous pouvons décrire le fonctionnement de ce moteur pas à pas avec le tableau suivant :
    Tb1.PNG

    Je fais en 2 messages, car je ne peux pas mettre plus de 5 photos ..
    Images attachées Images attachées  

  16. #15
    harchi01

    Re : MSP430 : Timer

    Si je traduit ce tableau à au MSP430, j'obtiens ça : Tb3.PNG

    Donc je suis obligé de lui renseigner ces positions pour le faire fonctionner. Pour lui assigner les bons états logiques à mes transistors, je suis obligé de lui écrire 2 commandes pour une position. Je l'ai détaillé dans mon rapport, que voici : Img4.PNG

    En espérant que ça vous aura aidé. Attention, j'ai peut-être fait des fautes dans ma démarche et dans mes explications.


    J'ai avancé mon programme, et donc j'ai réussi à enlever les délais :
    Code:
    P2OUT |= 0x18;
    _delay_cycles(10000);
    P2OUT &= 0x18;
    Mon TACCR0 avait un impact sur le fonctionnement de mon moteur. Je l'ai mis à 3000 et cela fonctionne correctement.

    Mais j'ai un autre problème, je n'arrive pas à arrêter mon timer. En effet, je dois réaliser seulement 1 tour (360°) . Ce qui correspond à 50 cycles (de mémoire), qui se trouve dans mon timer.

    J'ai essayé de faire dans mon main :
    Code:
    if ( i > 200) // i est incrément de 1 à chaque position (dans mon switch)
        {
         __disable_interrupt();
        }
    Mais cela ne fonctionne pas car j'ai l'impression que mon i n'est jamais incrémenté dans mon switch.

    J'ai essayé de le voir, en allumant une led, si i<200 et en l'éteignant si i>200.
    Le résultat, la led est toujours éteinte. Donc mon i n'est pas incrémenté ...

    Est-ce que j'utilise la bonne solution ? Et si oui, pourquoi i ne veut pas s'incrémenter ?

    Ps : j'ai épuré mon code, pour qu'il soit plus claire.


    Code:
    #include <msp430.h> 
    
    volatile int cpt = 0;
    volatile int i = 0;
    int main(void)
    
    {
    
        WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
    
        P1DIR |= BIT0;
        P2DIR |= 0x3F; 
    
        //Set MCLK = SMCLK = 1MHz
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
        TACCTL0 |= CCIE; //Enable interrupt for CCR0.
        TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
        _enable_interrupt();
        TACCR0 = 3000; //Start Timer
    
        if ( i > 200)
        {
            P1OUT &= ~BIT0;
            //__disable_interrupt();
        }
        else
        {
    
            P1OUT |= BIT0;
        }
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        switch (cpt)
        {
    
        case 0 : // Position 1
    
          P2OUT |= 0x03;
          P2OUT &= 0x03;
          cpt++;
          i++;
          break;
    
        case 1 : // Position 2
    
          P2OUT |= 0x18;
          P2OUT &= 0x18;
          cpt++;
          i++;
          break;
    
        case 2 : // Position 3
    
          P2OUT |= 0x06;
          P2OUT &= 0x06;
          cpt++;
          i++;
          break;
    
        case 3 : // Position 4
    
          P2OUT |= 0x30;
          P2OUT &= 0x30;
          cpt=0;
          i++;
          break;
    }
    }

  17. #16
    Antoane
    Responsable technique

    Re : MSP430 : Timer

    Bonjour,

    Citation Envoyé par harchi01 Voir le message
    Si je traduit ce tableau à au MSP430, j'obtiens ça : Pièce jointe 434324
    Peux-tu donner un schéma du hardware ?

    Mon TACCR0 avait un impact sur le fonctionnement de mon moteur. Je l'ai mis à 3000 et cela fonctionne correctement.
    TACCR0 est la valeur jusqu'à laquelle le timer compte avant de déclencher une interruption. Plus la valeur est grande, plus le moteur tourne lentement.

    Mais j'ai un autre problème, je n'arrive pas à arrêter mon timer. En effet, je dois réaliser seulement 1 tour (360°) . Ce qui correspond à 50 cycles (de mémoire), qui se trouve dans mon timer.

    ...
    Code:
    ...
    int main(void)
    
    {
    
        WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
    
        P1DIR |= BIT0;
        P2DIR |= 0x3F; 
    
        //Set MCLK = SMCLK = 1MHz
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
        TACCTL0 |= CCIE; //Enable interrupt for CCR0.
        TACTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
        _enable_interrupt();
        TACCR0 = 3000; //Start Timer
    
        if ( i > 200)
        {
            P1OUT &= ~BIT0;
            //__disable_interrupt();
        }
        else
        {
    
            P1OUT |= BIT0;
        }
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
    ...
    }
    Avec ce code, le main est exécuté une fois puis le CPU du µC ne fait plus rien. Il faut que le IF soit dans une boucle infinie.
    Mais il serait plus propre de le faire directement à partir de la routine d'interruption.
    Deux pattes c'est une diode, trois pattes c'est un transistor, quatre pattes c'est une vache.

  18. #17
    harchi01

    Re : MSP430 : Timer

    Bonsoir,

    Je n'ai pas de schéma à te proposer. C'est une maquette qui a été réalisé entre des moteurs, un carte de puissance (L298) et notre MSP430. On a directement eu les numéros les ports pour chaque moteur. Nom : fs258.png
Affichages : 299
Taille : 92,5 Ko

    Merci, j'ai réussi à interrompre mon moteur avec un IF dans la routine d'interruption, comme ceci :
    Code:
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        if (i < 200)
        {
        switch (cpt)
        {
    ...
    Merci encore Antoane et Vincent PETIT pour m'avoir aidé.
    Je vais pouvoir finir mon projet
    Dernière modification par Antoane ; 06/03/2021 à 19h50. Motif: Réparation PJ

  19. #18
    harchi01

    Re : MSP430 : Timer

    Hello,

    Je reviens car je voudrais s'il est possible d'appeler mon timer, comme une fonction. Dans le code, ci-dessous, j'ai une condition If avec un constante (que je voudrais modifier au fur et à mesure de mon main, avec une variable j). Je voudrais quelque chose comme ceci :
    Code:
    appeler_mon timer(int j);
    Code:
    if (i < 50)
    Je voudrais bien avoir quelque chose comme ceci :
    Code:
    if (i < j) // i variable interne à mon timer et j variable externe à mon timer
    Code:
    ...
    {
    
         WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
    
        P2DIR |= 0x3F; // Définir les entrées
       // P1REN|= BIT3;
       // P1OUT |= BIT3;
    
        //Set MCLK = SMCLK = 1MHz
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
        TA0CCTL0 |= CCIE; //Enable interrupt for CCR0.
        TA0CTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
         _enable_interrupt();
        TA0CCR0 = vitesse; //Start Timer
    
    
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        if (i < 50)
        {
              ...
         }
    }
    Est-ce que c'est réalisable ?

    Je vous remercie d'avance.

  20. #19
    Vincent PETIT
    Animateur Électronique

    Re : MSP430 : Timer

    Bonjour,
    Je ne suis pas certain d'avoir compris mais si tu veux que la portée de la variable i soit globale, il suffit de déclarer tout en haut de ton fichier :

    Code:
    volatile int i; // variable globale au fichier et surtout !!! volatile car elle est utilisée dans une interruption
    
    void main (void)
    {
       i = 0; // faut quand même l'initialiser au début
       int j = 25;
    
    
       while(1) // boucle infinie
          if(i > j)
          {
             break; // on casse la boucle dès que i devient supérieur à j, donc à 25. 
          }
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        if (i < 50)
        {
              i++; // j'incrémente i 
         }
    }
    Là où il n'y a pas de solution, il n'y a pas de problème.

  21. #20
    harchi01

    Re : MSP430 : Timer

    Bonsoir,

    Je voudrais contrôler la vitesse et le nombre de tour de mon moteur pas à pas de cette façon :

    Code:
    void M_PAP(int vitesse,int rotation)
    Le problème c'est que la rotation est directement lié à mon timer. Dans celui-ci, il y a une condition SI qui fait "tourner" mon moteur si i<50 (50 correspond à 1 tour).
    Je voudrais plutôt mettre i<rotation.

    Code:
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
    if (i < 50)
    {
    ...
    }
    Donc est-il possible, dans ma fonction M_PAP de faire appel à mon timer, comme ceci :
    Code:
    void M_PAP(int vitesse,int rotation)
    
    {
    ...
        BCSCTL1 = CALBC1_1MHZ;
        DCOCTL = CALDCO_1MHZ;
        TA0CCTL0 |= CCIE; //Enable interrupt for CCR0.
        TA0CTL = TASSEL_2 + ID_0 + MC_1; //Select SMCLK, SMCLK/1 , Up Mode
         _enable_interrupt(int rotation); // Je ne pense pas que ça se déclare comme cela pour faire appel à mon timer
        TA0CCR0 = vitesse; //Start Timer
        
    
    
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(int rotation)
    {
        if (i < rotation)
        {
    ...
        }
    J'espère avoir été plus claire.

  22. #21
    harchi01

    Re : MSP430 : Timer

    Bonjour,

    Je te remercie, avec un peu de réflexion, j'ai réussi en utilisant, comme tu me l'as indiqué, avec une variable globale, comme ceci :
    Code:
    #include <msp430.h> 
    
    volatile int cpt = 0;
    volatile int i = 0;
    volatile int rotationTimer;
    
    void main (void)
    {
        M_PAP(20000,50);
    }
    void M_PAP(int vitesse,int rotation)
    
    {
    
         [...]
    
       // Définition de mon timer
    
        rotationTimer=rotation;
    
    
    }
    
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A_CCR0_ISR(void)
    {
        if (i < rotationTimer)
        {
         [...]
        }
    }

Discussions similaires

  1. Msp430
    Par invite7285b0f8 dans le forum Électronique
    Réponses: 13
    Dernier message: 26/05/2012, 11h56
  2. Faire un timer avec un MSP430
    Par invite6015f114 dans le forum Électronique
    Réponses: 4
    Dernier message: 15/05/2012, 10h46
  3. MSP430 et TUSB3410
    Par invite8fe13b0e dans le forum Électronique
    Réponses: 1
    Dernier message: 21/03/2012, 14h56
  4. Timer du MSP430 F2013
    Par invite40f2798e dans le forum Électronique
    Réponses: 0
    Dernier message: 20/05/2010, 14h10
  5. Programmation en C avec Timer 0 et Timer 1
    Par invite6844fe5f dans le forum Électronique
    Réponses: 43
    Dernier message: 20/04/2010, 13h27
Découvrez nos comparatifs produits sur l'informatique et les technologies.