Перетворення АЦП STM32 за допомогою HAL


10

Я намагаюся навчитися використовувати "нову" бібліотеку HAL від stm32.
Коли я намагаюся зробити просте перетворення АЦП, він працює лише один раз, але потім він перестає конвертувати. Я припускаю, що прапор кінця конверсії не встановлюється. Я використовую плату Discovery STM32f429I, на якій є STM32f429ZI.
Зауважте, що я знаю, що спринт є поганою практикою і робити adc з перериванням краще, я знаю, що, будь ласка, не вказуйте цього, це не стосується питання, я просто тестую HAL тут.
Отже, питання полягає в тому, чому прапор EOC не встановлений або що я можу зробити, щоб він працював? Гуглінг не дуже допомагає, оскільки там дуже мало хороших матеріалів про HAL.

Ось код:

__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);
}

Я також створив проект за допомогою CubeMX, adc конфігурація така: введіть тут опис зображення

EDIT 1
Я спробував налагодити все, і здається, що програма застрягла в тому, щоб перевірити прапор EOC - він бачить, що він не показаний, і тому видає таймер, очікуючи на показ EOC (але він ніколи не встановлюється) Ось код, де він застрягає в налагоджувачі:

/* 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;
      }
    }

Відповіді:


6

У своєму початковому коді встановіть Вимкнути кінець конверсії на вимкнено.

 hadc1.Init.EOCSelection = DISABLE;

Виявилося, що #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)значення дорівнює DISABLE. Таким чином, EOCSelection має бути налаштований так: мати можливість опитувати АЦП кілька разів.введіть тут опис зображення

Тоді ви можете читати АЦП безперервно, не зупиняючи та не запускаючи АЦП:

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);
        }
    }
}

Таким чином, він добре працював для мене.

Оскільки HAL - це зовсім нова бібліотека, знайти не так багато ресурсів, але не неможливо. Я багато чого навчився з цього підручника , він демонструє все можливе використання АЦП крок за кроком; від простого опитування, до використання переривань і DMA.


hm ... відключення EOCSelection змушує його працювати, але з його визначення зазначено - Вказує, чи встановлений прапор EOC в кінці конверсії одного каналу або в кінці всіх перетворень. Відключення цього не повинно допомагати за визначенням .. але це допомагає .... заплутати. Чи знаєте ви, чому саме це відключення змушує це працювати? спасибі за відповідь все одно
ScienceSamovar

Я просто вивчаю HAL теж, тому ще не знаю причини. Це просто досвід. Я виявив, що HAL може так багато разів пустувати.
Бенс Каулікс

Я перевірив значення, #define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)які визначаються, і те ж саме, що вимкнено, тому відключений насправді ADC_EOC_SEQ_CONV.
Бенс Каулікс

1
о, гаразд, так це буквально не відключається. Це має сенс, раніше це було ADC_EOC_SINGLE_CONV, що, ймовірно, означає саме це - воно перетворюється лише один раз, а ADC_EOC_SEQ_CONV - це постійне перетворення. Ще одна таємниця вирішена :) Дякую!
ScienceSamovar

Так, саме так і має бути. :)
Бенс Каулікс

2

Гм ... Я знайшов кілька навчальних посібників, які використовували HAL_ADC_Stop (& hadc1) для завершення конвертації ... Я переглядав ці підручники раніше і думав, що це досить варварський шлях, здається, він повністю відключає АЦП, тому я хоч і повинен бути інший метод. Але здається, що це насправді працює добре.
Будь ласка, будь ласка, опублікуйте відповідь, якщо є більш елегантний спосіб зробити це, оскільки я думаю, що використання HAL_ADC_Stop () є досить жахливим, але його можна використовувати для навчальних цілей.

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);

  }

Привіт, я знайшов проблему з цим методом, він обмежує максимальну швидкість вибірки, яку ви можете досягти за допомогою LOT, не рекомендується використовувати цей метод, якщо вам потрібні швидкі перетворення ADC.
Річард Бамфорд

2

Я хотів би додати, що для моєї установки (nucleo-h743) встановити її було недостатньо:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

Я також повинен був увімкнути налаштування перевиконання:

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

Без цього HAL_ADC_PollForConversion все ще блокувався. Я не повністю розумію, чому це було необхідно, але це дозволяє мені опитуватись у безперервному режимі.


0

Це працює для мене, сподіваюся, що це допоможе:

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.