Initialement prévu pour tester des fonctions du microprocesseur STM32F103 en utilisant le module Maple Mini clone, ce projet est vite devenu inexploitable parce que la dernière application finissait par occulter les autres réalisées auparavant. Pour y remédier et parce que toutes les applications ne peuvent pas fonctionner en même temps, il a fallu réorganiser le code en fonctions indépendantes et sélectable par l'utilisateur.
Les fonctions USART1 et CDCACM sont installées par defaut. Il est possible de sélectionner les fonctions suivantes:
Ce document présente les diiférentes fonctions réalisées.
Le module utilisé pour ce projet est le Maple Mini clone, mais le module Bluepill peut faire la même chose en adaptant certaines entrées sorties. Par contre pour passer sur une autre plateforme ce sera plus compliqué, car une grande partie du code sert à initialiser les périphériques du microprocesseur.
Noter que les entrées sorties sont imposées par le périphérique utilisé.
Pour comprendre le code, Il est bien sûr conseillé d'avoir la documentation du constructeur RM0008 Reference manual.
Le programme implémente un interpréteur de commandes permettant d'accéder aux fonctions générales, que l'on retrouvera d'une application à l'autre :
La commande C prend comme paramètre l'index de la fonction dans la table des fonctions. Par exemple, pour démarrer l'affichage de l'heure, exécuter :
C0
Lorsque l'on ne sait pas quelle fonction utiliser, on peut toujours afficher l'heure, la date et la température si on a un ds18b20 sous la main.
* C0A -> p = A display to console * C0B -> p = B display to lcd * C0G -> p = G temperature display to lcd * C0O -> p = O send to cdcacm
La fonction readadc peut être utilisée en 2 modes: un mode lent pour lire une tension d'un circuit ou d'un capteur analogique sur un ou plusieurs canaux et un mode rapide où adc1 et adc2 échantillonne simultanément chacun un canal.
La fonction est cadencée par l'interruption à 100 Hz générée par le systick handler qui décrémente un compteur rdadc_rate initialisé par la valeur introduite par la commande T multiplié par 100.
* C5AC0C17T20 -> p = AC0C17T20 -> channel 0 + channel 17 Vref every 20s
Il est possible, par la commnde N, de spécifier le nombre d'échantillons composant la mesure, qui par défaut est 16, afin d'effectuer une moyenne.
Dans le mode rapide, le cadencement est effectué par le timer 3 qui produit le signal TRGO qui va déclencher la conversion ADC sur ADC1 et ADC2. L'ADC est configuré pour que son signal EOC de fin de conversion déclenche le dma 1 channel 1 qui va transféré le contenu du registre ADC1_DR vers un buffer en mémoire. Le dma provoque 2 interruptions, une lorsque le buffer est à moitié plein et l'autre quand il est complètement plein. Le code dans l'interruption transfère les données du demi buffer vers l'USB cdcacm et qui sont accessibles, sur une machine hôte, sur le port /dev/ttyACM0. Noter que ADC1_DR contient en fin de conversion le résultat de ADC1 et ADC2.
* C5BC0C1F8000 -> p = BC0F8000 -> channel 0 + channel 1 triggered by timer TIM3_TRGO at 8kHz
Pour tester un fréquencemètre, quoi de mieux que de se créer un générateur en utilisant, par exemple, le timer 3 sur le port PA7 signal TIM3_CH2.
Le timer 3 est utilisé en timer et défini dans gentim3.c. Il compte les impulsions de l'oscillateur interne divisées par le prescaler et le diviseur (le compteur lui même), qui pilote l'output compare, fonctionnant en mode PWM1 et pilotant le port PA7 signal TIM3_CH2.
La sélection de fréquence se fait par une des commandes suivantes:
C3F100 -> p = F100 => sélection fréquence 100 Hz ou C3P35D19 -> p = P35D39 => prescaler 35 et diviseur 39 sélection => fréquence 50 kHz
Dans la première commande C3 est le sélecteur de fonction gentim3 et F100 La sélection de fréquence à 100 Hz. Dans la deuxième on trouve le sélecteur C3 un prescaler de 35 et un diviseur de 39. Ce qui donne une fréquence de 72 Mhz / 36 / 40 = 50 kHz. Noter que les registres prescaler (PSC) et diviseur (ARR) doivent contenir la valeur - 1 pour diviser par la valeur.
Les timers 1, 2 et 4, dans gentim1.c, gentim2.c et gentim4.c, fournissent la même fonctionnalité respectivement sur les ports PA8 signal TIM1_CH1, PA1 signal TIM2_CH2 et PB6 signal TIM4_CH1
C1F100 -> p = F100 => sélection timer 1 fréquence 100 Hz C2F100 -> p = F100 => sélection timer 2 fréquence 100 Hz C4F100 -> p = F100 => sélection timer 4 fréquence 100 Hz
Les mémoires eeprom du type at24cxx utilisent le bus I2C pour les opérations d'accès lecture et écriture. Elles peuvent servir pour, par exemple, stocker une configuration qui lue au démarrage remplacerait la ligne de commande.
La connexion de ces mémoires au microprocesseur nécessite une interface dont voici le schéma:
La commande suivante initialise la fonction et definit la taille de la mémoire à 0x8000 octets.
* C6A8000 -> p = A8000
Les sous commandes suivantes permettent de lire et d'écrire la mémoire
* :R read from address 0, len = memory size * :r<addr>_<len> read from address addr, len = len, ex: :r10_100 * :Wwrite string at address 0, ex: Wil fait beau * :w<addr>_<string> write string to address addr, ex: :r10_il fait beau
Cette fonction permet de lire la temperature avec un circuit DS18B20. La position du capteur est définie dans le Makefile et utilise, actuellement, le port PB10 pour le bus onewire et PB11 pour l'alimentation du capteur.
Par défaut la période de mesure est de 10 s, elle peut être ajustée avec la commande C7A20 pour, par exemple, 20 secondes.
C7 # mesure toutes les 10 s C7A60 # mesure toutes les minutes
La fonction fréquencemètre consiste par définition à compter le nombre de cycles du signal d'entrée pendant l'unité de temps, la seconde.
Pour cela, on utilise le timer 2 comme compteur connecté à l'entrée PA0 et utilisant le signal TIM2_CH1_ETR. Le timer 2 est controlé par le timer 1 qui produit un créneau calibré OC1 de 10 s, 1 s, 0.1 s, suivant la gamme choisie. Le timer 2 ne compte que lorsque le créneau OC1 est à 1. La transition 1 à 0 du créneau est la fin de la mesure on peut alors afficher la fréquence mesurée.
Le timer 1 est utilisé en timer, il divise l'horloge interne 72 MHz. On utilise l'Output Compare OC1 pour produire le créneau calibré qui peut être visible sur le port PA0 signal TIM1_CH1. Ce signal est routé en interne vers le timer 2 par configuration.
L'activation du fréquencemètre se fait par une des commandes suivantes:
C8A ou C8B ou C8C => pour le choix de la gamme ou C8AF100 => lance en plus gentim3 à la fréquence 100 Hz
La fonction périodemètre consiste, par définition, à mesurer la durée d'un cycle du signal d'entrée et l'unité de temps est la seconde.
L'entrée se fait sur le port PA1 signal TIM2_CH2 du timer 2, qui va compter les cycles d'une horloge à 1 MHz dérivée de l'oscillateur interne.
On utilise 2 canaux d'input compare ic1 et ic2, tous deux connectés au port d'entrée, l'un, ic2, déclenchant sur le front montant et l'autre, ic1, sur le front descendant. De plus le timer est programmé en mode esclave de façon que le front ic2 reset le compteur, ce qui provoque un évènement update. L'update intervient aussi à chaque débordement du compteur, il faut alors ajouter 65536 au compteur totalisateur. Voir 15.3.6 PWM input mode dans la doc RM0008 de ST.
Le premier compteur totalise entre 2 fronts montants, ce qui donne la période et le deuxième entre le premier front montant et le front descendant, ce qui permet de calculer un rapport cyclique.
La sélection du périodemeètre se fait par une des commandes suivantes:
C9A ou C9B => sélection de la gamme ou C9AF100 => lance en plus gentim3 à la fréquence 100 Hz
L'analyse logique consiste à échantillonner un port à une fréquence au moins 2 fois plus rapide que la fréquence des signaux à observer.
La fréquence d'échantillonnage est fournie par le timer 2 qui va, régulièrement, déclencher le dma 1 channel 2 qui lit le port et transfère la valeur dans un buffer en mémoire. Une interruption est émise lorsque le buffer est plein à moitié et complétement, ce qui permet de transférer, à chaque fois, le contenu du demi buffer vers USB cdcacm. Un programme, sur le host, doit lire les données transmises sur le port USB /dev/ttyACM0 et les stocker dans un fichier pour traitement ultérieur.
Le démarrage du timer 2 est fait, par défaut, par l'ouverture du port /dev/ttyACM0 sur le host. On peut choisir d'utiliser le port PA8 pour démarrer ou arrêter le timer.
La sélection de l'analyseur se fait par une des commandes suivantes:
C10AF1000000 => sélection de la fréquence, trigger sur USB ou C10CF100000 => sélection de la fréquence, trigger sur PA8
Cette fonction permet de la lecture d'une mémoire flash série avec le bus SPI.
* C11 C11 6 id 0xEF14 4 mf 0xEF id 0x4015
Cette fonction est incomplète, elle permet simplement de lire l'identificateur de la mémoire en utilisant le bus SPI. Pour une mémoire Winbond W25Q16DV, le manufacturer id est 0xEF14 et le jedec id est 0xEF 0x4015. Pour un fonctionnalité compléte, un transfert de données entre un host et la carte doit être implémenté.
Cette fonction permet le test du circuit d'horloge RTC ds1302. L'heure du stm32 doit être initialisé au préalable.
C12
Avant d'effectuer un test, le ds1302 doit être initialisé, c'est à dire mis à l'heure, ce qui initialise les registres internes. On enregistre, en même temps, dans la ram sauvegardée le time_t de la date courante. Ceci se fait par la sous commande U. Le ':' introduit la sous commande.
:U
Au bout d'un certain temps, on peut relire l'heure et la comparer à l'heure actuelle. Comme on a sauvegardé la date de départ, on peut calculer la dérive sur une certaine durée.
:R diff time -4493 s in 14195307 s 14195307 s equivaut à 164d 7h 8m 27s
Ici, le ds1302 a pris 4493 secondes d'avance sur l'heure actuelle en 164d 7h 8m 27s. Ce n'est pas très bon !.
Deux autres sous commandes permettent de lire et écrire une chaine de caractères à l'adresse 8 dans la mémoire sauvegardée du ds1302.
:wC8AF10000 :r ds1302 string C8AF10000
Ici la commande enregistrée permet de lancer, au démarrage, le fréquencemètre et le générateur timer 3 à 10 kHz si la variable maple_cfg a pour valeur 2 (voir les cavaliers de configuration).
Les générateurs, présentés précédemment, ne peuvent pas fournir toutes les fréquences, mais il est possible d'en élargir le nombre en utilisant une modulation d'une porteuse F0 par une fréquence F1 à l'aide d'un montage annexe composé de 2 bascules D et d'une porte ou exclusif, dont voici le schéma:
Pour ce faire, on doit disposer d'une fréquence 2F0 fournie par le timer 2 et d'une fréquence F1 fournie par le timer 3. On recupère sur la sortie Q en 9 une fréquence FD = F0 - F1.
La sélection du générateur de fréquence par différence se fait par une des commandes suivantes:
C13F200000f22500 ou :F100000 => sélection de la fréquence 2F0 :f100000 => sélection de la fréquence F1
Il s'agit ici de générer un signal compatible avec celui de l'émetteur DCF77, permettant de piloter en local une horloge radiopilotée du type WC8708 ou WT87, en cas de non réception dcf.
La génération de la porteuse DCF 77.5 kHz se fait à l'aide de la fonction freqdiff. Le timer 2 génère la fréquence 2F0 = 200 kHz, le timer 3 génère la fréquence F1 = 22500 Hz et l'adaptateur freqdiff la fréquence FD 77.5 kHz.
Le timer 1 et son output compare est utilisé pour générer la modulation accessible sur le port PA8. Il est piloté par le timer 4 utilisé en prescaler qui fournit la fréquence 1000 Hz, car il n'est pas possible d'utiliser le prescaler du timer 1 dans le mode esclave.
A chaque minute, Les bits de modulation sont calculés à partir de l'heure locale theTime ou du RTC et servent à mettre à jour le registre TIM1_CCR1 et l'état souhaité de la sortie PA8 à chaque compare match qui est atteint lorsque le compteur, qui est activé en permanece, égale la valeur du registre TIM1_CCR1. L'état de a sortie PA8 est alors remis à jour par le timer.
Les signaux de porteuse et de modulation sont alors combiner dans un modulateur dont voici le schéma:
Le générateur de fréquence par différence et le modulateur sont cablés sur le même circuit.
Un simple fil connecté sur la prise ANT et entourant l'horloge permet la synchronisation, sans perturber les voisins !.
La sélection du générateur de signal DCF77 se fait par la commande suivante:
C14 => pas de paramètre
Le signal de téléinformation EDF est le signal émis en permanence par le compteur d'électricité. Pour en savoir plus, voir cette page et les documents en références.
Un générateur peut être utile pour tester un récepteur sans avoir à se brancher sur le compteur.
Le générateur consiste en un oscillateur à 50 kHz modulé en ASK (Amplitude Shift Keying) par le signal transmis, qui est une suite de 0 et 1. Lorsque le signal est à 0, le 50 kHz est transmis et lorsqu'il est à 1, le 50 KHz n'est pas transmis.
En fait, le signal est une suite de trames contenant des mots de 10 bits (1 start, 7 bits de donnée, 1 bit de parité paire sur la donnée, 1 bit de stop). Le tout est transmis à la vitesse de 1200 bits/s.
Le timer 2 est utilisé en oscillateur et fournit sa sortie sur le port PA1 signal TIM2_CH2. Il est controlé par le signal OC1 de l'output compare du timer 1 et qui peut être visible (bien que non utilisée) sur le port PA8 signal TIM1_CH1. Le timer 2 n'émet que lorsque OC1 est à 1.
Le timer 1 est piloté à 1.2 MHz par son prescaler, il faut donc 1000 impulsions à son entrée pour générer un temps bit. Pour chaque bit du mot à transmettre, on calcule la valeur à mettre dans le registre CCR1 pour qu'un évènement Output Compare se produise et provoque le changement d'état du signal OC1. On recommence pour les 10 bits, puis on passe au mot suivant.
Une trame est générée en début de séquence et est stockée dans un buffer à la disposition du timer 1. Elle contient les informations statiques similaires à celles fournies par le compteur et des informations qui changent à chaque trame, comme la puissane consommée et la valeurs des compteurs.
On peut observer la trame en bande de base sur le port PA8 signal TIM1_CH1, qui est inversé par rapport à OC1, en y branchant un uart à 1200 ou 9600 bit/s, 7 bits + parité paire. Si la parité gêne, on peut positionner la variable strip_parity à 1.
Pour être conforme au signal en sortie du compteur, il faudrait une adaptation de niveau pour attaquer le récepteur. Mais comme il ne s'agit que de simulation pour essais, on peut aussi strapper l'étage d'entrée du récepteur et avoir le même effet.
Si la fonction est sélectionnée dans le Makefile, l'activation du générateur de téléinformation se fait par la commande suivante:
C15 => pas de paramètre 9600 b/s mode standart C15L => 1200 b/s mode legacy
Cette fonction est une fonction de test du module FatFs permettant d'accéder à un filesystem FAT sur une carte SD/MMC et dérivée du paquet http://elm-chan.org/fsw/ff/ffsample.zip, les modifications consistant à s'adapter au contexte de mymaple. Ce n'est donc pas une apllication en soi, mais un code permttant de s'exercer aux fonctions de FatFs avant de réaliser une application.
La taille du code étant importante, cette fonction n'est pas incluse par défaut.
La fonction est initialisée par la commande suivante. Les sous fonctions peuvent être accédée directement ou préfixée par ':'. La commande '?' liste les commandes disponibles que l'on peut retrouver dans la table HelpMsg du fichier mmcuser.c.
C16 => pas de paramètre mW # pour voir si ça répond STM32F103 test monitor LFN Disabled, Code page: 437 mp 1 # turn power on mi 0 # Initialize disk rc=0 ms 0 # Show disk status Drive size: 1000448 sectors Block size: 128 sectors fi 0 # Force initialized the volume rc=0 FR_OK fs # Show volume status FAT type = FAT16 Bytes/Cluster = 8192 Number of FATs = 2 Root DIR entries = 512 Sectors/FAT = 256 Number of clusters = 62486 Volume start (lba) = 105 FAT start (lba) = 121 DIR start (lba,clustor) = 633 Data start (lba) = 665 Volume name is DLOGGER Volume S/N is 9464-BA2E ...14 files, 51984643 bytes. 0 folders. 499888 KiB total disk space. 449072 KiB available. fl # Show a directory ----A 2019/03/10 07:34 1737799 10-BE_~1.MP3 ----A 2019/03/10 07:35 1651158 DSCF4090.JPG ----A 2019/03/10 07:35 1630462 DSCF4091.JPG ----A 2019/03/10 07:35 1637264 DSCF4100.JPG ----A 2019/03/10 07:35 908288 KIF_4421.JPG ----A 2019/03/10 07:35 903680 KIF_4427.JPG ----A 2019/03/10 07:35 638464 KIF_4428.JPG ----A 2019/03/10 07:35 937984 KIF_4430.JPG ----A 2019/03/10 07:35 915129 KIF_4431.JPG ----A 2019/03/10 07:35 935936 KIF_4432.JPG ----A 2019/03/10 07:35 744960 KIF_4435.JPG ----A 2019/03/10 07:35 916480 KIF_4436.JPG ----A 2006/03/01 12:00 19 INDEX ----A 2019/03/10 07:50 38427020 AUDIO_15.WAV 14 File(s), 51984643 bytes total 0 Dir(s), 459849728 bytes free ...
L'interface utilise le port PB2 / BOOT1, ce qui rend impossible le chargement du programme en flash sans déconnecter l'interface.
Le montage utilise un adaptateur SD/MICROSD vers USB du commerce qui a succombé assez rapidement et est donc réutilisé en support de carte. La carte MICROSD se monte sur l'autre face.
Le schéma proposé ici est un essai de raccordement de différentes fonctions au module maple-mini: carte sd, ds18b20, lm4040, lm35, spi, i2c, usart1, usart3 ...
Mymaple dépend de la librairie opencm3 qui doit donc être installée au préalable. Après avoir téléchargé les sources de mymaple, extraire les sources et compiler avec le compilateur précédemment installé:
tar Jxvf mymaple-20yy.mm.dd.xz cd mymaple-20yy.mm.dd make # maple-mini-clone BLUEPILL=1 make # bluepill make flash # pour telecharger le programme
Il est possible de ne pas embarquer certaines fonctions, cela se passe dans le Makefile.
The mymaple software is licensed under the terms of the GNU General Public License as published by the Free Software Foundation. See the file COPYING in the archive.