samedi 9 décembre 2017

Busy Bee partie 3, PCA suite

Je poursuis mes expériences avec le PCA Programmable Counter Array du EFM8BB10F8G-A-SOIC6 débuté dans la partie 2 de cette série. J'en suis rendu au mode high speed output.

high speed output

D'emblée je dois dire que la documentation fournie par Silicon Labs laisse à désirer. Voici tout ce qu'a à dire le manuel de référence à propos de ce mode de fonctionnement.
À partir de cette information insuffisante j'ai eu de la difficulté à faire fonctionner ce mode malgré mes recherches sur le site de Silicon labs qui ne m'ont pas permis de trouver un exemple d'application spécifique à ce MCU mais seulement la note applicative AN107 qui concerne les MCU C8051Fxxxx. Après de nombreux essais et erreurs j'ai réussi à faire fonctionner le mode high speed output pour faire du PWM 16 bits. Pour cette expérience j'ai utilisé le même montage que pour la partie 1. Dans cette expérience l'intensité de la LED varie selon une fonction triangulaire sur une période de 2 secondes.

Comme on le voie sur le diagramme bloc ci-dessous ce mode utilise un compteur 16 bits constitué de PCA0H:PCA0L et d'un registre de comparaison de 16 bits constitué de PCA0CPHn:PCA0CPLn. Lorsque le compteur atteint la valeur de comparaison la sortie CEXn est inversée. Le compteur PCA0 marche en boucle de 0 à 65535. Donc la période est fixée par la fréquence Fpca qui alimente le compteur PCA0. Si on configure Fsys à la fréquence maximale de 24,5Mhz et qu'on alimente le compteur PCA0 directement à cette fréquence,la fréquence du cycle PWM sera de 24,5e6/65536=373,8Hertz.

Pour faire du PWM 16 bits avec ce mode il faut activer l'interruption sur débordement du Compteur PCA0 et celle du comparateur et la l'intérieur de la routine d'interruption modifier la valeur de comparaison dans PCA0CP. On va garder le même projet que dans la partie 2 mais en retournant dans le configurateur et on va modifier la configuration pour obtenir les valeurs suivantes.

  • clock à la fréquence maximale pour obtenir un Fsys de 24,5Mhz.
  • PCA0 alimenté par Fsys ce qui va nous donner une fréquence PWM de 24,5e6/65536=373,8Hertz. On va activé l'interruption sur débordement du compteur PCA0
  • PCA0, Channel 0 configuré pour le high speed output avec activation de l'interruption sur le comparateur. La sortie est aussi inversée car la broche est configurée en open drain avec la cathode de la LED sur la broche P1.3. Si la sortie n'est pas inversée l'intensitée sera inversement proportionnelle à la valeur de PCA0CP0 et non proportionnelle mais ça va fonctionner quand même.
  • .

On ferme le configurateur pour mettre à jours les fichiers et on va ajouter quelques lignes de codes.

  • Dans le fichier InitDevice.h on va ajouter les constantes suivantes. La valeur de PWM_MIN a été déterminée par essaie et erreur et dépend de la durée de l'interruption. Plus l'interruption met de temps à s'exécuter plus cette valeur est grande.
  • Dans le fichier Interrupts.c on va ajouter du code dans la routine d'interruption générée par le configurateur.
  • Finalement on va ajouter le code pour contrôler l'intensité de la LED dans la fonction main() du fichier pca_experiments_main.c
    On met les instructions à l'intérieur de la boucle while parce que à chaque interruption le MCU sort du mode idle et que c'est à ce moment qu'on modifie l'intensité avant de remettre le MCU en idle.

Fonctionnement

Commençons par la fonction main(). le code tourne indéfiniment dans une boucle while(1){}. La première instruction de la boucle suspend l'exécution de code en mettant le MCU en mode idle. Lorsqu'une interruption se produit le MCU sort du mode idle et lorsque l'interruption se termine le CPU exécute le code qui suis l'instruction PCON0|=1. Ce code débute par un verrou lock. lock est ce qu'on appelle en informatique une variable mutex (i.e. mutually exclusive). Sont rôle est d'empêcher la routine d'interruption d'accéder la variable pwm_val lorsque la routine main() est en train de la modifier. Comme il s'agit d'une variable 16 bits il faut plus d'une instruction machine pour modifier cette variable. Imaginez qu'une interruption se produit entre le moment où la fonction main() a modifié l'octet faible de pwm_val et celui où elle modifie l'octet fort de pwm_val. Si l'interruption fait une lecture de pwm_val la valeur lue sera erronée. Donc avant de lire pwm_val l'interruption vérifie la valeur de la variable lock et ne lie la variable que si lock est à zéro. Ainsi on est certain que la valeur lue est bonne. Donc la variable lock est mise à 1 avant de débuter le bloc d'instructions qui va modifier la valeur de pwm_val qui contrôle l'intensité de la LED. Elle est remise à zéro lorsque la modification est complétée.

À chaque interruption la fonction main() modifie la valeur de pwm_val en ajoutant ou soustrayant la valeur step qui contrôle la vitesse du cycle fade in, fade out. Plus step est grand plus la LED va varier d'intensité rapidement. Dans ce démo le cycle est régler sur 2 secondes. La fonction main() s'assure que la valeur de pwm_val demeure à l'intérieur des limites valides.

Le rôle de la routine d'interruption

Le compteur PCA0 compte en boucle de 0 à 65535. À chaque débordement de PCA0 ainsi que lorsque PCA0==PCA0CP0 l'interruption SI_INTERRUPT (PCA0_ISR, PCA0_IRQn) est déclenchée. S'il s'agit d'une interruption causée par le débordement du compteur PCA0, c'est la première moitié du cycle PWM. On vérifie si la variable pwm_val est disponible. Si c'est le cas on réinitialise la variable locale brightness avec la valeur de pwm_val. Ensuite on affecte la valeur de brightness au registre PCA0CP0 qui détermine l'intensité de la LED. Par contre si l'interruption est causée par PCA0==PCA0CP0,c'est la deuxième moitié du cycle PWM. Alors PCA0CP0 est mis à 0 pour compléter le cycle en inversant à nouveau la sortie P1.3 lorsque le compteur va revenir à zéro par débordement.

Notez que PWM_MIN ne peut être inférieur au délais de réponse de l'interruption car pendant ce délais le compteur PCA0 continue à avancé. Si on initialise PCA0CP avec une valeur trop petite le compteur aura déjà dépassé cette valeur lorsque PCACP0 sera initialisé et le comparateur ne déclenchera pas l'inversion de la sortie. Ce raisonnement vaut aussi pour la valeur PWM_MAX qui est le complément à 1 de PWM_MIN.

Générateur de fréquence avec diviseur 16 bits

Il est possible d'utiliser le mode high speed output pour générer des fréquences. On retourne dans le configurateur pour désactiver l'interruption sur le débordement du compteur PCA0.


On remplace le code dans la routine d'interruption par ceci

Le principe de fonctionnement est le même que pour le générateur de fréquence de la partie 2 sauf que la mise à jour de PCA0CP doit-être faite manuellement dans la routine d'interruption. Ce qui implique encore une fois une valeur minimum pour FRQ_DIV. Par essaie erreur j'obtiens 48 pour cette valeur minimum. Avec le compteur PCA0 alimenté à 24,5Mhz ça donne une fréquence maximale de 24,5Mhz/2/48=255Khz la valeur de fréquence minimale est de 24,5Mhz/2/65535=187Hertz. La granularité, c'est à dire la variation de fréquence entre 2 diviseurs adjacents, est inversement proportionnelle à FRQ_DIV.

Gestion de la consommation

Tous les MCU possèdent un mécanisme de gestion de la consommation électrique. Les EFM8BB1xxx ne font pas exceptions. Quelques explications sur les modes disponibles. Il y en a 4.

  1. Normal, dans ce mode le CPU et les périphériques activés fonctionnent normalement. C'est le maximum de consommation électrique. On peut réduire la consommation en réduisant la fréquence de l'horloge.
  2. Idle, dans ce mode le CPU est désactivé donc aucune instructions n'est exécutée. Par contre les périphériques continues à fonctionner comme ils ont été configurés. On économise donc l'énergie dépensée par le CPU. Ce mode est utilisé dans les applications pilotées par interruption. Sitôt qu'une interruption est déclenchée le CPU se remet en fonction pour exécuter le code de l'interruption. À la fin de l'interruption il ne retombe pas en mode idle il faut l'y remettre. L'exemple ci-haut est un exemple de ce mode de fonctionnement. La dépense d'énergie est principalement celle causée par les périphériques. Dans ce mode la mémoire RAM est conservée et les états du CPU sont conservés. A la sortie de l'interruption c'est l'instruction qui suis celle qui a mis le CPU en idle qui est exécutée.
  3. stop, arrête tous les signaux d'horloges. Donc le CPU et les périphériques nécessitant un signal d'horloge sont désactivés. Par contre les entrés/sorties demeure dans leur état. Donc si une LED branchée sur une broche est allumée elle demeure allumée. Les comparateurs analogiques continus de fonctionner et peuvent-être configurer pour déclencher un reset. La seule façon de sortir de ce mode est par un reset ou une remise sous tension. Notez que si la détection missing clock est activée elle va générer un reset après son délais normal et redémarrer le MCU. Pour garder le MCU en mode stop il faut donc que la détection missing clock soit désactivée. Lorsque le MCU sort de ce mode il exécute le code à partir de l'adresse 0x0000 comme s'il venait juste d'être mis sous tension.
  4. shutdown, semblable au mode stop mais en plus le régulateur de tension du CPU est désactivé. Consommation minimale assurée. Le CPU fonctionne à 1,8 volt et puisque le MCU doit-être alimenté avec une tension entre 2,2 et 3,6 volt il faut un régulation de tension interne fournissant 1,8 volt au CPU.
La figure suivante montre par code de couleur de qui est actif dans chaque mode.

Il n'y a que 2 registres pour gérer la consommation
  • PCON0, Contient les bits IDLE et STOP. Les 6 autres bits peuvent-être utilisés par les application comme indicateurs booléens et sont nommés GF0 à GF5.
  • REGCN0, Il n'y a qu'un seul bit d'utilisé dans ce registre STOPCF. Si ce bit est mis à 1 avant de mettre le bit STOP à 1 alors le MCU va passé en mode SHUTDOWN et seule la broche ~reset ou un cyclage de l'alimentation pourra le redémarrer.

mardi 5 décembre 2017

Busy Bee partie 2, PCA

En lisant le manuel de référence du EFM8BB10F8 mon attention a été attiré par le périphérique PCA Programmable Counter Array. Chaque fabriquant nomme ses périphériques comme sa lui chante d'autres appelleraient ça Advance Capture/Compare. Cependant le PCA possède un mode de fonctionnement que je n'ai pas vue ailleurs. Silicon Labs appelle-ça le mode Frequency output. Dans cette deuxième partie mon objectif est d'expérimenter cette fonctionnalité.

PCA experements

Le PCA possède un compteur 16 bits et 3 canaux comparateurs qui peuvent-être utilisés selon 11 modes. J'ai créé un nouveau projet appelé PCA experements dans simplicity studio.

problème avec le configurateur

le PCA a 3 canaux j'ai choisi le canal 0 pour ma sortie en fréquence. L'entrée/sortie CEX0 peut-être assignée à n'importe qu'elle broche des ports 0 ou 1 mais j'ai découvert qu'il n'y a pas de registres pour sélectionner la broche désirée. Le crossbar choisi lui-même la broche en fonction de celles qui sont disponibles et d'un système de priorité par périphérique1.

Le crossbar assigne les broches par ordre croissant en commençant à P0.0 jusqu'à P1.7 pour les broches qui ne sont pas skipped. L'UART0 par contre est toujours assigné aux borches P0.4 pour TX et P0.5 pour RX. Le périphique SPI0 a la deuxième priorité il sera donc assigné aux broches de plus petite numérotations même s'il est activé après un autre périphérique. Comme dans mon projet je ne configure que CEX0 toutes les broches sont disponibles le crossbar a donc mis CEX0 sur la broche P0.0. Ça ne faisait pas vraiment mon affaire je voulais la sortie sur P1.3. Pour régler le problème j'ai tenté de sélectionner chaque broche l'une après l'autre dans la perpsective Configurator pour mettre la propriété skip à skipped. Le crossbar n'utilise pas les broches marqués skipped. Problème, le configurateur ne me laisse pas sélectionner les broches du port 1, elles sont tracées en gris pâle.

Au diable le configurateur

Au diable le configurateur, on n'est jamais mieux servit que par soi-même. J'ai configuré ce que j'ai pu dans le configurateur et j'ai ajouter le code suivant dans la fonction void SiLabs_Startup (void) du fichier pca_experements_main.c.


void SiLabs_Startup (void)
{
 // empêche le crossbar d'utiliser le port 0.
 P0SKIP=255; 
 // bloc pour le crossbar toutes les broches du port 1
 // sauf P1.3
 P1SKIP=~(1<<3); 
}

L'idée est de skipper toutes les broches des ports 0 et 1 sauf P1.3 obligeant ainsi le crossbar à utiliser cette broche.

A part ça il n'y a rien d'autre à faire sinon d'ajouter une seule ligne de code dans la fonction main. En mode Frequency output, la valeur dans le registre PCA0CPHx détermine la fréquence du générateur selon la formule:

Fcex=Fpca/2/PCA0CPHx
Fpca est la fréquence du signal qui alimente la minuterie du PCA
PCA0CPHx  est la valeur dans le registre PCA0CPHx. 
Ici x représente le canal, i.e. {0,1,2}

int main (void)
{
  // Call hardware initialization routine
  enter_DefaultMode_from_RESET();

 //fréquence de sortie sur Fcex0=Fpca/2/PCA0CP0H
        // Fsys=24,5Mhz/32
 // Fpca=Fsys/12=63802Hertz
 // Fcex0=63802/2/10=3190Hertz
 PCA0CPH0=10;
  while (1) 
  {
    // $[Generated Run-time code]
    // [Generated Run-time code]$
  }                             
}
Pour changer la fréquence il suffit de changer la valeur dans PCA0CPH0. Notez que la plus basse fréquence est obtenue avec la valeur zéro qui correspond à un diviseur de 256. La plus haute fréquence est obtenue avec le diviseur 1 qui donne une fréquence de Fpca/2. Si on utilise Fsys à sa fréquence maximale de 25Mhz et qu'on configure le diviseur du PCA0CPH0 à 1 on obtient une fréquence de sortie de 12,5Mhz. Le fonctionnement du mode frequency output est le suivant. La valeur du registre PCA0L est comparée avec la valeur de PCA0CPL0. Lorsque c'est 2 valeurs sont égales la sortie CEX0 est inversée et le registre PCA0L est rechargée avec la valeur PCA0CPL0+PCA0CPH0. Ainsi le compteur PCA0L doit toujours être incrémenté du même nombre de cycles pour atteindre l'égalité avec PCA0CPL0. Ainsi on obtient une onde carrée.

Expérience #2

Dans le configurateur si on active les interruptions sur PCA0


On doit aussi activé Cycle overflow interrupt

Ainsi que dans l'onglet channel 0 on doit activé la propriété capture/compare flag Interrupt.

Maintenant dans la routine d'interruption du périphérique PCA0 du fichier Interrupts.c on ajoute le code suivant:

SI_INTERRUPT (PCA0_ISR, PCA0_IRQn)
{
 static unsigned char hcycles=0;
 PCA0CN0&=0xfe; // remet à zéro le bit CCF0
 hcycles++;
 if (hcycles==2){
    hcycles=0;
           // truc pour commuter la valeur de PCA0CPH0 entre 10 et 20.
    PCA0CPH0=30-PCA0CPH0;
 }
}
Maintenant la fréquence de sortie du générateur change à chaque cycle entre 3190Hertz et 1595Hertz. Cet exemple peut-être facilement modifié pour fabriquer un modulateur FSK.

Conclusion

Grâce au configurateur et malgré ses défauts on a presque pas eu de code à écrire pour obtenir ce résultat.

  1. pas de récompense pour l'ingénieur qui a imaginé ce système.

dimanche 3 décembre 2017

abeille laborieuse et luciole désespérée

Introduction

Jusqu'à tout récemment je connaissais Silicon Labs pour leur produits radio-fréquences et je ne savais pas qu'ils vendaient aussi des microcontrôleurs. Il vendent entre autre des MCU 8 bits affublés du nom commercial de busy bee que je traduirais par abeille laborieuse plutôt que abeille occupée comme le suggère un certain traducteur en ligne. Il n'existe pas de version DIP de ces microcontrôleurs par contre il existe une version SOIC-16, le EFM8BB10F8G-A-SOIC-16. Très économique, actuellement 0,86cent chez digikey.ca. Évidemment il me fallait aussi un programmeur que Sillicon Labs appelle USB Debug Adapter. Il existe 2 versions de ce débogueur une pour les MCU 8 bits et une autre pour les MCU 32 bits. D'apparence ils sont identiques sauf pour la couleur, à ne pas confondre.

Présentation des Busy Bee

Comme mentionné en introduction il s'agit de MCU1 8 bits. Ils sont basés sur un CPU1 appelé CIP-51 par Silicon Labs. Il s'agit d'une version modernisé et 100% compatible avec le vénérable CPU d'Intel MCS-51 qui était au coeur des premiers microcontrôleurs mise en marché en 1980, les Intel 8051. Intel a abandonné la commercialisation des i8051 il y a longtemps mais de nombreux fournisseurs ont prie le relais. Les Busy Bee sont donc des descendant direct mais plus performant du i8051. Les Busy Bee fonctionnent jusqu'à 25Mhz. Il y a aussi des Universal Bee pour les application USB ainsi que les Laser Bee qui peuvent fonctionner à 72Mhz. Dans cette introduction il sera question du Busy Bee modèle EFM8BB10F8G-A-SOIC16.

Particularités des MCU de la famille Bee

Le CPU a quelques particularités qu'il est bon de souligner par exemple il utilise les 32 premiers octets de la RAM comme 4 banques de 8 registres. Une seule banque est active à la fois. Pour l'assembleur ces registres sont nommés R0 à R7. l'intérêt d'avoir 4 banques se situe au niveau des appels de sous-routines et surtout des interruptions. Le délais de réponse d'une interruption peut-être réduit si elle n'a pas besoin de sauvegarder les registres sur la pile. Elle peu s'éviter cette tâche en utilisant une autre banque de registres. Autre particularité les adresses RAM entre 32 à 48 sont accessibles par certaines instructions au niveau du bit. Pour ces instructions il ne s'agit pas d'octets mais d'un tableau de 128 bits adressable de 0 à 127. Il faut aussi mentionner que même plus économique des Busy Bee possède un multiplicateur en hardware. Je ne connais aucun autre MCU 8 bits à moins de 1$ qui en possède un.

Première étape

Silicon Labs fournis gratuitement l'environnement de développement appelé simpliciy studio. Il faut créer un compte pour le télécharger. Je l'ai installé sur mon laptop qui est en Windows 10 mais comme vous le verrez sur le site il est aussi disponible pour OSX et Linux.

Une fois le logiciel installé on découvre qu'il utilise le compilateur C/C++ de Keil et qu'il faut enregistrer son installation auprès de Silicon Labs pour bénéficier de toutes les fonctionnalités du compilateur gratuitement. Avant de lancer l'IDE2 ne pas oublier de brancher le USB Debug Adapter à l'ordinateur, ainsi il sera vu par l'IDE.

Simplicity studio

Même si cet environnement s'appelle Simplicity Studio ce n'est pas simple à utiliser comme l'IDE de Arduido. Il faut un certain temps pour se familiariser mais heureusement il y a un tour guidé. C'est basé sur l'environnement Eclipse CDT donc plus facile d'accès si vous avez déjà travaillé avec Eclipse. L'environnement utilise le concept de perspective. Selon la tâche à accomplir on passe d'une perspective à l'autre. Dans Symplicity Studio les boutons pour passer d'une perspective à l'autre sont dans la barre d'outils en haut à droite. Il y en a 5, Launcher, Configurator, Simplicity IDE, C/C++ et Debug. Au premier démarrage de l'application on se retrouve dans la perspective Launcher et par la suite dans la perspective visible lors de la fermeture de l'application.

Ma première tentative de créer un projet fut un échec. J'ai eu l'idée de créer un projet vide. Quand Simplicity Studio dit Empty C project il veut vraiment dire projet vide. Lorsqu'on clique avec le bouton droit de la souris sur le nom du projet dans la perspective Simplicity IDE la fenêtre des propriétés du projet s'ouvre. Cette fenêtre contient plusieurs onglets et de nombreuses options dans chaque onglet. Si vous avez choisi empty C project vous devez définir chacun de ces paramètres. Disons que c'est pour les utilisateurs avancés.

On retourne donc à la perspective Launcher et on clique sur le bouton new solution.


On inscris le nom du MCU sur la ligne sous le bouton new solution, EFM8BB10F8G-A-SOIC16. Un dossier jaune apparaît avec le nom du MCU sous lui. On peut renommé le dossier en cliquant bouton droit dessus. Appelons le luciole désespérée

Maintenant on va cliquer sur le bouton new project.

Le nom du MCU qu'on a sélectionné apparaît, on clique sur le bouton next.
On conserve la sélection par défaut soit Simplicity Configurator Program et on appuie encore sur next.
À cette étape on nomme notre projet, les espaces ne sont pas permis dans le nom: luciole_désespérée donc. next
On garde ça tel quel et on clique sur finish. C'est lent avant de passer automatiquement à la perspective Configurator.

Il s'agit d'un outil de configuration visuel. On nous présente le brochage du composant sélectionné pour ce projet. Pour ce projet on va utilisé seulement la broche 8/P1.3. On clique dessus pour la sélectionner. A droite la fenêtre Properties nous permet de configurer cette broche. Pour ce projet on doit avoir la configuration suivante:

On va brancher une LED3 à cette broche on l'a donc nommé ainsi.
En bas de la figure du composant on va maintenant cliquer sur DefaultMode peripherals.
Dans cette nouvelle vue on configure des valeurs par défaut des périphériques. J'ai sélectionné Clock Control et dans les propriétés j'ai choisis pour la propriété Select clock source, Low Frequence Oscillator. Il s'agit d'un oscillateur interne fonctionnant à 80Khz. Pour la propriété Clock Source Divider, j'ai choisi SYSCLK/32.
Ensuite j'ai sélectionné LFOSC
Il s'agit d'activé l'oscillateur et de choisir de diviser sa fréquence par 8 tel qu'indiqué dans la fenêtre properties.
Il nous reste maintenant à désactivé le Watchdog Timer

Problèmes

Lorsqu'on est dans le configurateur et qu'on clique sur PB2 dans le fenêtre Outline la fenêtre properties demeure vide. Hors le registre PB2 est celui qui permet d'activer le crossbar. Le crossbar est le multiplexeur qui permet de sélectionner quel périphérique est relié à quel broche. Il faut qu'il soit activé même si dans cette application on n'utilise aucun périphérique. Heureusement dans la fenêtre Problèmes un avertissement apparaît pour nous dire que le crossbar n'est pas activé. En double cliquant sur cet avertissement la fenêtre propriété du registre PB2 s'affiche et on peut activé le crossbar.

Pour ce projet simple c'est tout ce que nous avons à faire comme configuration mais ça nous évite pas mal de travail de codage manuel. Le configurateur va générer automatiquement le code nécessaire dans le fichier InitDevice.c. Le fichier qui contient l'information de configuration matérielle s'appelle luciole_desespérée.hwconf.

Luciole désespérée

Lorsqu'on travaille pour la première fois avec un MCU il est bon de commencer avec le projet le plus simple qu'on appelle habituellement blinky et qui consiste à faire clignoter une LED. Puisque Silicon Labs a décidé de donner un nom d'insecte à ses MCU, je joue le jeu en nommant mon blinky luciole désespérée. Désespérée parce qu'elle ne se contente pas de clignoter à vitesse régulière mais émet plutôt répétitivement un SOS en morse. Montage super simple pour un projet super simple:

schématique

montage expérimental
Notez que le débogueur n'utilise que 3 fils, GND position 2 sur le connecteur du débogueur, C2CLK position 7 sur le connecteur du débogueur et C2D position 4 sur le connecteur du débogueur. Lors du développement il il n'y a donc que 5 broche du MCU qui sont utilisées, 4=GND,5=+3Volt,6=C2CK,7=C2D et 8=LED. Les broches 6 et 7 sont débranchées lorsque le développement est complété.

Le code source en C

Puisque le configurateur a fait une bonne partie du travail pour nous il ne nous reste que très peu à écrire dans le fichier luciole_desespérée_main.c lui aussi créé par le configurateur.

C'est simple je cré un tableau appelé sos qui contient 4 octets. en fait ce tableau est lu comme une série de bits. Un bit à 0 signifie LED éteinte et un bit à 1 signifie LED allumée. La variable b est incrémentée de 0 à 27 et est utilisée pour lire séquentiellement les bits et lorsque b=28 on réinitialise b à zéro et le cycle recommence. Comme sos est un tableau d'octets on accède le bon octet en divisant b par 8 et le bon bit en prenant le modulo de b par 8. Les bits sont numérotés à l'inverse donc on soustrait le modulo de 7. Le code morse est fait de signaux courts dit et longs dah. Les dah sont 3 fois la longueur des dit. Donc en prenant le signal dit comme unité de temps pour produire un dah il suffit de mettre 3 bits consécutifs à 1. Les 5 derniers bits de la séquence sont a zéro pour produire une pose entre chaque appel.

Pour compiler le projet on utilise le marteau. et pour programmer le MCU avec le fichier binaire on utilise l'icône flèche verte au dessus d'un circuit intégré. Il faut choisir le fichier binaire à programmer.

Le fichier généré utilise 257 octets de mémoire programme et 13 octets de mémoire RAM. On peu demander au compilateur de généner le code assembleur. On va allez dans les propriétés du projet et cocher assembly code dans l'option listing du compilateur Keil.

Maintenant si on recompile on va voir à la fin du fichier luciole_désespérée_main.lst qui se trouve dans le dossier src, le code assembleur. J'ai oublié de mentionner que le configurateur génère 2 configurations une configuration release et une configuration debug. Lorsqu'on modifie les propriétés du projet ça s'applique seulement à la configuration active.

Conclusion

Quelques problèmes se sont présentés lors de cette prise en main de Simplicity Studio.

  • J'ai été capable de créer une variable de type bit mais lorsque j'ai voulu convertir le tableau const char sos[4] en const bit sos[28] le compilateur m'a donné une erreur! Il est possible de créer une variable scalaire de type bit mais pas un vecteur de ce type.
  • J'ai essayé d'imbriquer du code assembleur à l'intérieur du code C sans succès. La simple ligne de code suivante:
    
      asm("nop");
    
    suffie pour déplaire au compilateur qui répond avec l'erreur suivante:
    
    *** ERROR C272 IN LINE 50 OF C:\Users\Jacques\SimplicityStudio\v4_workspace\
    luciole_desespérée\src\luciole_desespérée_main.c:
     '__asm' requires src-control to be active
    
    Je n'ai pas encore trouvé la solution de ce problème.
  • Lorsque j'essaie de déboguer le programme pour suivre l'exécution en pas à pas la session plante, le programmeur s'appelle pourtant USB Debug Adapter!
    Erreur fatale lorsque j'essaie d'utiliser le débogueur

Bien sur je ne suis encore qu'un néophyte avec cet environnement j'ai encore beaucoup à apprendre.

Petite expérience

J'ai décidé de créer une version plus permanente de la luciole désespérée et de l'alimenter avec une pile lithium CR2032. L'objectif est de voir combien de temps va duré la pile. Le premier décembre à 15:00 EST j'ai mis une pile neuve et je surveille la luciole. Je vais compter le nombre de jours qu'elle va clignoter. Vous avez noté que j'ai inséré une résistance de 1Kohm en série avec la LED pour réduire le courant à 1mA environ. De plus le CPU fonctionne à une fréquence à 312,5Hertz pour réduire la consommation de celui-ci à environ 120µA comparativement à environ 5mA à la configuration par défaut qui utilise l'oscillateur haute fréquence avec un diviseur à 8 ce qui donne Fsys de 3,0625Mhz. Vous avez aussi notez qu'à fréquence de 312,5Hertz je n'ai pas besoin d'un boucle de délais pour prolonger la duré entre chaque bit. En fait à cette fréquence la durée entre chaque bit est d'environ 0,12 seconde. Il résulte donc un code morse facile à lire.


Le montage est fait directement au dos du porte pile. Le MCU est collé à celui-ci avec de la colle chaude et la résistance ainsi que la LED sont collés au dos du MCU avec de la colle cyanate (Creazy glue). D'après mes calculs luciole désespérée devrait clignoter environ 20 jours. Je vais mettre à jour cet article lorsque j'aurai le résultat final.

mise à jour 2017/12/04

J'ai trouvé comment inclure du code assembleur dans un fichier en C. Dans la fenêtre Project explorer, dans le dossier src du projet il faut cliquer bouton droit sur le fichier dans lequel on veut inclure du code assembleur et dans le menu surgissant il faut sélectionner Properties.

Dans les options générales il faut cocher l'option Generate assembly SRC from "*.c" file.
Pour inclure du code assembleur dans le fichier en question il encadrer les instructions assembleurs par les directives #pragma asm/#pragma endasm.
Curieusement le fait d'ajouter 2 instructions nop a fait passer la taille du code binaire de 257 octets à 268 octets alors que chacune de ces instructions n'occupe qu'un octet.

J'ai trouvé la solution sur le site de Keil dont l'aide est beaucoup plus complète que l'aide qui viens avec simplicity studio.

mise à jour 2017-12-17

La luciole s'est éteinte au cours de la nuit. Elle aura donc vécue moins de 16 jours. 4 de moins que ce que j'avais estimé sur la base d'une capacité de la pile de 240mah. Possiblement que la pile avait une capacité inférieure à celle utilisée pour mon calcul. La pile utilisé était sans spécification et j'avais utilisé la valeur d'une marque connue.


  1. MCU signifie Micro Controller Unit, tandis que CPU signifie Central Processing Unit. Il ne faut pas confondre les deux. tout MCU a en son coeur un CPU mais ne se limite pas à celui-ci elle possède aussi de la mémoire et des périphériques programmables.
  2. IDE Integrated Development Environment est une application utilisée pour le développement de logiciel qui contient un éditeur de texte mais aussi le support intégré au compilateur ainsi que d'autre outils nécessaire à la réalisation d'un projet. Il permet donc d'écrire le code source, de le compiler, de l'injecté dans le microcontrôleur et aussi de le déboguer sans avoir à sortir de l'environnement. D'où son nom d'environnement intégré.
  3. LED Light Emitting Diode ou Diode Electro Luminescente en français.