Introduction
Cette page donne quelques informations sur l'utilisation d'une carte de développement STM32F407VET6 que j'ai utilisé pour réaliser le prototype du chronocomparateur PC-RM4. Si vous êtez arrivé directement sur cette page via le Web, je vous conseille de regarder d'abord la page concernant ce chronocomparateur. A noter que finalement, pour la version définitive avec circuit imprimé, j'ai utilisé une carte DevEBox très proche mais plus facile à implanter sur le circuit. Principal défaut par rapport à celle utilisée pour le prototype : le quartz semble être un modèle moins précis.
J'ai initialement créé cette page pour mes propres besoins. Son objectif était de disposer d'un résumé des informations nécessaires pour le développement du chronocomparateur et d'un historique des essais que j'ai pu faire avec les éventuels problèmes ou échecs. Mais je me suis dit que ça pouvait aussi être utile à d'autres, y compris pour réaliser autre chose qu'un chronocomparateur...
Environnement de développement utilisé :
- Windows 10
- STM32Cube
Matériels utilisés
La carte de développement utilisée pour la réalisation du prototype du chronocomparateur est une ST32F407VET6 avec un écran interface parallèle, le tout, acheté sur Aliexpress. J'ai également utilisé un ST-LINK V2 également acheté sur Aliexpress pour programmer et contrôler la carte.
Les différents éléments se présentent ainsi :
Carte de développement STM32F407VET6 et écran
Carte STM32F407VET6 avec son écran
La carte peut être fournie avec un écran 3.2 pouces en 320x240 pixels, contrôleur ILI9341 (et XPT2046 pour le TouchScreen), qui se connecte directement sur les broches marquées TFT de la carte de développement. J'ai également acheté un écran plus grand avec une meilleure résolution (320x480) et une interface SPI pour faire d'autres essais.
Voici quelques liens qui m'ont été utiles à propos de cette carte en espérant qu'ils resteront actifs...
- https://os.mbed.com/users/hudakz/code/STM32F407VET6_Hello/shortlog/ pour la liste des pins.
- https://stm32-base.org/boards/STM32F407VET6-STM32-F4VE-V2.0.html qui complète bien le précédent lien.
- https://stm32-base.org/boards/ qui est la racine du lien précédent et qui présente pleins de cartes à base de STM32.
- https://www.st.com/en/microcontrollers-microprocessors/stm32f407ve.html#overview, le point d'entrée de ST pour cette carte.
Note : pour rappel, la carte utilisée pour la version sur circuit-imprimé est celle de la figure ci-dessous.
Carte DevEBox
L'écran est également un autre modèle que celui utilisé pour le prototype.
Sonde ST-Link V2
Sonde ST-Link V2
Connexion sonde et carte
La connexion de la sonde ST-Link V2 avec la carte se fait de la façon suivante (points jaune sur l'image) :
- GND sonde sur GND du port JTAG (pin 6)
- 3.3V sonde sur 3.3V du port JTAG (pin 1)
- SWDIO de la sonde sur SWDIO du port JTAG (pin 7, PA13)
- SWCLK de la sonde sur SWCLK du port JTAG (pin 9, PA14)
Sonde ST-Link V2
Il n'est pas utile de connecter RST pour ce que j'ai lu (et je ne l'ai pas connecté).
Attention : le branchement tel que décrit implique l'alimentation par la sonde. Dans ce cas, il ne faut pas brancher d'alimentation externe sur la carte de développement (et donc, la carte ne doit pas être reliée via sa prise USB). Si toutefois vous devez le faire (par exemple, parce que l'alimentation fournie par la sonde n'est pas assez puissante), il faut alors déconnecter le 3,3V de la sonde.
Première mise sous tension
Une fois la connexion de la sonde et de la carte de développement faite, et l'écran branché sur la carte de développement , branchez la sonde sur un port USB. Sur ma configuration, j'ai l'affichage suivanté :
MCUDEV STM34F4
STM32F407VET6 system TEST
mcudev.taobao.com
2015/8/15
KEY0:Read sector 0
SD Card Error / Please Check
Comme je n'ai pas mis de SD Card, l'erreur signalée est compréhensible.
ST Link Utility
Vous pouvez vérifier que vous arrivez à communiquer avec votre sond ST-Link et qu'elle reconnait bien la carte de développement. Lancez l'utilitaire STM32 ST-LINK Utility qui est normalement disponible en téléchargement sur le site de ST Microelectronics.
Sélectionnez "connect to the target". Si vous avez une erreur, commencez par débrancher la sonde de son port USB, rebrancher la et sélectionnez de nouveau "connect to the target". Je fais l'hypothèse que la connexion s'effectue correctement (sinon, je ne sais pas).
L'utilitaire affiche les informations suivantes (certaines dépendent de la sonde, de la carte de développement et du moment ou vous faites la connexion).
Sonde ST-Link V2
Vous pouvez profiter que l'utilitaire est lancé pour faire une mise à jour du firmware de la sonde. Pour ce faire, mieux vaut débrancher et rebrancher la sonde de son port USB. Ceci fait, sélectionnez l'option ST-LINK dans le menu puis firmware update et laissez vous guider.
Le STM32F407
Le STM32F407 est un magnifique microcontrôleur, rapide et offrant de nombreuses possibilités. Pour ce qui me concerne, outre la rapidité et un fonctionnement natif en 32bits, j'ai retenu ce processeur car il disposait de deux timers 32 bits dont j'avais besoin pour réaliser les pesures sur PC-RM4.
Evidemment, la documentation est à l'avenant : la version du datasheet que j'ai utilisée ne fait pas moins de 1700 pages.
Ce datasheet ne pertubera pas les personnes qui ont déjà eu à travailler avec des processeurs modernes : il reprend la présentation habituelle des différentes fonctions telles qu'on les trouve, par exemple, chez Texas Instrument (je prends cet exemple car pour ma part, j'ai pas mal développé sur certains processeurs basse consommation de ce fabricant).
Prendre en main un tel processeur en partant de zéro a de quoi rebuter. Heureusement, ST propose quelques outils qui permettent de traiter le problème de base habituel sur ce genre de processeur : les initialisations et en particulier, les initialisation des horloges. Ce point est présenté dans le chapitre suivant.
Il y a néanmoins quelques points noirs qui sont signalées par pas mal de personnes dont une qui a, pendant un temps, répertorié les erreurs, incohérences et difficultés d'utilisation de différentes versions des datasheet, jusqu'à abandonner.
Une des difficultés que j'ai rencontrée a concerné la gestion des timers. Visiblement, je ne suis pas le seul et je trouve la documentation sur ce point peu abordable et très mal faite, sans compter les erreurs.
Pour information, les timers, qui offrent de nombreuses possibilités, disposent de plus de 20 registres qu'il faut comprendre et initialiser.
Dans mon cas, la difficulté a été de faire fonctionner les registres 32 bits (TIM2 et TIM5) en mode dit gated.
Lorsque j'ai développé PC-RM4, je n'ai pas trouvé d'exemples fonctionnels d'utilisation de ce mode. Par contre, j'ai trouvé de nombreuses questions de personnes qui étaient bloquées et qui malheureusement, n'ont pas eu de réponse.
En théorie, le mode gated est d'une utilisation très simple dans la présentation qui en est faite dans le datasheet : le compteur TIM2 (on prendra celui là comme exemple), alimenté par une horloge, commence à compter sur un signal bas TI1 sous réserve que le bit CEN (qui s'appelle aussi parfois CNT_EN ce qui ne simplifie pas les choses) soit actif dans le registre TIM2_CR1. Il s'arrête de compter lorsque TI1 revient à l'état haut.
La documentation indique que le signal TIF (Timer Interrupt Flag) est positionné lorsque le comptage démarre ou s'arrête.
Sur le graphique de la documentation, on voit aussi le bit CEN positionné à l'état inactif en fin de comptage ce qui implique de le remettre actif pour qu'un nouveau comptage puisse démarrer. On ne sait pas à ce stade si le passage du bit CEN à l'état inactif est fait par le processeur ou par le programme. Disons simplement qu'il est probable qu'il soit fait par le processeur du fait du timing des opérations. Mais la documentation ne le précise pas dans ce chapitre.
Les choses se gâtent lorsque si vous utilisez l'outil de configuration STM32CubeMX (ce qui était mons cas) : la configuration générée ne correspond pas à celle indiquée dans la documentation.
Quelques points utiles pas forcéments clairs dans la documentation :
- Horloges internes utilisées pour les timers : le schéma des bus d'horloges (qu'on trouve en particulier sur STM32CubeMX) montrent que APB2 et APB1 peuvent servir d'horloges aux timers. Mais il faut regarder les registres RCC APB1 et RCC APB2 pour constater que seules, les connexionx de TIM2 et TIM5 à APB1 sont possibles. Dans le cas de PC-RM4, APB1 vaut 84MHz.
- J'ai trouvé dans le fichier stm32f4xx_hal_tim.c que par défaut, les timers étaient reliés à leur APBi respectifs. Donc, l'initialisation par la macro __HAL_RCC_TIMx_CLK_ENABLE() n'est pas nécessaire. En pratique, cette initialisation est faite dans le fichier "stm32f4xx_hal_msp.c" qui est généré par l'environnement et qui comporte un call back pour l'initialisation qui est appelée par la bibliothèque HAL.
A suivre...
Environnement de développement
STM32Cube
J'ai utilisé l'environnement STM32CubeIDE proposé par ST Microelectronics qui s'appuie sur Eclipse. L'avantage théorique est qu'il est adapté au STM32 et qu'il intègre STM32CubeMX pour configurer le processeur et la carte de développement. A noter cependant que STM32CubeMX peut également s'exécuter en dehors de cet environnement. C'est pratique si vous n'utilisez pas STM32CubeIDE, ce qui a été mon cas dans d'autres développements en 2019 car trop de bugs dans STM32CubeIde.
En 2022, la situation s'est améliorée (version 1.9.0). Globalement, j'ai pu en général développer, compiler et debugger sans plantage pendant des heures d'affilées. Mais j'ai eu aussi quelques gros problèmes qui m'ont fait perdre plusieurs heures :
- la configuration de l'espace de travail et des chemins aux sources&nbp;: je n'ai pas réussi à m'en sortir sans modifier directement les sources du projet (fichier ".cproject"). Je ne sais pas si le problème vient d'Eclipse ou de produit ST.
- La génération des sources avec STM32CubeMX : régulièrement, les parties réservées aux inclusions de l'utilisateur étaient supprimées dans les fichiers "main.c/h" et "stm32f4xx_it.c/h".
- Plusieurs fois, l'environnement a carrément supprimé les fichiers du répertoire drivers, là ou sont stockés les ".h" et ".c" des différents fichiers de la bibliothèque HAL en particulier.
J'ai lu beaucoup de complaintes a propos de cet environnement et aussi, des bibliothèques HAL. J'ai mieux compris pourquoi... Un peu tard.
Utilisation de HAL ou pas ?
Si vous développez à l'aide de cet environnement, vous aurez immédiatement à faire un choix : utilisation de la bibliothèque HAL (Hardware Abstraction Level) ou pas.
Evidemment, l'utilisation d'une telle bibliothèque est tentante car elle vous permet d'éviter de faire à la main certaines configurations de registres fastidieuses ainsi que certains contrôles de cohérence... Sous réserve que vous preniez en compte les codes d'erreur de la bibliothèque dans votre programme.
Couplée avec l'utilisation de STM32CubeMX, la partie du programme qui configure le matériel selon vos besoins est générée automatiquement. Pour le reste, un grand nombre de macro ou de fonctions utiles sont immédiatement disponibles.
Pourtant, on peut lire de nombreuses critiques sur cette bibliothèque et beaucoup de développeurs en déconseille l'utilisation. Pour ma part, elle m'a fait gagner du temps sur pas mal de sujet et m'en a fait perdre beaucoup dès que quelque chose ne fonctionnait pas comme prévu. Voici ce que je peux en dire à l'usage :
- HAL permet d'enchainer automatiquement tout un tas de contrôles et d'initialisations. C'est très pratique, surtout quand vous ne connaissez pas bien le microcontrôleur. Mais dès que vous commencez à le connaitre un peu, beaucoup de ces contrôles sont inutiles pour un cas d'usage donné. C'est normal, HAL est prévu pour tous les cas d'usages et doit donc faire ces contrôles. Mais pour un usage donné, cela ajoute pas mal de code inutile.
- Une fois que vous avez commencé avec HAL, il est lourd de revenir en arrière. Or des fois, on aimerait bien !
- HAL introduit une surcouche entre le matériel (donc le datasheet) et votre application. C'est normal, il est fait pour ça. Mais lorsque vous devez vous référer au datasheet, les choses se compliquent car vous ne voyez pas si tel ou tel registre est configuré comme vous le souhaitez. Et là, le plus souvent, il faut aller dans les sources de la bibliothèque de HAL pour savoir ce qui est réellement fait. Ca prend pas mal de temps.
- HAL introduit des renommages qui compliquent encore la situation précédente car on a encore plus de mal à trouver la correspondance entre les objets manipulés par HAL et ceux décrits dans le datasheet... Jusqu'à ce qu'on trouve l'équivalence introduite par le renommage.
Alors, faut-il utiliser HAL ? Je ne sais pas répondre à cette question car ayant démarré avec cette bibliothèque, j'ai continué avec elle.
Ce que je pense est que l'utilité de HAL varie en fonction de l'expérience que l'on a sur le STM32 et sur la bibliothèque elle même.
- Lorsque vous démarrez avec le STM32, HAL vous permet de faire quelques programmes simples plus rapidement qu'en manipulant directement les registres du processeurs.
- Lorsque vous commencez à mieux maitriser le STM32, HAL à tendance à vous poser des problèmes.
- Lorsque vous maitrisez bien HAL et si vous n'avez pas besoin d'optimiser votre code pour des raisons de vitesse d'exécution, alors HAL vous permet d'améliorer votre productivité en terme de codage.
Le problème est que la maitrise du STM32 et celle de HAL n'évoluent pas au même rythme.
Premiers essais avec la carte STM32F407VET6
Afin de ne pas démarrer de zéro comme je l'avais fait pour la carte DiyMore que j'utilisais précédemment, j'ai téléchargé l'archive d'une implémentation de la gestion d'écran (BLACK407VE) disponible sur GitHub.
Pour l'installation, il suffit de recopier l'ensemble des fichiers décompressé dans wotre workspace ce qui créé le projet.
Evidemment, tout ne s'est pas passé sans quelques adaptations, à commencer par la configuration des répertoires (à mettre à jour manuellement dans les propriétés du projet).
Le programme n'était pas compilable. Un peu par hasard, je me suis aperçu que le fichier BALCK407VE.ioc n'était pas à jour par rapport à ma version de l'environnement (il suffit d'essayer de l'ouvrir dans l'environnement de développement et s'il n'est pas à jour, l'environnement vous le signale).
Pour mémoire, ce fichier contient toute la configuration du processeur, l'affectation des pins, des horloges, etc. et est généré automatiquement par STM32CubeMX qui est lancé lorsqu'on clique sur BALCK407VE.ioc.
Si vous êtes dans le même cas que moi, l'environnement vous propose de migrer le fichier vers la nouvelle version de STM32CubeMX ce qu'il faut faire. La migration semble mettre également à jour un certain nombre de librairies.
J'ai alors pu aller un peu plus dans la compilation mais j'ai eu des erreurs dans certaines librairies STM32F4xx_HAL. Après quelques recherches, je me suis aperçu qu'elles ne correspondaient pas complètement à celles disponibles sur GitHub (il manquait des #define). J'ai donc téléchargé les fichier .h erronés.
Je ne sais pas trop bien d'où vient ce problème. Peut-être s'agit-il de résidus d'anciennes versions des librairie. Pour mémoire, ma dernière installation de STM32Cube datait de 2019 et peut-être que certaines mises à jours n'ont pas été effectuées correctement lorsque je l'ai relancé en 2022.
Ceci fait, le programme a pu être compilé sans erreurs ni warnings.
Après avoir vérifié que les ports configurés correspondaient bien à ceux sur lesquels était connecté l'écran, j'ai lancé une exécution du programme de test le plus basique (#define USE_LVGL à mettre en commentaire dans main.c). L'environnement m'a proposé une mise à jour du logiciel de dialogue avec la sonde et ceci fait, le programme s'est téléchargé et s'est exécuté sans problème sur la carte de développement (ce qui m'a un peu étonné !).
J'ai ensuite utilisé le programme de tests plus élaboré auquel on accède en définissant #define USE_LVGL dans main.c. Tout a fonctionné correctement (mais cette fois, j'a été moins étonné ! On s'habitue à tout.).
Cette première étape m'a aidé à démarrer et à prendre en main l'environnement mais je n'ai pas conservé grand chose des sources que j'avais récupéré.
Portage de PC-RM3
L'étape suivante a été le portage du programme développé pour PC-RM3.
Evidemment, ça n'a pas été aussi simple que prévu car en pratique, les bibliothèques bas niveau que j'ai récupéré à droite ou à gauche étaient souvent incomplète et assez mal fichues et surtout, je n'ai pas trouvé un gestionnaire de TouchScreenfonctionnel pour le XPT2046. J'ai donc finalement réécrit la plupart des fonctions de bas niveau. J'aborde le point un peu plus loin.
Après quelques jours, j'ai eu une application fonctionnelle avec l'écran 320x240. Comme il me manquait quelques composants électroniques pour aller plus loin, j'ai décidé d'adapter le programme pour qu'il prenne en compte un écran 480x320 comme celuis don dispose PC-RM3, mais cette fois-ci, en utilisant un bus SPI.
Ca m'a pris beaucoup plus de temps que je l'imaginais mais cela m'a permis de trouver quelques bugs dans la version avec écran 320x240 !
Le résultat est que le programme est proposé à la fois avec un écran 320x240 (bien suffisant et plus facile à installer sur la carte de développement) et d'un écran 480x340 avec bus SPI.
Gestion des écrans
Il y a plusieurs points à considérer dans le choix d'un écran pour cette application :
- La taille de l'écran. Ici, 66x50mm (3,2 pouces) ou 73x48mm (3,5 pouces) selon la définition. En pratique, il y a peu de différences et 66x50mm est largement suffisant.
- La définition de l'écran (320x240 pixels ou 480x320 pixels). Les écrans étant relativement petits, la définition la plus basse est acceptable et suffisante. Evidemment, en 480x320, les caractères sont plus beaux et certains affichages sont améliorés.
- Le bus utilisé pour les communications :
- 320x240 avec contrôleur ILI9341 : l'affichage se fait avec un bus parallèle. De ce fait, il est très rapide. Pour ces écran et ce contrôleur, un affichage complet nécessite l'envoi d'environ 1,2Mbits de données (chaque pixel fait 16 bits).
- 480x320 avec contrôleur ILI9488 : l'affichage se fait avec un bus SPI (pour l'écran que j'ai choisi) c'est à dire, en série. Sachant qu'un pixel nécessite 3 octets, 3,7Mbits, l'affichage est un peu plus lent et nécessite quelques acrobaties pour améliorer la situation. Dans le cas présent, il est fait usage du DMA dès que cela est possible.
Pour le DMA et le STM32F407, il existe un excellent tutoriel sur www.microtechnics.ru/en/stm32cube-spi-and-dma-example/.
- La facilité de connexion avec la carte de développement : il existe des écrans 320x240 pixels qui se connectent directement sur le connecteur prévu. En 2022, je n'en ai pas trouvé pour des écrans 480x320
Le contrôleur de TouchScreen XPT2046
Généralités
Si vous avez des difficultés avec la mise en œuvre du contrôleur XPT2046 (TouchScreen), la suite peut vous intéresser.
En préambule, comme sans doute la plupart des gens, j’ai cherché une implémentation sur le Web. J’en ai trouvé pas mal mais…Beaucoup étaient boguées ou ne compilaient même pas, y compris lorsque le contributeur indiquait que c’était la version qui tournait chez lui…
Dans ce cas, il faut partir de la documentation qui dans ce cas, n’est pas toujours d’une très grande clarté.
De tout ça, il résulte le mode opératoire et les conseils suivants :
- Hypothèse :
- Les communications SPI sont initialisées.
- Un driver existe dans stm32f4xx.it.c. Dans mon cas, il s’agit juste du positionnement d’un booléen (LCD_Pen) pour indiquer qu’une IT a eu lieu.
- Mon utilisation du TouchScreen se fait par test d’état via une fonction qui rend vrai si des données sont valides (avec la valeur de ces données à savoir, X, Y et Z (la pression sur le TouchScreen) ou faux s’il n’y a pas de données valides (X et Y valent 0). La fonction s’appelle TP_readXYZ.
- Certaines données sont disponibles par ailleurs et accessibles par la fonction de gestion du TouchScreen, comme l’orientation courante de l’écran et sa définition en pixel.
- Principes :
- Pour envoyer une commande au XPT2046, il faut qu’il soit sélectionné (CS actif). Il n’est pas utile de le laisser sélectionné lorsqu’on n’a plus de commande à envoyer.
- Pour que le XPT2046 génère une IT, il faut lui envoyer une commande de validation des IT (bit Start + bit IRQenabled). Les IT sont générées même si le XPT2046 n’est pas sélectionné (CS inactif). Cette validation se fait lors de l’initialisation de la bibliothèque qui gère le XPT2046 (TP_Init).
- Lorsqu’une IT a été générée, il faut vérifier si elle provient d’un appui sur l’écran ou s’il s’agit seulement d’un bruit de fond (l’IT est générée par un système analogique. Une détection peut avoir lieu même si on n’a pas appuyé sur l’écran).
- La fonction sous IT appelle une fonction XPT2046_update qui rend vrai si elle a lu des données valides ou faux sinon. Si elle rend vrai, X et Y sont initialisés aux valeurs des coordonnées lues. Sinon, X et Y valent zéro. Cette fonction gère également l'anti-rebond.
- Pour déterminer si les données sont valides, il faut :
- Sélectionner le XPT2046 (CS actif).
- Envoyer les commandes de lecture de Z1 et Z2 pour déterminer la pression sur l’écran. La documentation indique que le fait d’envoyer des commandes peut provoquer des interruptions parasites. Pour chaque lecture, on prendra soin de positionner le bit IRQdisabled dans la commande.
- Vérifier si la pression déterminée par Z1 et Z2 dépasse le seuil d’une pression valide (voir plus loin).
- Si la pression dépasse le seuil d’une pression valide, lire les valeurs de X et Y un certain nombre de fois pour pouvoir calculer une moyenne. Pour chaque lecture, on prendra soin de positionner le bit IRQdisabled dans la commande.
Pour finir, on affecte les valeurs attendues X Y et Z par le programme avec les valeurs lues. Cette affectation dépend de l’orientation de l’écran (portrait, paysage, portrait miroir et paysage miroir). - Ces valeurs lues ne correspondent pas aux valeurs ligne et colonne de l'écran. Il faut ensuite déterminer les facteurs de conversion (mise à l'échelle) pour qu'elles soient utilisables. Et pour cela, il faut faire une calibration.
- Que le seuil soit valide ou non, il faut réactiver les interruptions pour le prochain coup (une commande avec le bit IRQenabled), indiquer que l’interruption a été traitée en positionnant le booléen LCD_Pen à faux et désélectionner le XPT2046 (CS inactif).
- La fonction TP_ReadXYZ permet aux applications de lire les dernières coordonnées capturées non encore lues.
Gestion de la pression
La valeur de la pression dépend de la position en X et Y sur l'écran. Le problème est que pour connaitre X et Y, il faut faire une moyenne sur plusieurs mesures. Mais pour que ces mesures soient valides, il faut qu'il y ait eut une pression !
On peut s'en sortir de la façon suivante :
lorsqu'il n'y a aucune pression, Z1 vaut 0 ou quelques unités et Z2 est maximale (sur mon écran, environ 2000).
Lorsqu'il y a une pression, la valeur de Z1 augmente et peut valoir quelques dizaines à quelques centaines selon la position en X et Y. La valeur de Z2 diminue (de 1000 a moins de 2000 sur mon écran en fonction de la position).
L'algorithme peut alors être le suivant :
- Lecture de Z1 et Z2
- Si Z1 ou (Z2-Z1) sont inférieurs à un certain seuil (Z1_THRESHOLD et Z2_THRESHOLD), alors, on ne prend pas en compte l'appui.
- Sinon, on détermines des valeurs pour X et Y (moyenne sur plusieurs lectures).
- On peut ensuite calculer la pression en fonction de X, Y, Z1 et Z2.
Pour les besoins de l'application, je n'ai implémenté que le premier test de seuil qui est suffisant et qui fonctionne très bien.
Calibration X et Y
En préambule, la plupart des implémentations que j'ai vu inversent les codes pour la lecture de X et Y par rapport à la documentation. En pratique, ça n'a pas d'importance car de toute façon, il faut faire un traitement en fonction de l'orientation. Il ne s'agit pas d'une erreur, juste une curiosité que je signale.
La principale difficulté consiste à calibrer le TouchScreen, c'est à dire, à transformer les données brutes reçues en coordonnées valides sur l'écran pour une orientation donnée.
La fonction de calibration que j'ai écrite donne de très bons résultats pour toutes les orientations de l'écran. Elle détermine de facteurs permettant de calculer un x (ou un y) en pixel à partir des données brutes renvoyées par le contrôleur. Toutefois, ce facteur n'est pas suffisant pour une bonne précision car les données brutes renvoyées par le contrôleur ne sont pas linéaires (i.e. un facteur valable pour un x de grande valeur n'est pas très bon pour un x de petite valeur et inversement (idem pour y). J'introduit donc une légère correction qui prend en compte cette non linéarité pour limiter les écarts pour toutes les valeurs de x et y.
Le programme complet, est disponible dans le fichier touch.c (bientôt en téléchargement).
Mémoire non volatile
Il est habituel de conserver des informations de paramétrage dans une mémoire non volatile (qui conserve l'information même si la carte de développement n'est plus alimentée). La carte de développement STM32F407VET6 (et son processeur) propose plusieurs possibilités :
- Sauvegarde en flash externe
- Sauvegarde en EEPROM interne
- Sauvegarde dans l'horloge temps réelle (RTC)
- Sauvegarde dans une mémoire SRAM de 4096 octets
Je n'ai pas exploré comment utiliser les deux premières possibilités. Mais si l'on souhaite éviter l'utilisation d'une batterie, ces deux possibilités sont à considérer. Pour les deux dernières, une batterie est nécessaire pour maintenir la RTC en fonctionnement et le contenu de la SRAM (mémoire statique). La très faible consommation de ces deux "périphériques" (quelques µA) permet une durée de conservation très longue avec une simple petite batterie au lithium.. Comme celle qui est livrée avec la carte de développement.
L'intérêt d'utiliser une de ces deux dernières possibilités est que l'on n'est pas limité par un éventuel vieillissemment des mémoires flash ou EEPROM.
Si vous avez très peu de données à conserver (maximum, 80 octets), l'utilisation de la RTC est à considérer car elle consomme moins que la SRAM.
Dans mon cas, je ne voulais pas trop me limiter et j'ai donc utilisé la SRAM.
On trouve assez facilement sur le net quelques exemples de mise en oeuvre sur lesquels je me suis basé. Heureusement car il semble par ailleurs que la fonctionnalité soit assez mal documentée (disons qu'il faut se palucher le datasheet du STM32F407 et que si on peut trouver directement l'information ailleurs, ce n'est pas plus mal !).
Pour pouvoir utiliser la SRAM, , il faut :
- Activer le backup. Normalement, On le fait une fois pour toute. Pour ce faire :
- Il faut autoriser l'accès au "domaine" qui gère le backup. A noter que cet accès est inactivé au démarrage de la carte pour éviter des écritures non voulues dans les paramètres.
- Activer l'horloge de la SRAM (je ne sais pas trop pourquoi dans cette phase. Peut-être n'est-ce pas vraiment utile).
- Activer le BackupRegister.
- Désactiver l'accès au domaine.
- Ensuite, il est possible d'écrire ou lire dans la SRAM. Pour lire, on active l'horloge de la SRAM, on on lit puis on désactive l'horloge.
Pour écrire, on autorise l'accès au "domaine" qui gère le backup, on active l'horloge de la SRAM, on écrit (à noter qu'il n'y a pas de cache donc pas besoin de la vider pour forcer l'écriture) puis on désactive l'horloge et l'accès au "domaine" qui gère le backup.
Le programme complet (initialisation, lecture, écriture) qui fait environ 70 lignes, commentaires compris, se trouve dans les fichiers nvmemory.c et nvmemory.h du programme du chronocomparateur.