Sujets traités:
- Générateur de nombre aléatoire utilisant l'ADC10
- Utilisation de fonctions en assembleur dans un projet en 'C'
- Utilisation du PWM pour contrôler un LED RGB
Générateur de nombres aléatoires
Les générateurs de nombres aléatoires sont très utilisés mais la fonction rand() qu'on retrouve dans la librairie standard 'C' est en fait un PRNG (Pseudo Random Number Generator), c'est à dire une fonction chaotique qui génère une séquence de nombres qui est toujours la même si on démarre avec le même seed. De plus la période d'un tel générateur a une valeur finie, ce qui signifie que la séquence va se répétée identique à elle-même après un certain nombres d'itérations. Un véritable générateur de nombre aléatoire ne peut pas être construit sur un algorithme il doit-être lié à un phénomène réellement aléatoire. Le générateur proposé ici utilise le bruit qui existe dans tout composant électronique pour produire un tel générateur.
Comme mentionné dans un article précédent les msp430 qui sont équipés d'un périphérique ADC10 ont aussi une sonde de température interne. Cette sonde est constituée de 2 diodes en série alimentées par un courant constant. Hors comme tout composant électronique chacune de ces jonctions génère un certain niveau de bruit aléatoire. Comme il y a deux jonctions en série ces bruits s'additionnent. En plus du bruit généré par cette sonde le source qui sert de voltage de référence pour l'ADC a aussi son propre bruit. De plus il faut ajouter le bruit électromagnétique généré par le CPU et de sources externes. Tout ça fait que lorsqu'on fait une lecture avec le convertisseur analogue/numérique les bits les plus faibles fluctuent aléatoirement d'une lecture à l'autre. Lors d'une utilisation normale de l'ADC10 on prend la moyenne de plusieurs lectures pour éliminer ce bruit.
Pour notre générateur aléatoire au contraire on veut se servir de ce bruit pour générer des entiers 16 bits qui auront on l'espère une distribution réellement aléatoire et non répétitive.
Le générateur utilisé dans le démo suivant utilise donc la sonde de température en faisant une série de lectures et en construisant une entier à partir du bit le moins significatif de chaque lecture car c'est celui qui est le plus susceptible de varier aléatoirement puisque son poids ne représente que Vref/1023. Pour un Vref de 1,5 Volt il a donc une valeur de 1,5 millivolt.
Pour obtenir un entier de 16 bits ont fait donc 16 lectures et pour chacune d'elle on ne garde que le bit le plus faible. On accumules les bits dans une variable par décalages successifs.
Le démo utilise ces nombres aléatoires pour changer à intervalle régulier la couleur d'un LED RGB qui est branché sur P2.0, P2.1 et P2.3. Le deuxième timer TA1 est utiliser en mode comparateur pour généner 3 signaux PWM sur ces broches.
Assemleur dans un projet en C
Inspiré par le document slaa338.pdf trouvé sur le site de Texas Instruments, j'ai adapté la version assembleur trouvé dans le code de TI pour l'utiliser dans ce démo. C'est une bonne occasion de voir comment on peut utiliser des routines en assembleur dans un projet en C.
Lorsqu'on ajoute un fichier dont l'extension du nom est .asm dans un projet en C il est reconnu par l'IDE comme un fichier en assembleur.
Conventions à respecter
Pour que ça fonctionne sans problème il faut respecter les conventions de registres et d'appel de sous-routines.
- Les registres R12-R15 sont réservés pour les arguments et la valeur retournée par la routine. Dans notre exemple la fonction en assembleur adc_rand, n'a qu'un seul argument: le nombre de bits que doit avoir le nombre aléatoire généré. Lorsque la fonction est appellée à partir du programme principal cet argument se retrouve dans R12. S'il y avait un deuxième argument il serait dans R13, le troisième dans R14 et le quatrième dans R15. S'il y en a plus de 4 les suivants sont sur la pile.
- Si votre fonction en assembleur utilise les registres R4-R10, elle doit les sauvegardés sur la pile avant de les modifiés et les restaurés avant de quitter.
- La fonction retourne sa valeur dans les registres R12-R15, les même qui servent à recevoir les arguments. Un entier 16 bits est retourné dans R12, un 32 bits dans R12,R13 et un 64 bits dans R12-R15. R12 a le poids le plus faible.
- Un fichier d'entête 'C' peut-être utilisé en mettant son nom dans dans une directive .cdecls
- Votre code assembleur se retrouve dans la section .text
- Les variables et fonctions exportées sont déclarées comme .global et les externes importées de la même façon.
- Si des variables sont définies dans le fichier en assembleur elle doivent l'être dans une section .data pour les variables qui sont initialisées et une section .bss pour les autres.
Test de différentes options
J'ai écris une version en C de la routine adc_rand et j'ai testé les 2. Au départ ma version en 'C' utilisait une interruption et le mode LPM0 mais j'ai constaté que les nombres générés étaient moins aléatoires que pour adc_rand. J'ai donc modifié la fonction pour qu'elle n'utilise pas les interruptions et le mode LPM0 et le résultat est semblable la version en assembleur. Je pense que le fait de mettre le MCU en mode LPM0 réduit le bruit et que la lecture est donc plus stable d'où la moins bonne distribution des nombres avec cette version. Pour cette application il est bon d'avoir du bruit.
Contrôle d'un LED RGB par PWM
Le msp430G2553 a deux minuteries de 16 bits munies chacune de 3 comparateurs. Ces minuteries peuvent-être utilisées en mode capture ou comparateur. En mode capture il s'agit de compter des impulsions durant intervalle de temps fixe. En mode comparateur un registre est incrémenté et sa valeur comparée à celle des 3 registres comparateurs à chaque cycle d'incrémentation. Lorsque les valeurs sont égales, dépendant du mode de fonctionnement, il y en a 4, un état est altéré. Le résultat de la comparaison peut-être utilisé pour altérer l'état d'une broche de sortie sans intervention logiciel. Mais dans ce démo les broches qui alimentent la LED sont contrôlées en logiciel. La minuterie est programmée pour que lorsque le registre TAR atteint la valeur d'un des 3 registres CCR une interruption est déclenchée. a l'intérieur de cette interruption l'état de la broche de sortie est mise à zéro. Lorsque le registre TAR déborde une autre interruption est déclenchée qui elle sert à débuté un nouveau cycle PWM en mettant les 3 anodes de la LED à 1. La période du cycle PWM est de SMCLK/65536 soit 8000000/65536=122Hz.
Il y a 2 vecteurs d'interruption affectés à chaque minuterie. Le premier vecteur est déclenché lorsque TAR==TAxCCR0. Le deuxième vecteur se déclenche pour débordement de TAR, TAR==TAxCCR1 et TAR==TAxCCR2. Pour ce second vecteur on distingue la source de l'interruption en faisant la lecture du registre TAxIV.
Dans une chronique ultérieure je vais donner d'autres exemples d'utilisation des minuteries.
Aucun commentaire:
Publier un commentaire
Remarque : Seuls les membres de ce blogue sont autorisés à publier des commentaires.