STM32. АЦП на практике. DMA, прерывания. Переходим с Arduino на STM32.
Vložit
- čas přidán 21. 07. 2024
- Привет друзья! Решил выпустить небольшую серию видеоуроков о переходе с платформы Arduino на STM32. Скажу сразу - я не профессионал. Я так же учусь. Надеюсь мои разборы хоть кому-то будут полезны :) Данный курс нацелен больше на новичков. Тех, кто только-только начинают осваивать 32-битные МК от STMicroelectronics. Если есть чего предложить, показать - милости просим к нам в команду.
Использую для конфигурации CubeMX и библиотеку HAL.
Пишу в Atollic TrueSTUDIO for STM32 9.3.0
Заходи в нашу группу ВК solderingiron.stm32
Материалы из урока: github.com/Solderingironspb/L...
ЯндексДзен: zen.yandex.ru/id/622208eed2eb...
00:00 Вступление
00:08 Пример работы с АЦП на Arduino
00:41 Stm32. Создание проекта, настройка АЦП.
02:59 Отличие регулярного канала от инжектированного
03:56 Документация Sampling time
10:34 Работа с DMA
19:38 Работа с DMA + прерывания
23:44 Практика с замером напряжения
Странно, что никто за пару лет никто не сказал, что 4095 - это потому что счет начинается с 0, как и в большинстве таких же случаев) Спасибо огромное, помогли разобраться!)
Добрый день, шикарные уроки! Наконец-то все понятно! 🎉 приятно и понятно слушать
Автор молодец😊 добра и счастья тебе, пожимаю руку. Всё ясно и понятно.
Делал всё по шагам. Всё работает! О Боги! Счастье есть! )) Спасибо! (Только использовал CubeIDE)
Спасибо большое друг за твой труд!
отлично! только у тебя нашел практическую реализацию регулярных каналов! все остальные радиолюбители показывают стандартно! одной строчкой и с одного канала выводят данные и все супер. снимай побольше видео, где есть практика и синтаксис написания кода. это реально полезно, помимо книг.
Материал ОГОНЬ!!!
There is no page that I haven't watched or read. I translated my problem to russian using the translate and came across you and the problem was solved(even though i don't know russian). thank you sir
Конечно полезно.
Спасибо!
Проверил на stm32f030. Из отличий заметил что в ADC нет настроек рангов, можно только выбрать "Scan Conversion Mode" - по возрастанию или по убыванию.
Еще в HAL_ADC_ConvCpltCallback получился конфликт из-за того что совпадают имена переменных, пришлось оставить только расчет напряжения а все остальное удалить...
пытаюсь повторить на макетной плате discovery, два значения в двух каналах с ацп первое в диапазоне от 5-245, а второе 0. Никак не могу понять где скрылась проблема.
Разобрался, проблема в порядке инициализации, которую генерит куб
при таком порядке инициализации работает правильно.
MX_DMA_Init();
MX_ADC1_Init();
куб изначально генерит АЦП, а потом ДМА и оно работает не правильно в итоге.
Спасибо за видео! Есть глупый вопрос - откуда у нас взялось 3,3 В при максимальном значении? Это верхняя граница измерений АЦП сама по себе или только в вашем случае?
4095 на ацп - это напряжение, равное напряжению на линии питания АЦП(VDDA). Сколько туда подадите, столько и будет считаться за 4095. Больше 3.3 не нужно прикладывать)
@@Solderingironspb Спасибо!
Подскажите как включить подсветку синтаксиса в Atollic?
Она должна изначально работать
Здравствуйте. Я попробовал загрузить в стм строчку L=analogRead(PA7); и она работает, только почему-то от0 до 1023 как на ардуино. На есп32 она работает лучше, от 0 до 4096
запись вида L=analogRead(PA7); это верх тупости в программировании микроконтроллеров! по этой строчке микропроцессор на всем скаку, своих 72МГц даст команду АЦП "начать считать" а сам будет ждать ответа! АЦП работает в сотни и тысячи раз медленнее чем тактовая частота процессора, поэтому вы тупо убьете всю производительность STM32 на ожидания ответа от АЦП. И такие вот записи я встречаю у 99% "учителей программировать"! а потом сказки что Ардуино 8 бит тормозное... ну так вы этой строчкой сделали STM32 тормознутым! ну и тащить в прерываниях флоат переменные это тоже маразм... учитесь правильно программировать МК, иначе вам никаких ресурсов не хватит даже для небольших программ.
@@user-zv1jp9fx3v вот Вы столько всего написали, что после прочитанного я как был нубом так и остался ни на нанометр не продвинулся. Те кто знают, как правильно программировать, те не оставляют комментарии подобные моему. А те кто оставляют, получают кучу навоза в ответ. Вам легче было оставить строчку правильного кода, но Вы такого никогда не сделаете. Вы ведь учились и тратили драгоценное время😁
И я, кстати, не учитель. Так что мне простительно.
А, ну и с 1023 я разобрался, ацп было в режиме 8 бит. Но это уже и не важно
Здравствуйте!
А как быть с калибровкой АЦП, если в нём используются каналы для дифференциального входа, для обычного входа и для обработки сигналов от встроенных датчиков, например, от встроенного датчика температуры?
Для дифф. входа:
HAL_ADCEx_Calibration_Start(&hadc1, ADC_DIFFERENTIAL_ENDED);
Для обычного входа:
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
Не делать же калибровку перед каждым замером конкретного канала?
Спасибо.
Добрый вечер.
Так вроде на F103 просто HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc).
Т.е. вводите HAL_ADCEx_Calibration_Start(&hadc1);
Ничего дополнительного прописывать не нужно.
@@Solderingironspb "Модель HAL_ADC_Ex предоставляет 3 функции, которые используются для калибровки АЦП. Первая
HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef* hadc, uint32_t SingleDiff);
автоматически выполняет процедуру калибровки. Она должна вызываться сразу после вызова HAL_ADC_Init() и перед вызовом HAL_ADC_Start_XXX(). В качестве параметра функции необходимо передать ADC_SINGLE_ENDED для калибровки несимметричного входа или ADC_DIFFERENTIAL_ENDED для дифференциального".
blog.radiotech.kz/perevod/adc-perevod-iz-knigi-mastering-stm32/#comment-6333
istarik.ru/blog/stm32/113.html
Я работал пока только с F103 и F411. На F411, в референс мануале вообще про калибровку ничего не сказано + она так же отсутствует в HAL под него.
В F103, повторюсь, есть только 1 функция калибровки АЦП. Скрины прилагаю:
user-images.githubusercontent.com/68805120/103935346-7e5ce380-5137-11eb-8aa5-157344f21541.png
user-images.githubusercontent.com/68805120/103935385-8c126900-5137-11eb-888b-61288e60af97.PNG
По первой ссылке, что Вы скинули, там рассказано про калибровку для МК серии STM32L4 и STM32F3.
Я их вообще не щупал.
Во второй же ссылке, как и у меня:
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1);
/* USER CODE END 2 */
Чему я и не удивлен, т.к. там тоже про F103C8T6 говорится.
________________________________________________________________________
PS. А про Ваш код там есть пометка "Функционал более продвинутых МК":
Что касается кода, то тоже есть отличия, например калибровка вызывается с доп. параметром…
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); // обычные каналы
HAL_ADCEx_Calibration_Start(&hadc1, ADC_DIFFERENTIAL_ENDED); // диф. каналы
Так же есть отдельные функции для инжект. и рег. каналов - посмотрите в файле stm32f3xx_hal_adc_ex.c.
@@Solderingironspb да вот, ковыряюсь именно с STM32L452RE. Было бы два АЦП, можно было бы поизвращаться с калибровками. А тут один!
Многовато запутанного в STM32 в целом, как мне кажется. Вот сейчас туплю над такой проблемой: в окне "Problems" рисуется две ошибки
make[1]: *** [makefile:92: post-build] Error 127
make: *** [makefile:55: all] Error 2
а в листинге никаких отметок! Только на ярлычке проекта. И в какой "чёрной комнате" искать пресловутого "чёрного кота"?
Лампочками помогать, конечно, просто. А чуть далее - начинаются проблемы. :(
ааа. Это все та же Nucleo?) C UART разобрались? Да запутанного очень много. Я вот с дисплеем ST7920 очень долго мучался. На F103 работало идеально, а под работу с F411 пришлось помучаться конкретно, чтоб все завелось. F411 работает на частоте 100 Мгц, F103 на 72 Мгц.
Если же на F103 я выбрал скорость spi 18 MBits/s и у меня все завелось, то на F411 заработало на частоте 781.25 KBits/s, а это в 24 раза меньше скорость. И вот я сижу и понять не могу, почему так. Почему скорость общения по spi в 24 раза меньше, а скорость обновления дисплея быстрее.
На счет проблемы с мэйкфайлом: Это скорее всего означает "нет такого файла или каталога" у меня такое было. Хочешь проект собрать, а он не может. Т.е. ошибка не в коде, а в отсутствии какого-то фала.
Изучаю АЦП на STM32F411CEu6 (black pill) - не нашел в описании библиотеки HAL функцию калибровки АЦП (HAL_ADCEx_Calibration), да и CubeIDE ругается на эту функцию. Бегло прочитав даташит, ничего не нашел про калибровку в разделе АЦП (гляну повнимательнее позже). Поэтому писал без нее, но код работает.
Здравствуйте) Действительно. Залез в "stm32f411ceu6 Reference manual". Там про калибровку вообще ни слова не сказано... Похоже на этих МК уже как-то по-другому отстроен АЦП. Тут самое-то главное - это посмотреть, как этот ацп работать будет. измерить то же напряжение от 0 до 3.3в. При условии, что сам МК питается от чистых 3.3в.
@@Solderingironspb Доброго времени суток! Вот что заметил работая с Callback функциями - в данном видео Вы используете функцию HAL_ADC_ConvCpItCallback и внутри нее выполняете проверку (if (hadc->Instance==ADC1). Эту проверку можно исключить всего лишь переместив * от ADC_HandleTypeDef к hadc. Вот как это выглядит у меня:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
HAL_ADC_Stop_DMA(&hadc1);
voltage[0]=(ADC_Value[0]*3.3f)/4096;
//1й канал ацп
voltage[1]=(ADC_Value[1]*3.3f)/4096;
//напряжение на внутреннем датчике температуры
temp=(1.43-voltage[1])/0.0043f+25;
//рассчитываем температуру
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Value, 2);
}
Данный код работает у меня как на stm32f103c8, так и на stm32f411ceu6. Увидел это на уроках канала NarodStream. Ваш же пример с условием на канале Controllers Tech(ни в коем случае не реклама). И вот назрел вопрос - а нужна ли эта проверка if (hadc->Instance==ADC1), если работает и без нее?
@@kopatbich4610 без неё работает, потому что запущен только один АЦП, как только начнёт работать два и более АЦП, то в буфере получится каша, так как колбэк неизвестно от кого приходит. Эта проверка нужна как раз чтобы отделить мух от котлет.
@@bdfy8349 понял, спасибо!
Третий день трах...сь с АЦП через ПДП для stm32f030.
Максимум, чего достиг - это чтения двух каналов, при этом такое впечатление, что оба они "складываются" в один элемент массива...
Столько действий с стм, в ардуино проще.
Конечно проще. НО! На ардуино все основные процессы написаны до Вас. Если брать просто AVR и писать с нуля все ручками в том же AtmelStudio, то тоже будет много всего. Но согласитесь, если во всем этом разобраться, то Вы хоть будете понимать, как устроен тот или иной узел и как Ваше устройство работает в целом.
@@Solderingironspb atmel согласен, работаешь с регистрами. А атолик и куб - такой же кодогенератор и разобраться оч трудно
Для этого я и записываю уроки, чтоб Вам было легче) Если будут вопросы - напишите в группу вконтакте, ссылка в описании. Попробуем разобраться в вопросе глубже)
@@Solderingironspb спасибо Вам за ваши труды
Дак загоните 4 строки в отдельную функцию и будете так же одной строкой запускать измерение )))
Если вместо умножения и потом деления просто умножить на 0,0008095238095 то можно значительно увеличить производительность.