Dans ce tuto, nous branchons à une carte STM32F103C "Blue Pill" un écran tactile TFT SPI de 240 X 320 pixels (2,4") munie d'un contrôleur ILI9341. La Blue Pill sera programmée avec l'IDE Arduino en utilisant le core officiel STM32.
Il existe un grand nombre de petits afficheurs couleurs qui se ressemblent beaucoup mais qui ne sont pas identiques: certains utilisent une interface parallèle plutôt que SPI, d'autre comportent une autre puce que la ILI9341, la résolution peut être différente et plusieurs écrans ne sont pas tactiles...
Si vous utilisez un afficheur différent de celui que j'ai utilisé, vous trouverez peut-être, malgré tout, des informations utiles dans cet article, puisque la bibliothèque TFT_eSPI supporte un grand nombre de modèle différents. Mais vous devrez certainement effectuer certaines modifications...
Connexions de l'écran à la Blue Pill
Mon écran comporte un total de 18 connecteurs; toutefois, je n'ai pas utilisé les 4 connecteurs qui servent au lecteur de carte SD (visible du côté gauche sur la photo ci-dessous).
J'ai connecté l'écran à la Blue Pill de la façon suivante:
- Broche VCC de l'écran - Sortie 3,3 V de la Blue Pill
- Broche GND de l'écran - Broche G de la Blue Pill
- Broche CS de l'écran - Broche A0 de la Blue Pill
- Broche RESET de l'écran - Broche Broche A2 de la Blue Pill
- Broche DC/RS de l'écran - Broche A1 de la Blue Pill
- Broche SDI (MOSI) de l'écran - Broche A7 de la Blue Pill
- Broche SCK de l'écran - Broche A5 de la Blue Pill
- Broche LED de l'écran - Sortie 3,3 V de la Blue Pill
- Broche SDO (MISO) de l'écran - Broche A6 de la Blue Pill
- Broche T_CLK de l'écran - Broche A5 de la Blue Pill
- Broche T_CS de l'écran - Broche A4 de la Blue Pill
- Broche T_DIN de l'écran - Broche A7 de la Blue Pill
- Broche T_DO de l'écran - Broche A6 de la Blue Pill
- Broche T_IRQ de l'écran - pas connectée
/* | |
Démonstration d'écran tactile à deux "boutons" | |
TFT SPI 2.4" 320 X 240 pixels | |
Plus d'infos: | |
https://electroniqueamateur.blogspot.com/2021/04/utilisation-dun-ecran-tactile-tft-spi.html | |
*/ | |
#include <SPI.h> | |
#include <TFT_eSPI.h> | |
TFT_eSPI tft = TFT_eSPI(); // https://github.com/Bodmer/TFT_eSPI | |
// Création de 2 objets boutons | |
#define NOMBRE_BOUTONS 2 | |
TFT_eSPI_Button bouton[NOMBRE_BOUTONS]; | |
void setup() { | |
tft.init(); | |
tft.setRotation(3); // portrait: 0 ou 2, paysage: 1 ou 3. | |
touch_calibrate(); // procédure de calibration de l'écran tactile | |
// affichage d'un message à l'écran: | |
tft.fillScreen(TFT_BLACK); // on efface tout (fond noir) | |
tft.setFreeFont(&FreeSansOblique12pt7b); // police de caractère | |
tft.setCursor(20, 70); // position du début du message | |
tft.setTextSize(1); | |
tft.setTextColor(TFT_WHITE, TFT_BLACK); | |
tft.println("Choisissez la forme desiree"); | |
// création de deux boutons | |
// premier bouton: son centre est positionné à x = 80 et y = 200, largeur 120, | |
// hauteur 50, contour en noir, remplissage rouge, texte en blanc, taille de texte 1. | |
bouton[0].initButton(&tft, 80, 200, 120, 50, TFT_BLACK, TFT_RED, TFT_WHITE, "rectangle", 1); | |
bouton[0].drawButton(); | |
// deuxième bouton: son centre est positionné à x = 250 et y = 200, largeur 120, | |
// hauteur 50, contour en noir, remplissage vert, texte en noir, taille de texte 1. | |
bouton[1].initButton(&tft, 250, 200, 120, 50, TFT_BLACK, TFT_GREEN, TFT_BLACK, "cercle", 1); | |
bouton[1].drawButton(); | |
} | |
//------------------------------------------------------------------------------------------ | |
void loop(void) { | |
uint16_t t_x = 0, t_y = 0; // coordonnées touchées par l'utilisateur | |
boolean pressed = tft.getTouch(&t_x, &t_y); // vrai si contact avec l'écran | |
// On vérifie si la position du contact correspond à celle d'un bouton | |
for (uint8_t numero = 0; numero < NOMBRE_BOUTONS; numero++) { | |
if (pressed && bouton[numero].contains(t_x, t_y)) { | |
bouton[numero].press(true); | |
} else { | |
bouton[numero].press(false); | |
} | |
} | |
// Vérifions maintenant si l'état d'un des boutons a changé | |
for (uint8_t numero = 0; numero < NOMBRE_BOUTONS; numero++) { | |
// si le bouton vient d'être relâché, on le redessine avec sa forme normale | |
if (bouton[numero].justReleased()) { | |
bouton[numero].drawButton(); | |
} | |
// si le bouton vient d'être pressé... | |
if (bouton[numero].justPressed()) { | |
bouton[numero].drawButton(true); // on le redessine avec les couleurs inversées | |
// ...puis on fait ce que l'utilisateur a demandé: | |
switch (numero) { | |
case 0: // premier bouton | |
tft.fillRect(0, 0, 320, 160, TFT_BLACK); // pour effacer le dessin précédent | |
tft.fillRect(60, 30, 200, 100, TFT_CYAN); // rectangle 200 de largeur et 100 de hauteur | |
break; | |
case 1: // deuxième bouton | |
tft.fillRect(0, 0, 320, 160, TFT_BLACK); // pour effacer le dessin précédent | |
tft.fillCircle(160, 80, 50, TFT_YELLOW); // cercle centré à x = 160 et y = 80 | |
break; | |
} | |
delay(10); // anti-rebond | |
} | |
} | |
} | |
// procédure de calibration de l'écran tactile | |
void touch_calibrate() | |
{ | |
uint16_t calData[5]; | |
uint8_t calDataOK = 0; | |
tft.fillScreen(TFT_BLACK); | |
tft.setCursor(25, 70); | |
tft.setTextFont(2); | |
tft.setTextSize(2); | |
tft.setTextColor(TFT_WHITE, TFT_BLACK); | |
tft.println("Touchez l'ecran a "); | |
tft.setCursor(15, 110); | |
tft.println("chaque coin indique."); | |
tft.setTextFont(1); | |
tft.println(); | |
tft.calibrateTouch(calData, TFT_YELLOW, TFT_BLACK, 20); | |
tft.setTextColor(TFT_GREEN, TFT_BLACK); | |
tft.println("Calibration terminee!"); | |
} |
/*************************************************************************** | |
Bouton coulissant sur un écran tactile TFT SPI 2.4" 320 X 240 pixels | |
Pour plus d'infos: | |
https://electroniqueamateur.blogspot.com/2021/04/utilisation-dun-ecran-tactile-tft-spi_25.html | |
******************************************************************************/ | |
#include <SPI.h> | |
#include <TFT_eSPI.h> | |
TFT_eSPI tft = TFT_eSPI(); // https://github.com/Bodmer/TFT_eSPI | |
#define VALEUR_MAX 100 // valeur affichée quand le bouton est poussé à l'extrême droite | |
#define LARGEUR 20 // largeur du bouton | |
#define HAUTEUR 40 // hauteur du bouton | |
#define POSY 150 // position verticale du bouton coulissant | |
#define LIMITE_GAUCHE 30 // extrémité gauche au 20e pixel | |
#define LIMITE_DROITE 290 // extrémité droite au 100e pixel | |
uint16_t x_precedent = 160 ; // position horizontale précédemment touchée (160 est le centre de l'écran) | |
// routine qui redessine le contenu de l'écran | |
void dessineContenu(uint16_t posx) { | |
uint16_t postxt; | |
// on ne permet pas que le bouton dépasse les limites établies | |
if (posx < LIMITE_GAUCHE) { | |
posx = LIMITE_GAUCHE; | |
} | |
if (posx > LIMITE_DROITE) { | |
posx = LIMITE_DROITE; | |
} | |
// on efface le bouton, là où il se trouvait précédemment | |
tft.fillRect(x_precedent - LARGEUR / 2, POSY - HAUTEUR / 2 - 2 , LARGEUR, HAUTEUR + 4, TFT_BLACK); | |
// on dessine la ligne horizontale | |
tft.drawLine(LIMITE_GAUCHE, POSY, LIMITE_DROITE, POSY, TFT_WHITE); | |
// on dessine le bouton à sa nouvelle position | |
tft.fillRect(posx - LARGEUR / 2, POSY - HAUTEUR / 2, LARGEUR, HAUTEUR, TFT_YELLOW); | |
// on efface l'ancienne valeur numérique | |
postxt = 90; | |
tft.setTextColor(TFT_BLACK); | |
postxt += tft.drawFloat(calcule_valeur(x_precedent), 1, postxt, 50, 4); | |
// on écrit la nouvelle valeur numérique | |
postxt = 90; | |
tft.setTextColor(TFT_GREEN); | |
postxt += tft.drawFloat(calcule_valeur(posx), 1, postxt, 50, 4); | |
x_precedent = posx; | |
} | |
// routine qui calcule la valeur numérique qui correspond à la position du bouton coulissant | |
float calcule_valeur (uint16_t valeur_brute) { | |
float valeur_convertie; | |
valeur_convertie = 1.0 * (valeur_brute - LIMITE_GAUCHE) / ( LIMITE_DROITE - LIMITE_GAUCHE) * VALEUR_MAX; | |
return valeur_convertie; | |
} | |
void setup() { | |
tft.init(); | |
tft.setRotation(3); // portrait: 0 ou 2, paysage: 1 ou 3. | |
touch_calibrate(); // procédure de calibration de l'écran tactile | |
tft.fillScreen(TFT_BLACK); // on efface tout (fond noir) | |
dessineContenu(160); | |
} | |
void loop(void) { | |
uint16_t t_x = 0, t_y = 0; // coordonnées touchées par l'utilisateur | |
boolean pressed = tft.getTouch(&t_x, &t_y); // vrai si contact avec l'écran | |
if (pressed) { // si on touche l'écran | |
if (t_x != x_precedent) { // si on a changé de position | |
dessineContenu(t_x); | |
} | |
} | |
} | |
// procédure de calibration de l'écran tactile | |
void touch_calibrate() | |
{ | |
uint16_t calData[5]; | |
uint8_t calDataOK = 0; | |
tft.fillScreen(TFT_BLACK); | |
tft.setCursor(25, 70); | |
tft.setTextFont(2); | |
tft.setTextSize(2); | |
tft.setTextColor(TFT_WHITE, TFT_BLACK); | |
tft.println("Touchez l'ecran a "); | |
tft.setCursor(15, 110); | |
tft.println("chaque coin indique."); | |
tft.setTextFont(1); | |
tft.println(); | |
tft.calibrateTouch(calData, TFT_YELLOW, TFT_BLACK, 20); | |
tft.setTextColor(TFT_GREEN, TFT_BLACK); | |
tft.println("Calibration terminee!"); | |
} |