STM32 ADC-Konvertierung mit HAL


10

Ich versuche zu lernen, wie man "neue" HAL-Bibliothek von stm32 verwendet.
Wenn ich versuche, eine einfache ADC-Konvertierung durchzuführen, funktioniert dies nur einmal, aber dann wird die Konvertierung beendet. Ich nehme an, das Flag für das Ende der Konvertierung wird nicht gesetzt. Ich verwende das STM32f429I Discovery Board, das STM32f429ZI an Bord hat.
Beachten Sie, dass ich weiß, dass Sprintf eine schlechte Übung ist und dass es besser ist, ADC mit Interrupt zu erstellen. Ich weiß, dass dies bitte nicht darauf hinweist. Dies ist für die Frage nicht relevant. Ich teste hier nur HAL.
Die Frage ist also, warum das EOC-Flag nicht gesetzt ist oder was ich tun kann, damit es funktioniert. Googeln hilft nicht viel, da es nur sehr wenige gute Materialien über HAL gibt.

Hier ist der Code:

__IO uint16_t ADCValue=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

int main(void)
{
  char str[15];

  /* Various initializations */

  HAL_ADC_Start(&hadc1);
  while (1)
  {

        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
            sprintf(str, "%d", ADCValue);
            BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }

  }

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADCValue = HAL_ADC_GetValue(&hadc1);
}

Ich habe das Projekt auch mit CubeMX erstellt. Die ADC-Konfiguration lautet wie folgt: Geben Sie hier die Bildbeschreibung ein

BEARBEITEN 1
Ich habe versucht, alles zu debuggen, und es scheint, dass das Programm nicht mehr nach dem EOC-Flag sucht - es sieht, dass es nicht angezeigt wird, und gibt daher einen Timer aus, der darauf wartet, dass das EOC angezeigt wird (aber es wird nie gesetzt). Hier ist der Code, in dem es angezeigt wird bleibt im Debugger stecken:

/* Check End of conversion flag */
  while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)))
  {
    /* Check for the Timeout */
    if(Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
      {
        hadc->State= HAL_ADC_STATE_TIMEOUT;
        /* Process unlocked */
        __HAL_UNLOCK(hadc);
        return HAL_TIMEOUT;
      }
    }

Antworten:


6

Setzen Sie in Ihrem ursprünglichen Code die Auswahl für das Ende der Konvertierung auf deaktiviert.

 hadc1.Init.EOCSelection = DISABLE;

Es stellte sich heraus, dass der #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)Wert gleich ist DISABLE. Eigentlich sollte die EOCSelection so konfiguriert sein , dass der ADC mehrmals abgefragt werden kann .Geben Sie hier die Bildbeschreibung ein

Dann können Sie den ADC kontinuierlich lesen, ohne den ADC anzuhalten und zu starten:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    ConfigureADC();

    HAL_ADC_Start(&hadc1);
    while(1)
    {
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
        }
    }
}

Auf diese Weise hat es für mich gut funktioniert.

Da HAL eine ziemlich neue Bibliothek ist, sind nicht viele Ressourcen zu finden, aber nicht unmöglich. Ich habe viel aus diesem Tutorial gelernt. Es zeigt Schritt für Schritt alle möglichen ADC-Verwendungen. von der einfachen Abfrage bis zur Verwendung von Interrupts und DMA.


hm ... durch Deaktivieren von EOCSelection funktioniert es, aber aus der Definition geht hervor, dass das EOC-Flag am Ende der Einzelkanalkonvertierung oder am Ende aller Konvertierungen gesetzt ist. Das Deaktivieren sollte per Definition nicht helfen ... aber es hilft ... verwirrend. Wissen Sie, warum genau das Deaktivieren funktioniert? Trotzdem danke für die Antwort
ScienceSamovar

Ich lerne gerade auch HAL, daher kenne ich den Grund noch nicht. Es ist nur eine Erfahrung. Ich fand, dass HAL so oft überzeugen kann.
Bence Kaulics

Ich habe die definierten Werte überprüft und #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)diese sind identisch mit deaktiviert, daher ist deaktiviert tatsächlich ADC_EOC_SEQ_CONV.
Bence Kaulics

1
Oh, ok, es ist also nicht buchstäblich deaktiviert. Es ist sinnvoll, früher war es ADC_EOC_SINGLE_CONV, was wahrscheinlich genau das bedeutet - es wird nur einmal konvertiert, und ADC_EOC_SEQ_CONV ist eine kontinuierliche Konvertierung. Noch ein Rätsel gelöst :) Danke!
ScienceSamovar

Ja, das sollte der Fall sein. :)
Bence Kaulics

2

Hm ... Ich habe einige Tutorials gefunden, die HAL_ADC_Stop (& hadc1) verwendet haben, um die Konvertierung zu beenden ... Ich habe mir diese Tutorials zuvor angesehen und dachte, dass dies ein ziemlich barbarischer Weg ist. Es scheint, dass ADC vollständig deaktiviert wird, also sollte es das geben andere Methode. Aber es scheint, dass dies tatsächlich gut funktioniert.
Sie können gerne eine Antwort posten, wenn es eine elegantere Möglichkeit gibt, dies zu tun, da ich die Verwendung von HAL_ADC_Stop () für ziemlich schrecklich halte, aber für Lernzwecke verwendet werden kann.

while (1)
  {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
                        sprintf(str, "%d", ADCValue);
                        BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }
        HAL_ADC_Stop(&hadc1);

  }

Hallo, ich habe ein Problem mit dieser Methode gefunden. Sie schränkt die maximale Abtastrate ein, die Sie mit VIEL erreichen können. Es wird nicht empfohlen, diese Methode zu verwenden, wenn Sie schnelle ADC-Konvertierungen benötigen.
Richard Bamford

2

Ich möchte hinzufügen, dass es für mein Setup (Nucleo-h743) nicht ausreichte, Folgendes festzulegen:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

Ich musste auch die Überlaufeinstellung aktivieren:

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

Ohne dies blockierte die HAL_ADC_PollForConversion immer noch. Ich verstehe nicht ganz, warum dies notwendig war, aber es erlaubt mir, im kontinuierlichen Modus abzufragen.


0

Das funktioniert bei mir, hoffe es hilft:

if (HAL_ADC_Start(&hadc) != HAL_OK)
{
    /* Start Conversation Error */
    // Error_Handler();
}
if (HAL_ADC_PollForConversion(&hadc, 500) != HAL_OK)
{
    /* End Of Conversion flag not set on time */
    // Error_Handler();
    ADCValue=-1;
}
else
{
    /* ADC conversion completed */
    /*##-5- Get the converted value of regular channel ########################*/
    ADCValue = HAL_ADC_GetValue(&hadc);
}
HAL_ADC_Stop(&hadc);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.