В современных электронных устройствах широкое применение находят аналого-цифровые преобразователи (АЦП, в англ. ADC – Analog to Digital Converter). С помощью данных АЦП можно считывать значения напряжения с различных аналоговых датчиков: температуры, наклона, тока, изгиба и многих других. В данной статье мы рассмотрим использование АЦП в плате STM32F103C8, которая также называется STM32 Blue Pill («синяя таблетка»). Мы подключим к плате STM32 Blue Pill небольшой потенциометр, напряжение с которого будем подавать на один из АЦП платы, измеренное значение напряжения мы будем выводить на экран ЖК дисплея 16х2.
Ранее на нашем сайте мы рассматривали использование АЦП в следующих микроконтроллерах (микроконтроллерных платах):
Необходимые компоненты
- Плата разработки STM32F103C8T6 (STM32 Blue Pill) (купить на AliExpress).
- ЖК дисплей 16×2 (купить на AliExpress).
- Потенциометр 100 кОм (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Сравнение АЦП в платах Arduino и STM32F103C8
Плата Arduino содержит 6 каналов АЦП (8 каналов в платах Mini и Nano, 16 – в плате Mega). Каждый из этих АЦП имеет разрядность 10 бит и диапазон входных напряжений 0V–5V. То есть он преобразует входное напряжение в диапазоне от 0 до 5V в целое число в диапазоне от 0 до 1023. А в плате STM32F103C8 10 каналов АЦП с разрядностью 12 и диапазоном входных напряжений 0V-3.3V. То есть данные АЦП преобразуют входное напряжение в диапазоне от 0 до 3.3V в целое число в диапазоне от 0 до 4095.
АЦП в STM32
АЦП, применяемые в микроконтроллерах STM32, используют принцип SAR (successive approximation register – последовательный аппроксимирующий регистр), при котором преобразование выполняется за несколько шагов. Число этих шагов равно разрядности АЦП.
10 каналов АЦП в плате STM32F103C8 означает что мы имеем 10 контактов АЦП, на каждом из которых мы можем измерять аналоговое напряжение. 12 бит характеризуют разрядность АЦП, это означает что на выходе АЦП в зависимости от значения аналогового напряжения мы получаем целое число в диапазоне от 0 до 4095. Инкремент аналогового напряжения в зависимости от единичного приращения данного числа можно определить по следующей формуле:
1 |
VOLTAGE / STEP = REFERENCE VOLTAGE / 4096 = (3.3/4096= 8.056mV) per unit. |
Распиновка платы STM32 Blue Pill приведена на следующем рисунке.
Каким образом аналоговый сигнал преобразуется в цифровой формат
Современные компьютеры могут хранить и обрабатывать только двоичные/цифровые значения (нули и единицы). Таким образом, аналоговые сигналы (например, с выхода датчиков) нам необходимо преобразовать в цифровые значения для последующей обработки, при этом данное преобразование должно быть по возможности как можно более точным. Когда на аналоговый вход STM32 поступает аналоговое напряжение, оно считывается и сохраняется в переменной целого типа (integer). Сохраненное аналоговое напряжение (0-3.3V) преобразуется в число целого типа (0-4096) в соответствии с формулой:
1 |
INPUT VOLTAGE = (ADC Value / ADC Resolution) * Reference Voltage |
где Resolution (разрешение) = 4096, а Reference (опорное напряжение) = 3.3V.
Схема проекта
Схема для демонстрации возможностей АЦП в плате STM32 Blue Pill представлена на следующем рисунке.
№ контакта ЖК дисплея | Обозначение контакта ЖК дисплея | Контакт платы STM32 |
1 | Ground (Gnd) | Ground (G) |
2 | VCC | 5V |
3 | VEE | средний контакт потенциометра |
4 | Register Select (RS) | PB11 |
5 | Read/Write (RW) | Ground (G) |
6 | Enable (EN) | PB10 |
7 | Data Bit 0 (DB0) | No Connection (NC) |
8 | Data Bit 1 (DB1) | No Connection (NC) |
9 | Data Bit 2 (DB2) | No Connection (NC) |
10 | Data Bit 3 (DB3) | No Connection (NC) |
11 | Data Bit 4 (DB4) | PB0 |
12 | Data Bit 5 (DB5) | PB1 |
13 | Data Bit 6 (DB6) | PC13 |
14 | Data Bit 7 (DB7) | PC14 |
15 | LED Positive | 5V |
16 | LED Negative | Ground (G) |
В схеме у нас присутствуют два потенциометра. Первый из них выполняет роль делителя напряжения – с него изменяемое значения напряжения поступает на аналоговый вход платы STM32. Левый контакт данного потенциометра подключен к источнику положительного напряжения платы STM32 (3.3V), правый контакт подключен к земле платы, а центральный контакт – к аналоговому контакту PA7 платы STM32. Второй потенциометр в схеме используется для регулировки контрастности ЖК дисплея. Питание наша схема получает через порт USB от компьютера/ноутбука.
Внешний вид собранной конструкции проекта показан на следующем рисунке.
Объяснение программы для платы STM32
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
В предыдущей статье на нашем сайте мы рассмотрели программирование платы STM32 Blue Pill через USB порт с помощью Arduino IDE, также ее можно запрограммировать с помощью FTDI программатора как описано в данной статье.
В данной статье мы будем использовать программирование платы через USB порт. Просто подключите плату STM32 к компьютеру с помощью USB кабеля и программируйте ее также как и обычные платы Arduino, не переключая на ней никаких джамперов.
Сначала в программе укажем контакты платы STM32, к которой подключен ЖК дисплей. Вы можете изменить их по своему усмотрению, внеся соответствующие изменения в схему проекта.
1 |
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //mention the pin names to with LCD is connected to |
Затем подключим библиотеку для работы с ЖК дисплеем – LiquidCrystal.h. Также инициализируем объект ЖК дисплея с помощью функции LiquidCrystal. Более подробно о подключении ЖК дисплея 16х2 к плате STM32 Blue Pill вы можете прочитать в этой статье.
1 2 |
#include <LiquidCrystal.h> // include the LCD library LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Initialize the LCD |
Внутри функции setup() мы укажем тип ЖК дисплея (16х2), выведем на его экран приветственное сообщение и спустя 2 секунды очистим экран дисплея.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
lcd.begin(16, 2); //We are using a 16*2 LCD lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("CIRCUITDIGEST"); //Print this lcd.setCursor(0, 1); //At secound row first column lcd.print("STM32F103C8"); //Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen lcd.setCursor(0, 0); //At first row first column lcd.print("USING ADC IN");//Print this lcd.setCursor(0,1); //At secound row first column lcd.print("STM32F103C8");//Print this delay(2000); //wait for two secounds lcd.clear(); //Clear the screen |
Внутри функции loop() мы начнем считывание аналогового напряжения с контакта PA7 платы, которое подается на него со среднего контакта потенциометра. Считывать аналоговое напряжение мы будем с помощью функции analogRead(), считанное значение напряжения мы будем сохранять в переменной “val”. Переменная “val” целого типа (integer), в нашем случае в нее будет записываться число в диапазоне от 0 до 4095 (поскольку у нас 12 битный АЦП).
1 |
int val = analogRead(A7); // read the ADC value from pin PA7 |
На следующем шаге мы будем преобразовывать считанное с выхода АЦП значение целого типа в значение аналогового напряжения. Делать мы это будем с помощью следующего выражения:
1 |
Voltage = (ADC Value / ADC Resolution) * Reference Voltage |
ADC value мы считали в результате предыдущей команды, разрешение АЦП (ADC resolution) у нас равно 4096, рабочее напряжение (operating voltage) микроконтроллера у нас равно 3.3V – его можно измерить с помощью мультиметра, подключенного между контактами Vcc и ground платы. Таким образом, для нашей программы мы получаем следующую команду для получения значения аналогового напряжения:
1 |
float voltage = (float(val)/4096) * 3.3; //formulae to convert the ADC value to voltage |
У вас могут возникнуть вопросы по поводу команды float (val) – она нужна для преобразования значения переменной “val” из целого типа данных в вещественный (float). Нам необходимо это преобразование поскольку если мы будем делить целое значение переменной val на 4096 мы будем получать всегда 0. Предварительное преобразование (перед делением) данной переменной в вещественный тип позволяет избежать данной проблемы. Поскольку значение аналогового напряжения мы получили, нам остается только отобразить его на экране. Мы это сделаем с помощью следующих строк кода:
1 2 3 4 5 6 |
lcd.setCursor(0, 0); // set the cursor to column 0, line 0 lcd.print("ADC Val:"); lcd.print(val); //Display ADC value lcd.setCursor(0, 1); // set the cursor to column 0, line 1 lcd.print("Voltage:"); lcd.print(voltage); //Display voltage |
Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#include <LiquidCrystal.h> // подключаем библиотеку для работы с ЖК дисплеем const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; //указываем контакты платы, к которым подключен ЖК дисплей LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //инициализируем ЖК дисплей const int analogip = PA7;//Initialize the analog input pin void setup() { lcd.begin(16, 2); //указываем тип дисплея 16*2 lcd.clear(); //очищаем экран lcd.setCursor(0, 0); //1-я строка 1-й столбец lcd.print("CIRCUITDIGEST"); //Print this lcd.setCursor(0, 1); //2-я строка 1-й столбец lcd.print("STM32F103C8"); //Print this delay(2000); //ждем 2 секунды lcd.clear(); //очищаем экран lcd.setCursor(0, 0); //1-я строка 1-й столбец lcd.print("USING ADC IN");//Print this lcd.setCursor(0,1); //2-я строка 1-й столбец lcd.print("STM32F103C8");//Print this delay(2000); // ждем 2 секунды lcd.clear(); // очищаем экран } void loop() { int val = analogRead(PA7); // считываем значение АЦП с контакта A7 float voltage = (float(val)/4096) * 3.3; //формула для преобразования значения АЦП в аналоговое значение напряжения lcd.setCursor(0, 0); // 1-я строка 1-й столбец lcd.print("ADC Val:"); lcd.print(val); //выводим на экран значение АЦП lcd.setCursor(0, 1); // 2-я строка 1-й столбец lcd.print("Voltage:"); lcd.print(voltage); // выводим на экран аналоговое значение напряжения } |
2 ответа к “Использование АЦП в STM32F103C8 (STM32 Blue Pill)”
Может ли китайская STM32 Blue Pill работать как 10-ти разрядный АЦП. У меня «работает»…
Ну почему нет если ее разрядность АЦП по умолчанию составляет 12 бит