Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы

И снова здравствуйте. Сегодня я хотел бы рассказать о не очень сложной, но достаточно полезной штуке - АЦП (Analog to Digital Converter) в stm32.


В тексте будут встречаться отсылки на мою первую статью, которую вы можете найти тут: https://pikabu.ru/story/dlya_nachinayushchikh_stm32f103c8t6_...


Итак, АЦП можно представить, как вольтметр, выдающий различные цифровые значения в зависимости от входного напряжения. В STM32 АЦП 12 разрядный, а входное напряжение на его входе колеблется от 0 до 3.3v (напряжение питания контроллера). Конструируя собственные поделки на камнях STM32 необходимо понимать, как работает АЦП.


На вход его подается 2 напряжения - напряжение питания и напряжение входное (котоорое мы хотим отобразить в числовом эквиваленте). Исходя из их сравнения АЦП и выдает результат. Из этого следует, что мы должны иметь очень стабильное напряжение питания самого АЦП, иначе значения будут сильно плавать. К счастью на нашей тестовой плате все уже реализовано и ничего изменить не удастся.


Давайте перейдем к наглядным примерам. Имеется 4 светодиода, каждый из которых подключен к выходам контроллера PB12(красный) PB13(желтый) PB14(зеленый) и PB15 (синий). Давайте подключим так же потенциометр, который будет работать делителем напряжения, а выходное значение будет обрабатываться нашим АЦП. Так же параллельно потенциометру подключим вольтметр, который будет помогать нам определить, что в данный момент на выходе делителя и соответственно на входе АЦП (в нашем случае это будет PA0).

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры
Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры
Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры
Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

В программной части реализации разделим возможный диапазон на 4 части, которые будут начинаться со следующих значений (комментарий - из значение в вольтах):

#define ADC_0V_VALUE 0 //0V

#define ADC_1V_VALUE 1024 //0.825V

#define ADC_2V_VALUE 2048 //1.65V

#define ADC_3V_VALUE 3072 //2.475V


Итак, программа написана следующим образом. В зависимости от значения на выходе потенциометра будет устанавливаться высокий уровень (загораться светодиод) на выходах PB12-PB15.


Теперь перейем к созданию проекта. В CubeMX выберем нашу плату STM32F103C8Tx. Активируем ADC для IN0. Отметим порты PB12-PB15 как выходные. Включим дебаг через Serial Wire и подключим внешний кварц HSE (опционально).

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

Вкладка Clock Configuration не имеет никаких изменений по сравнению с предыдущей статьей:

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

А теперь зайдем в настройки AЦП:

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

Вполне возможно, вы читали какие то гайды и как правило во всех них, при использовании куба с этой отладочной платой имеется аналогичный скрин, где видна возможность настройки разрядности АЦП (вроде этого):

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

Но реальность увы не иная, возможно, ранее разрядность АЦП и можно было настроить для этого камня, но теперь куб такой возможности не предоставляет и окно конфига выглядит так:

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

Возможно, это обусловлено тем, что камень f103 один из самых старых, и stm просто уделяет ему меньше внимания, но это не так критично, ведь по умолчанию, хоть разрядность ацп и не указана, но она выставлена как максимальное значение 12 бит. Все что нам необходимо, это включить Continious Conversion Mode, как на скрине выше. Зачем? Давайте останоовимся немного на режимах работы АЦП их 3:


1. Scan Conversion Mode (Многоканальный) - этот режим используется в том случае, если у нас будет несколько входных каналов преобразователя. Т.к. в данном случае мы используем только один вход A0, то этот режим оставляем отключенным. Если же вы используете несколько входных каналов, то АЦП можно будет сконфигурировать для их опроса в заданной последовательности.


2. Continious Conversion Mode (Циклический) - если этот режим отключен, то опрос канала/каналов произойдет лишь однажды, результат запишется в выходной регистр АЦП и данные всегда будут неизменны. В случае активацции, опрос каналов будет происходить непрерывно, и данные в выходном регистре будут обновляться.


3. Discontinuous Conversion Mode (Непоследовательный) - этот режим позволяет настроить АЦП сканирующее несколько каналов так, что бы опрос происходил не по всем каналам, а по заранее заданным группам каналов, причем если групп несколько, то за раз будет опрашиваться толко одна, затем следующая и т.д.


Следующий раздел ADC_Regular_ConversionMode предоставляет возможность сконфигурировать работу нескольких АЦП. Его мы рассмотрим в следующих статьях в более сложных примерах, а сейчас просто оставим все заданные значения по умолчанию.


На этом конфигурацию проэкта в CoubMX можно считать законченной. Завершим создание проекта для Atollic по аналогии с прошлой статьей.

Stm32f103C8T6 ADC (АЦП - аналого-цифровой преобразователь) основы Stm32f103, Atollic, Гайд, Stm32, Длиннопост, Микроконтроллеры

Вся программная релизация заключается в объявлении переменной, хранящей значение adcResult и объявлении выше описанных #define значений. После этого в цикле читаем значение с АЦП в переменную adcResult и останавливаем АЦП до следующей итерации цикла:


HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1, 100);

adcResult = HAL_ADC_GetValue(&hadc1);

HAL_ADC_Stop(&hadc1);


Затем сравниваем полученное значение с объявленными выше и в зависимости от результата включаем заданный выход контроллера (загорается светодиод) и отключаем остальные.


Код приложения доступен для скачивания по ссылке: https://bitbucket.org/shurankain/adc_leds_f103/downloads/


Стоит заметить, что камень STM32F103C8 имеет встроенных 2 АЦП, каждый из которых может обрабатывать до 18 каналов. Каналами могут служить не только данные извне, но и от внутренних источников. На используемой нами плате доступны 10 внешних каналов (ADC1_IN0-ADC1_IN9 или ADC2_IN0-ADC2-IN9), а так же внутренний термометр встроенный в чип и опорное напряжение (1.20V но может меняться от температуры).


P.S. Дабы избежать ненужных вопросов в стиле: "а чем отличается от Адруино?", - отвечу сразу. Рарядностью. В ардуино 10и разрядный АЦП в stm32 12и разрядный. Что это значит? Ардуино может дискретизировать входной сигнал с точностью 1/1024 (1024 = 2 в 10й степени), в случае с stm32 это 1/4096 (2 в 12й степени). Соответственно, благодаря двум дополнительным разрядам, АЦП в stm32 выдает результат в 4 раза точнее.


P.S. Я обязательно расскажу об использовании нескольких АЦП в будущих статьях. Но в ближайших планируется рассказать о работе с i2c, подключении дисплеев и датчиков. Хочу поблагодарить своих подписчиков, которые у меня появились за интерес к данной теме! Буду рад отвтетить на ваши вопросы и услышать ценные советы с вашей стороны. Спасибо.

TECHNO BROTHER

1.6K постов12.5K подписчиков

Добавить пост

Правила сообщества

1-Мы А-политическое сообщество. 2-Запрещено оскорбление: Администрации Пикабу, сообщества, участников сообщества а также родных, близких выше указанных.

3-Категорически запрещается разжигание межнациональной розни или действий, направленных на возбуждение национальной, расовой вражды, унижение национального достоинства, а также высказывания о превосходстве либо неполноценности пользователей по признаку их отношения к национальной принадлежности или политических взглядов. Мат - Нежелателен. Учитесь выражать мысли без матерщины

1
Автор поста оценил этот комментарий

Пока далеко не ушел от осваивания АЦП. Поэкспериментируй со связкой АЦП+DMA. Например выделил буфер на 1000 отсчетов, пнул АЦП он сам себе оцифровывает а DMA складывает все в буфер, как только буфер заполнился DMA дает прерывание ну и дальше хочешь усредняй хочешь цифровую фильтрацию применяй (понятно, что не внутри прерывания).

Обычный способ в лоб, цифровать по одному отсчету сгодится разве что для наглядности и поиграться. На практике, дергать ядро для обработки каждого отсчета достаточно бесполезная вещь.

Вообще с наличием такого инструмента в stm32 как DMA желательно по возможности пихать его во всю периферию, ну и учиться ее применять не отходя от кассы.

Я вначале своего пути с stm забил на DMA, мол сложная непонятная херня. Зато потом сошло озарение) SPI, I2C, USART, ADC, DAC - чем во все это пихать по байту или доставать по байту, отвлекая ядро на все эти действия, проще один раз настроить DMA и забыть об этом)

раскрыть ветку
1
Автор поста оценил этот комментарий

А как быть если хочешь измерить больше 3.3 вольт или микровольты наоборот? Киньте в меня пожалуйста правильным запросом в гугл или книжкой. Я просто да же не представляю как это может называться, а АЦП заюзать хочу но до 24 вольт и микровольты...

раскрыть ветку
Автор поста оценил этот комментарий

Может ответ на почту сбросите: tabanez1942@mail.ru.

Автор поста оценил этот комментарий

Работаю с дисплеем 1602L в среде Atollic.

#include <stdio.h>

#include "stm32F10x.h"

#include "Lcd1_driver.c"

#include "Lcd1_driver.h"

#include "stm32f10x_rcc.h"


void main()

{

lcd_init();

lcd_clear();

lcd_xy(0, 1) ; // выводить будем в верхнюю строку во вторую позицию

lcd_out("Hello world"); // выводим строку

while(1);

}

Выдаёт единственное предупреждение:

return type of 'main' is not 'int' и не формирует hex файл.

В настройках hex файл как выходной установлен.

elf файл тоже не создаётся.

В чём может быть дело?

Автор поста оценил этот комментарий
Что это за магическое "напряжение питания" которое на вход АЦП подаётся? Опорное напряжение - да есть, и да МК считает относительно него. Не стоит вводить людей в заблуждение.