STM32 АЦП преобразование с использованием HAL


10

Я пытаюсь узнать, как использовать "новую" библиотеку HAL из stm32.
Когда я пытаюсь сделать простое преобразование АЦП, он работает только один раз, но затем он останавливается. Я полагаю, что флаг Конверсии не установлен. Я использую плату обнаружения STM32f429I, в которой есть STM32f429ZI.
Обратите внимание, что я знаю о том, что sprintf - плохая практика, и лучше делать АЦП с прерываниями, я знаю, что, пожалуйста, не указывайте, это не имеет отношения к вопросу, я просто тестирую HAL здесь.
Итак, вопрос в том, почему флаг EOC не установлен или что я могу сделать, чтобы он работал? Поиск в Google не очень помогает, так как очень мало хороших материалов о 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, конфигурация АЦП выглядит следующим образом: введите описание изображения здесь

РЕДАКТИРОВАТЬ 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 - довольно новая библиотека, ресурсов не так много, но не невозможно. Из этого урока я многому научился , он демонстрирует все возможные варианты использования АЦП шаг за шагом; от простого опроса до использования прерываний и прямого доступа к памяти.


хм ... отключение 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), чтобы закончить преобразование ... Я смотрел на эти учебники раньше и думал, что это довольно варварский способ, кажется, он полностью отключает ADC, так что я должен был другой метод. Но, похоже, это действительно хорошо работает.
Не стесняйтесь опубликовать ответ, если есть более элегантный способ сделать это, так как я думаю, что использование 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);

  }

Привет, я обнаружил проблему с этим методом, он ограничивает максимальную частоту дискретизации, которую вы можете достичь много, не рекомендуется использовать этот метод, если вам нужны быстрые преобразования АЦП.
Ричард Бэмфорд

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.