// ПР6. АЦП: измерение напряжения на выходе резистивного делителя
// Плата: NUCLEO-C031C6, Wokwi + STM32duino
// Автор: Алексеев Ф.В., ЭФБО-08-23
//
// Делитель R1/R2 подключён между 3V3 и GND, средняя точка -> A0 (PA0, ADC1_IN0)
// В Wokwi делитель моделируется потенциометром 10 кОм (движок делит его на R1 и R2)
// U = ADC_value / (2^n - 1) * Uref, n = 12, Uref = 3,3 В
#define ADC_PIN A0 // PA0 — ADC1_IN0
#define BTN_MEAS D4 // кнопка однократного измерения
const uint32_t UREF_MV = 3300; // опорное напряжение, мВ
const uint32_t ADC_MAX = 4095; // 2^12 - 1
const uint8_t N_AVG = 16; // число усредняемых отсчётов
// Пересчёт кода АЦП в милливольты (целочисленно, с округлением)
uint32_t codeToMv(uint32_t code) { return (code * UREF_MV + ADC_MAX / 2) / ADC_MAX; }
void printMv(uint32_t mv) { // вывод в формате X.XXX В
Serial.print(mv / 1000); Serial.print(".");
if (mv % 1000 < 100) Serial.print("0");
if (mv % 1000 < 10) Serial.print("0");
Serial.print(mv % 1000); Serial.print(" V");
}
bool pressed() {
static bool st = HIGH, last = HIGH; static uint32_t t = 0;
bool raw = digitalRead(BTN_MEAS);
if (raw != last) { last = raw; t = millis(); }
if (millis() - t > 25 && raw != st) { st = raw; return raw == LOW; }
return false;
}
void setup() {
Serial.begin(115200);
pinMode(BTN_MEAS, INPUT_PULLUP);
analogReadResolution(12); // разрешение 12 бит
analogRead(ADC_PIN); // первое преобразование: инициализация ADC1
Serial.println("ADC1: 12 bit, Uref = 3.300 V, channel IN0 (PA0)");
Serial.print("ADC1->CFGR1 = 0x"); Serial.println(ADC1->CFGR1, HEX);
Serial.print("ADC1->SMPR = 0x"); Serial.println(ADC1->SMPR, HEX);
Serial.print("ADC1->CHSELR= 0x"); Serial.println(ADC1->CHSELR, HEX);
Serial.println("Mode: continuous (every 500 ms, avg of 16). Button D4 - single conversion");
}
void loop() {
static uint32_t tLast = 0;
// ---- Однократное измерение по кнопке ----
if (pressed()) {
uint32_t code = analogRead(ADC_PIN);
Serial.print("SINGLE: code = "); Serial.print(code);
Serial.print(" U = "); printMv(codeToMv(code)); Serial.println();
}
// ---- Непрерывное измерение с усреднением ----
if (millis() - tLast >= 500) {
tLast = millis();
uint32_t sum = 0, mn = ADC_MAX, mx = 0;
for (uint8_t i = 0; i < N_AVG; i++) {
uint32_t c = analogRead(ADC_PIN);
sum += c; if (c < mn) mn = c; if (c > mx) mx = c;
}
uint32_t avg = (sum + N_AVG / 2) / N_AVG;
Serial.print("CONT: code = "); Serial.print(avg);
Serial.print(" U = "); printMv(codeToMv(avg));
Serial.print(" (min "); Serial.print(mn); Serial.print(", max "); Serial.print(mx);
Serial.println(")");
}
}
Loading
st-nucleo-c031c6
st-nucleo-c031c6