Configuration et acquisition des données analogiques avec les ADC du STM32

Sur les cartes de développement basées sur le STM32, les périphériques ADC1 et ADC2 sont utilisés pour la numérisation de signaux analogiques. L'ADC1 est configuré pour lire deux sources : une sortie analogique et une tension sur la broche PB14 via le MCP4017. L'ADC2, quant à lui, sert à mesurer une seconde sortie analogique.

L'acquisition de données ADC peut être réalisée de deux manières principales :

  • Par acquisition directe, ce qui consomme des ressources CPU.
  • Par acquisition via DMA (Direct Memory Access), qui minimise la charge sur le processeur.

Cet article présente deux approches : la première utilise le DMA pour les deux ADC avec l'ADC1 en mode double canal, et la seconde combine l'acquisition directe pour l'ADC1 avec le DMA pour l'ADC2.

Configuraton avec STM32CubeMX

Réglage de l'horloge ADC

L'horloge de l'ADC doit être divisée en fonction des spécifications du microcontrôleur, avec une fréquence maximale recommandée de 52 MHz. Dans CubeMX, cela se configure via l'arbre des horloges.

Paramétrage de l'ADC1

Pour l'ADC1, activez le mode balayage pour gérer deux canaux et le mode de conversion continue afin de permettre un transfert DMA ininterrompu. Définissez le nombre de conversions à deux, puis configurez l'ordre des canaux et le temps d'échantillonnage pour chaque rang.

Choisissez une division d'horloge asynchrone par deux, en vous assurant que la fréquence ADC est conforme. Le temps d'échantillonnage doit être suffisamment long pour améliorer la précision.

Configuartion du DMA pour l'ADC1

Sélectionnez le mode circularie pour le DMA et alignez les largeurs de données source et destination pour éviter les erreurs de transfert.

Paramétrage de l'ADC2

L'ADC2 est configuré pour un seul canal, donc le mode balayage n'est pas nécessaire. Les autres paramètres, comme le mode de conversion continue et la configuration du DMA, restent similaires à ceux de l'ADC1.

Exemples de code pour l'acquisition DMA

Les fonctions ci-dessous démarrent le transfert DMA et traitent les données acquises.

void start_adc_acquisition() {
    HAL_ADC_Start_DMA(&adc1_handle, (uint32_t*)adc1_buffer, 40);
    HAL_ADC_Start_DMA(&adc2_handle, (uint32_t*)adc2_buffer, 40);
}

float compute_adc1_voltage() {
    uint32_t sum_channel_a = 0, sum_channel_b = 0;
    for (int idx = 0; idx < 20; idx++) {
        sum_channel_a += adc1_buffer[idx][0];
        sum_channel_b += adc1_buffer[idx][1];
    }
    float voltage_a = 3.3f * (sum_channel_a / 20.0f) / 4096.0f;
    float voltage_b = 3.3f * (sum_channel_b / 20.0f) / 4096.0f;
    return voltage_a;
}

float compute_adc2_voltage() {
    uint32_t total = 0;
    for (int i = 0; i < 40; i++) {
        total += adc2_buffer[i];
    }
    return 3.3f * (total / 40.0f) / 4096.0f;
}

Le tableau adc1_buffer est déclaré comme une matrice 2D pour stocker les échantillons des deux canaux. Les données sont accumulées et moyennées pour appliquer un filtre de lissage avant la conversion en tension.

Alternative avec acquisition directe

Dans cette méthode, l'ADC1 est démancé manuellement à chaque lecture, ce qui permet une flexibilité supplémentaire sans utiliser le mode continu.

float read_adc1_value() {
    HAL_ADC_Start(&adc1_handle);
    uint32_t raw_value = HAL_ADC_GetValue(&adc1_handle);
    return (float)raw_value * 3.3f / 4096.0f;
}

Étiquettes: STM32 ADC DMA CubeMX Microcontrôleur

Publié le 18 juin à 00h50