Préparation de l'environnement et gestion des conflits de code
Lors de l'intégration d'un écran LCD 4.3 pouces utilisant l'interface FMC (Flexible Memory Controller) sur un microcontrôleur STM32H750 via STM32CubeMX, il est crucial de gérer correctement les fichiers sources et les initialisations matérielles pour éviter les conflits de compilation.
Tout d'abord, importez les fichiers de pilotes nécessaires dans votre projet, notamment les modules de gestion du LCD, des polices de caractères (font), des délais (delay) et du système (system). Étant donné que STM32CubeMX génère automatiquement le code d'initialisation bas niveau (MspInit) pour les périphériques configurés, il est impératif de commenter la fonction HAL_SRAM_MspInit présente dans votre fichier de pilote LCD personnalisé. Cela permet d'éviter les définitions multiples lors de la compilation.
Configuraton STM32CubeMX et initialisation FMC
Dans l'interface STM32CubeMX, activez le périphérique FMC en mode SRAM et configurez les broches GPIO correspondantes. Une fois le code généré, l'initialistaion matérielle des broches FMC et des broches de contrôle du LCD (rétroéclairage et reset) doit être intégrée dans le fichier stm32h7xx_hal_msp.c (ou le fichier FMC généré) à l'intérieur de la fonction HAL_SRAM_MspInit.
Voici une implémentation optimisée et restructurée de l'initialisation des broches :
void HAL_SRAM_MspInit(SRAM_HandleTypeDef* hsram) {
GPIO_InitTypeDef gpioConfig = {0};
// Activation des horloges périphériques
__HAL_RCC_FMC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
// Configuration des broches de contrôle (Rétroéclairage et Reset)
gpioConfig.Mode = GPIO_MODE_OUTPUT_PP;
gpioConfig.Pull = GPIO_NOPULL;
gpioConfig.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
gpioConfig.Pin = GPIO_PIN_13; // PD13: Contrôle du rétroéclairage
HAL_GPIO_Init(GPIOD, &gpioConfig);
gpioConfig.Pin = GPIO_PIN_12; // PD12: Signal de reset
HAL_GPIO_Init(GPIOD, &gpioConfig);
// Configuration des broches de données et d'adresse FMC sur le port D
gpioConfig.Mode = GPIO_MODE_AF_PP;
gpioConfig.Pull = GPIO_PULLUP;
gpioConfig.Alternate = GPIO_AF12_FMC;
gpioConfig.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 |
GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 |
GPIO_PIN_11 | GPIO_PIN_14 | GPIO_PIN_15;
HAL_GPIO_Init(GPIOD, &gpioConfig);
// Configuration des broches de données FMC sur le port E
gpioConfig.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 |
GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |
GPIO_PIN_15;
HAL_GPIO_Init(GPIOE, &gpioConfig);
}
Implémentation de l'application principale
L'exemple suivant démontre comment initiailser le système, configurer le tampon de référence de tension (VREFBUF), et utiliser le LCD pour afficher des statistiques de tension en temps réel acquises via un ADC avec transfert DMA. Le code a été restructuré pour améliorer la lisibilité et corriger la logique de calcul statistique.
int main(void) {
uint8_t displayBuffer[32];
uint32_t adc_samples[256];
// Initialisation du système et des périphériques
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_FMC_Init();
MX_ADC1_Init();
MX_TIM6_Init();
CPU_CACHE_Enable();
MPU_Memory_Protection();
SysTick_clkconfig(400);
LED_Init();
LCD_Init();
Set_TIM_Freq(&htim6, 256000);
// Configuration du tampon de référence de tension interne (VREFBUF)
__HAL_RCC_VREF_CLK_ENABLE();
__HAL_RCC_SYSCFG_CLK_ENABLE();
HAL_SYSCFG_VREFBUF_VoltageScalingConfig(SYSCFG_VREFBUF_VOLTAGE_SCALE0);
HAL_SYSCFG_VREFBUF_HighImpedanceConfig(SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE);
while (HAL_SYSCFG_EnableVREFBUF() != HAL_OK) {
HAL_Delay(100);
}
// Affichage de l'interface utilisateur statique
LCD_SetTextColor(COLOR_RED);
LCD_DrawString(30, 10, "STM32H750 FMC LCD Demo");
LCD_DrawString(30, 30, "ADC DMA Sampling");
LCD_DrawString(30, 50, "System Status: Active");
LCD_SetTextColor(COLOR_BLUE);
LCD_DrawString(30, 90, "ADC CH4 Statistics:");
LCD_DrawString(30, 110, "Max Voltage : 0.000V");
LCD_DrawString(30, 130, "Min Voltage : 0.000V");
LCD_DrawString(30, 150, "Avg Voltage : 0.000V");
uint32_t peak_val = 0;
uint32_t trough_val = 0xFFFF;
uint64_t total_sum = 0;
float volt_max, volt_min, volt_avg;
// Démarrage de l'acquisition ADC via DMA et du timer de déclenchement
HAL_ADC_Start_DMA(&hadc1, adc_samples, 256);
HAL_TIM_Base_Start(&htim6);
HAL_Delay(10);
while (1) {
// Séquence de test des LED
LED_SetColor(LED_COLOR_BLUE);
HAL_Delay(500);
LED_SetColor(LED_COLOR_CYAN);
HAL_Delay(500);
LED_SetColor(LED_COLOR_MAGENTA);
HAL_Delay(500);
// Traitement des échantillons ADC
peak_val = 0;
trough_val = 0xFFFF;
total_sum = 0;
for (int i = 0; i < 256; i++) {
if (adc_samples[i] > peak_val) peak_val = adc_samples[i];
if (adc_samples[i] < trough_val) trough_val = adc_samples[i];
total_sum += adc_samples[i];
}
// Conversion des valeurs brutes en tension (Référence 2.048V sur 16 bits)
volt_max = (float)peak_val * (2.048f / 65535.0f);
volt_min = (float)trough_val * (2.048f / 65535.0f);
volt_avg = (float)(total_sum / 256) * (2.048f / 65535.0f);
// Mise à jour de l'affichage LCD
snprintf((char*)displayBuffer, sizeof(displayBuffer), "%3.3fV", volt_max);
LCD_DrawString(134, 110, (char*)displayBuffer);
snprintf((char*)displayBuffer, sizeof(displayBuffer), "%3.3fV", volt_min);
LCD_DrawString(134, 130, (char*)displayBuffer);
snprintf((char*)displayBuffer, sizeof(displayBuffer), "%3.3fV", volt_avg);
LCD_DrawString(134, 150, (char*)displayBuffer);
HAL_Delay(250);
}
}