Давайте попробуем разобраться как работает аналого цифровой преобразователь - АЦП или adc в stm32. АЦП как следует из названия преобразует аналоговый сигнал в сигнал понятный микроконтроллеру а именно цифровой код. Измерение аналогового сигнала на входе происходит с определенной частотой (дискретно), чем выше частота измерения тем выше дискретизация измеряемого сигнала тем точнее произойдет преобразования аналога в цифру.
К примеру при частоте 24 МГц, время преобразования будет 1,17 мкс.
АЦП в микроконтроллерах STM32 имеет следующие параметры:
Для считывания данных с 16-ти внешних каналов имеется мультиплексор, обращение к каждому каналу осуществляется поочередно.
Преобразование сигнала может осуществлятся в разных режимах : однократном, непрерыном, по таймеру, по триггеру. Имеет возможность работы с DMA (прямого доступа к памяти).
Измеренное напряжение сравнивается с опорным V_REF- и V_REF+.
V_REF- подключается к земле, а V_REF+ можно подключить к питанию микроконтроллера либо к источнику опорного напряжения (ИОН)
Напряжение | Результат |
V_Ref- | 0 |
V_in | V_in/(V_Ref+-VRef-)*4096 |
V_Ref+ | 4096 |
Не буду описывать регистры для работы с АЦП вы их можете сами посмотреть в документации на соответствующий микроконтроллер stm, а лучше приведу код программы для настройки АЦП.
void adc_init() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // настройки ADC ADC_InitTypeDef ADC_InitStructure; ADC_StructInit(&ADC_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // режим работы - одиночный, независимый ADC_InitStructure.ADC_ScanConvMode = DISABLE; // не сканировать каналы, просто измерить один канал ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // однократное измерение ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // без внешнего триггера ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //выравнивание битов результат - прижать вправо ADC_InitStructure.ADC_NbrOfChannel = 1; //количество каналов - одна штука ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); // настройка канала ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_55Cycles5); // калибровка АЦП ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); }
Метод получения результата измерения
uint16_t get_adc_value() { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); return ADC_GetConversionValue(ADC1); }
Данный метод работает следующим образом: сначала запускается преобразование, преобразование осуществляется до тех пор пока флаг преобразования EOC (END of Conversion) не будет изменен, далее производится считывание данных с регистра DR.
Остается только в главном методе main проинициализировать на АЦП и в цикле получать значение.
void main() { adc_init(); uint16_t value = 0; while(1) value = get_adc_value(); }