STM Урок 16. HAL. ADC. Regular Channel



Урок 16

HAL. ADC. Regular Channel

 

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

Я думаю все, кто занимается прогарммированием микроконтроллеров знают не понаслышке, что такое АЦП и чем он занимается. А если кто не знает, то посмотрите мои уроки по программированию котроллеров AVR — там я очень подробно рассказываю про АЦП.

Здесь же мы затронем принцип работы АЦП очень коротко.

Аналого-цифровой преобразователь — это такой преобразователь, который преобразует величину электрическго сигнала в цифровой код.

Ну и как всегда компания STM не осталась в стороне и включила во все свои контроллеры аппаратную поддержку АЦП, причём так включила, что мы на это посвятим не один урок.

И начнём мы, как всегда, с проекта.

Проект создаём из MYLCD80, называем его ADC_REGULAR. Почему именно из этого проекта, потому что данный дисплей мы будем с вами использовать сегодня в нашем занятии с АЦП для отображения сконвертированных в цифровой вид результатов наших преобразований.

Запускаем Cube, включим ADC1 например 5 вход (IN5). Видим, что лапка для измерения напряжения у нас будет PA5. Зайдем сначала в Clock Configuration и убедимся, что у нас там всё нормально, ничего не красное. Кстати за ADC1, если посмотреть табличку в Reference Manual, отвечает шина APB2, то есть данная периферия у нас будет работать на максимальной частое 84 МГц.

Переходим в Configuration. Здесь у нас очень много параметров. На всякий случай сначала включим прерывания, потом вернемся к параметрам. И… ничего тут не трогаем, т.к. мы сегодня будем использовать все настройки по умолчанию. Но вы, конечно, сразу же должны задать вопрос. Так за каким же мы сюда тогда зашли, если ничего не трогаем. А за тем что я все равно о параметрах вам немножко расскажу.

 

 

Теперь сгенерируем и запустим наш проект. Добавим также в него lcd.c. Соберем его.

Сконфигурируем наш программатор, чтобы не жать кнопку RESET. Делается это следующим образом. Меню Flash->Configure Flash Tool ну или кнопкой Option For Target->закладка Utilites, кнопка Settings и ставим чекбокс в «Reset and Run».

В главной функции main немного уменьшим размерность массива str. Нам хватит и 9. Также переменную i сделаем 16-битной.

  /* USER CODE BEGIN 1 */

        char str[9]={0};

        uint16_t i;

  /* USER CODE END 1 */

Откроем руководство STM32F4_HAL_User Manual. На 108 странице там весь процесс запуска преобразований, ожидания результата и остановки преобразований написан.

Найдем функцию для старта преобразования в файле stm32f4xx_hal_adc.h (строка 544). В бесконечном цикле пишем

  while (1)

  {

        HAL_ADC_Start(&hadc1);

Затем нам нужно дождаться конца преобразования.

        HAL_ADC_Start(&hadc1);

        HAL_ADC_PollForConversion(&hadc1,100);

Возьмем результат и сохраним его в переменную

        HAL_ADC_PollForConversion(&hadc1,100);

        i = (uint32_t) HAL_ADC_GetValue(&hadc1);

 

 

Остановим преобразования

        i = (uint32_t) HAL_ADC_GetValue(&hadc1);

        HAL_ADC_Stop(&hadc1);

И отобразим результат

        HAL_ADC_Stop(&hadc1);

        sprintf(str,»%04d»,i);

        LCD_SetPos(0, 3);

        LCD_String(str);

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

        LCD_String(str);

        HAL_Delay(500);

        /* USER CODE END WHILE */

Прошьем и посмотрим результат наших действий с кодом.

Можно покрутить резистор и посмотреть, как меняются показания преобразований.

Но в таком виде нам не интересно смотреть показания.

Для этого сначала добавим переменную другого типа вместо i.

        uint16_t i;

        float u;

И немного изменим код в бесконечном цикле.

        i = (uint32_t) HAL_ADC_GetValue(&hadc1);

u = ((float)HAL_ADC_GetValue(&hadc1))*3/4096;

HAL_ADC_Stop(&hadc1);

sprintf(str,»%04d»,i);

sprintf(str,»%.2fv  «,u);

Прошиваем и смотрим. Вот теперь другое дело!

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Отладочную плату и дисплей можно приобрести здесь:

STM32F4-DISCOVERY

Дисплей LCD 20×4

 

 

Смотреть ВИДЕОУРОК

 

STM32 HAL. ADC. Regular Channel

 

Один комментарий на “STM Урок 16. HAL. ADC. Regular Channel
  1. Lexa:

    Запустилось сразу! Спасибо!

  2. Алексей:

    А можно смотреть результат без дисплея, а напрямую в кейле в режиме дебага?

  3. Сергей:

    Подскажите, пожалуйста, для чего в большинстве примерах в сети в бесконечный цикл while(1) вставляют HAL_ADC_Start(&hadc1);   и  HAL_ADC_Stop(&hadc1);? Ведь старт лучше делать один раз до бесконечного цикла. А так получается каждый такт мы зачем-то каждый раз делаем старт, а потом еще и стоп. И так во многих примерах, для чего так делают? Спасибо.

    • Start — это не запуск шины. Запуск шины — это Init.Start — это начало преобразования. Если не включен специальный режим в настройках шины, то от этого никуда не деться. Когда нам нужно получить значение на канале, приходится запускать процесс преобразования.

      • Сергей:

        В инструкции сказано только следующее:

        Activate the ADC peripheral and start conversions using function HAL_ADC_Start()

        Я выношу HAL_ADC_Start за цикл while(1), тем самым объявляя только 1 раз перед циклом и все нормально работает, поэтому и интересно, зачем каждый цикл делать данное действие, если и так работает или я что-то не понимаю? 

  4. Андрей Пашин:

    Как выбрать канал АЦП?

  5. maxvalin:

    Здравствуйте! Спасибо за прекрасный труд! Изучаю stm, присматриваюсь к нему, не плох он таки))) надеюсь что не сильно буду выглядеть занудным ардуинщиком если спрошу насчёт map?
    Здесь есть что-то схожее? Ведь в аналоговых делах очень удобно масштабировать диапазоны.

    • Ну конечно есть. Только стиль написания программ и архитектура регистров разная. В AVR 8-битных одни регистры, а STM32 32-битных — другие. Также Arduino IDE предусматривает написание кода на C++, а здесь мы пишем на обычном C. Всё потому, что все библиотеки также написаны на C.

  6. issida:

    Можно ли получить результаты преобразований с нескольких каналов без dma и инжектированных каналов? Настроил очередность, но получаю только результат с одного канала.

  7. Slavko_:

    Все хорошо, но нигде и никто в примерах или уроках не вспоминает строчку из даташита «It is recommended to perform a calibration after each power-up.» Я столкнулся с тем что при 3.3 вольта (у меня f103) значения ацп было 4027, не больше. Но порылся по файле адс и нашел функцию калибровки ацп HAL_ADCEx_Calibration_Start(). Теперь все работает отлично. Мелоч, но ушло 2 дня(

  8. kotofot24:

    Дурацкий вопрос но: sprintf (str,»v:%.2F», a); не работает в System Workbench, просто ничего не делает. Маленькая 'f' вообще не пролазит выдает ошибку. Уже и в заголовках искал и хелпах нигде нет описание стандартных операторов (все их все равно никто не помнит, или как я позабыл давно 🙂 )

    • kotofot24:

      Вот характер сам вопрос задал сам ответил:
      project properties > C/C++ Build > Setings > Tool Settings (TAB) > MCU GCC Linker > Miscellaneous > Linker flags
      надо добавить: -u _printf_float

  9. Валера:

    i = (uint32_t) HAL_ADC_GetValue(&hadc1);
    почему не i = (uint16_t) HAL_ADC_GetValue(&hadc1)
    ведь надо привести к 16 битам ?

  10. Rifnur:

    Здравствуйте. Я благодарен за ваши труды.
    Я новичок в программировании, изучаю АЦП по Уроку 16 на базе платы NUCLEO-767ZI, дисплей LCD 1602, среда разработки STM32CubeIDE_1.7.0, генератор кода STM32CubeMX 6.3.0. Значение АЦП sprintf(str,»%.2d v»,i); выводится на дисплей нормально, а с плавающей запятой sprintf(str,»%.2f v»,u);- пустое поле. На этой строке программы сообщение: The float formatting support is not enabled, check your MCU Settings from «Project Properties>C/C++Build>Settings>Tool Settings», or add manually «-u_printf_float» in linker flags. В свойствах проекта нет такой вкладки >Tool Settings. Кто может сталкивался с такой проблемой, какой выход?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*