lundi 8 juillet 2013

msp430 launchpad, partie 4

Dans cette partie j'explore une fonctionnalité particulière du Watchdog timer. Sur la majorité des micro-controleurs que je connais le WDT ne fait que réinitialiser le MCU lorsque son compteur expire. Le WDT+ des msp430 a un mode de fonctionnement supplémentaire qui permet de l'utiliser en mode minuterie qui déclenche une interruption lorsque le compte expire sans réinitialiser le MCU, d'où la signification du + après le WDT. Pour cette expérience le crystal de 32768Hz fournis avec le launchpad doit-être soudé sur la carte car l'expérience consiste à créer une horloge temps réel. Le programme utilise juste un peut plus de 1Ko (1028 octets) et pourrait-être utilisé sans modification sur un msp430g2xxx plus économique que le msp430g2553. Un msp430g2202IN20 ferais aussi bien l'affaire pour moins de la moitié du prix d'un msp430g2553.

Sujets traités:

  • Configuration des condensateurs internes pour l'oscillateur LFXT1.
  • Utilisation du WDT+ comme minuterie.
  • Surveillance de la défectuosité d'un oscillateur.

Comme programme démo j'ai créé une horloge qui affiche les heures et minutes en B.C.D. J'avais déjà beaucoup de LEDs de plantées sur la carte sans soudure suite à mes expériences antérieures, j'ai donc décidé de continuer à les utiliser comme affichage. Comme illustré sur le schéma électronique suivant l'horloge utilise 14 LED, 4 par digit sauf pour les dizaines d'heures qui n'en utilisent que deux.

Horloge à affichage B.C.D.

En gros l'oscillateur interne LFXT1 utilise le crystal 32768Hz branché sur les broches 18 et 19 du MCU. LFXT1 est utilisé comme source pour ACLK qui à son tour cadence le compteur du WDT+. Le WDT+ possède 4 diviseurs: 32768, 8192, 512, 64. Dans cette application j'utilise le diviseur 64 car il faut multiplexer les digits de l'affichage à un fréquence suffisamment élevée pour éviter le scintillement. Avec ce diviseur il y a 512 interruptions par seconde. Le programme est configuré de sorte que la fonction display_time() est appelée à chaque interruption pour afficher un seul digit. La variable q est incrémentée de sorte qu'à l'appel suivant se sera un autre digit qui sera affiché. Le multiplexeur d'affichage fonctionne donc à 512Hz.

En ce qui concerne le crystal installé sur les broches 18 et 19 normalement on devrait aussi installer 2 condensateurs entre Vss et chaque broche pour que l'oscillateur fonctionne. Mais le msp430 a des condensateurs internes. Il y a 4 valeurs de condensateurs: 1pF, 6pF, 10pF et 12,5pF. La sélection de la valeur se fait par les bits XCAPx dans le SFR BCSCTL3. la ligne
BCSCTL3 = XCAP_3;
permet de sélectionner les condensateurs de 12,5pF. Les constantes XCAP_0 à XCAP_3 sont définies dans le fichier d'entête.

La configuration du WDT+ se fait par le SFR WDTCTL et encore une fois le fichier d'entête contient une série de constantes qui simplifient la configuration du WDT+ comme minuterie. Il suffit d'affecter une de ces constantes au registre WDTCTL pour que le minuterie soit correctement configurée:

  • WDT_ADLY_1000 délais de 1seconde. 1 interruption par seconde.
  • WDT_ADLY_250 délais de 250 millisecondes. 4 interruptions par seconde.
  • WDT_ADLY_16 délais de ~16 millisecondes. 64 interruptions par seconde.
  • WDT_ADLY_1_9 délais de ~1,9 millisecondes. 512 interruptions par seconde.
Ces valeurs de délais ne sont valables que si ACLK=32768hz. Donc à intervalle régulier il y aura une interruption sur le vecteur WDT_VECTOR qui sera générée à condition que les interruptions soient activées par _enable_interrupts() et IE1 |= WDTIE; comme c'est le cas dans ce programme.

La documentation des msp430 mentionne que ça peut prendre plusieurs microsecondes avant que l'oscillateur LFTXT1 devienne stable après la réinitialisation du MCU. Il est donc conseillé de contrôler l'état de l'oscillateur en début de programme avant de continuer. Il existe un bit dans le SFR IE1 qui s'appelle OFIE Oscillator Fault Interrupt Enable. Lorsque ce bit est mis à 1, l'indicateur OFIFG passera à 1 si il y a un problème avec un des oscillateurs du MCU. Si les interruptions sont activées l'interruption sera générée sur le vecteur NMI_VECTOR. Dans ce programme OFIE est mis à 1 juste après avoir activé les interruptions. À ce moment il est douteux que l'oscillateur LFXT1 soit stable, donc l'interruption nmi_() sera déclenchée immédiatement. Cette routine d'interruption remet à zéro l'indicateur OFIFG et après un certain délais vérifie son état à nouveau. Le programme va rester dans cette ISR tant que l'oscillateur ne sera pas stable. Étant donné le rôle fondamental que joue cet oscillateur dans le programme il faut attendre qu'il soit stable avant de continuer.

La logique du programme est simple. Une fois que les interruptions et les E/S sont configurées on appelle la fonction set_time() car après une mise sous tension l'heure doit-être ajustée. Le bouton 1 sert à passer d'un digit à l'autre et le bouton 2 à ajuster la valeur du digit sélectionné. On sais qu'un digit est sélectionné parce que son affichage bascule entre la valeur du digit et tous les LED du groupe allumés. Une pression brève sur le bouton 2 incrémente la valeur du digit. Une pression brève sur le bouton 2 passe au digit suivant. Une pression d'au moins une seconde sur le bouton 1 permet de sortir du mode ajustement de l'heure. Lorsqu'en mode normal une pression d'au moins une seconde sur le bouton 1 remet le programme en mode ajustement de l'heure.

La routine de service d'interruption watchdog_timer() en plus d'incrémenter la variable tick fait la lecture des 2 boutons et ajuste les indicateurs booléens associés qui sont maintenu dans la variable btns_flags. La fonction set_time() ne lit pas l'état des boutons, elle ne vérifie que les indicateurs booléens qui sont dans btns_flags.

code source

Prochaine étape, remplacé l'affichage B.C.D. par un affichage LCD 16x2 que j'ai en main.

Aucun commentaire:

Publier un commentaire