Спасибо Neekeetos, с помощью товарища одного мне удалось собрать код
На низких частотах работает нормально. Из проблем у меня выявилось небольшое отклонение по вольтажу - 4095 значение при 2.8 В
Частоту мерит без проблем
Код: Выделить всё
#include <тут подключите библиотеки необходимые>
void init_gpio(void);
void init_timer(void);
uint16_t uint16_time_diff(uint16_t now, uint16_t before);
volatile uint16_t systick_ms = 0;
volatile uint16_t Tcapture1 = 0, Tcapture2 = 0;
volatile uint8_t T1capture_is_first = 1, T1capture_is_ready = 0;
uint32_t period;
uint32_t adcvalue;
void ADC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* PCLK2 is the APB2 clock */
/* ADCCLK = PCLK2/6 = 72/6 = 12MHz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
/* Enable ADC1 clock so that we can talk to it */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Put everything back to power-on defaults */
ADC_DeInit(ADC1);
/* ADC1 Configuration ----------*/
/* ADC1 and ADC2 operate independently */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
/* Disable the scan conversion so we do one at a time */
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
/* Don't do contimuous conversions - do them on demand */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
/* Start conversin by software, not an external trigger */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
/* Conversions are 12 bit - put them in the lower 12 bits of the result */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
/* Say how many channels would be used by the sequencer */
ADC_InitStructure.ADC_NbrOfChannel = 1;
/* Now do the setup */
ADC_Init(ADC1, &ADC_InitStructure);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
//настройка канала АЦП
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
//настройка прерывания для ацп
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_EnableIRQ(ADC1_2_IRQn);
}
//прерывание измерит значение и передаст переменной adcvalue
void ADC1_2_IRQHandler(void)
{
//обработали прерывание
if (ADC_GetITStatus(ADC1, ADC_IT_EOC))
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
adcvalue = ADC_GetConversionValue(ADC1);
}
}
int main(void)
{
static uint32_t toggle_ms = 0;
//тут настройте тактирование и прочие параметры
init_gpio();
init_timer();
ADC_Configuration();
//SysTick_Config(SystemCoreClock / 1000);
while (1)
{
if (T1capture_is_ready)
{
NVIC_DisableIRQ(TIM3_IRQn);
T1capture_is_ready = 0;
/* Обрабатываем захваченный период */
period = uint16_time_diff(Tcapture2, Tcapture1);
// ...
NVIC_EnableIRQ(TIM3_IRQn);
}
//тут уже оперируйте со значением амплитуды adcvalue
}
}
void init_gpio(void)
{
GPIO_InitTypeDef gpio_cfg;
GPIO_StructInit(&gpio_cfg);
/* Таймер TIM3, канал 1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
gpio_cfg.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio_cfg.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &gpio_cfg);
//светодиоды PC9 и PC8
gpio_cfg.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
gpio_cfg.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_cfg.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOC, &gpio_cfg);
}
void init_timer(void)
{
TIM_TimeBaseInitTypeDef timer_base;
TIM_ICInitTypeDef timer_ic1;
TIM_ICInitTypeDef timer_ic2;
/* Подаём такты на TIM3 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Настраиваем предделитель так, чтобы таймер считал миллисекунды.
На бо́льших частотах следите, чтобы предделитель не превысил
максимальное значение uint16_t - 0xFFFF (65535) */
TIM_TimeBaseStructInit(&timer_base);
//прескалер для измерения низких частот
timer_base.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInit(TIM3, &timer_base);
/* Настраиваем захват сигнала:
- канал: 1
- счёт: по нарастанию
- источник: напрямую со входа
- делитель: отключен
- фильтр: отключен */
timer_ic1.TIM_Channel = TIM_Channel_1;
timer_ic1.TIM_ICPolarity = TIM_ICPolarity_Rising;
timer_ic1.TIM_ICSelection = TIM_ICSelection_DirectTI;
timer_ic1.TIM_ICPrescaler = TIM_ICPSC_DIV1;
timer_ic1.TIM_ICFilter = 0;
TIM_ICInit(TIM3, &timer_ic1);
timer_ic2.TIM_Channel = TIM_Channel_2;
timer_ic2.TIM_ICPolarity = TIM_ICPolarity_Falling;
timer_ic2.TIM_ICSelection = TIM_ICSelection_DirectTI;
timer_ic2.TIM_ICPrescaler = TIM_ICPSC_DIV1;
timer_ic2.TIM_ICFilter = 0;
TIM_ICInit(TIM3, &timer_ic2);
/* Разрешаем таймеру генерировать прерывание по захвату */
TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
/* Включаем таймер */
TIM_Cmd(TIM3, ENABLE);
/* Разрешаем прерывания таймера TIM3 */
NVIC_EnableIRQ(TIM3_IRQn);
}
void TIM3_IRQHandler(void)
{
//если сработало прерывание по фронту
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
/* Даём знать, что обработали прерывание */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
// /* Запоминаем предыдущее измерение и считываем текущее */
/* время будет как разность этих двух значении */
Tcapture1 = Tcapture2;
Tcapture2 = TIM_GetCapture1(TIM3);
// /* Для корректной обработки нужно минимум два измерения */
if (!T1capture_is_first)
T1capture_is_ready = 1;
T1capture_is_first = 0;
//одновременно будем считать, что здесь высокий уровень сигнала, а значит можно измерить амплитуду
//запускаем конвертацию АЦП
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//
/* Тут как-нибудь обрабатываем событие over-capture, если провороним */
if (TIM_GetFlagStatus(TIM3, TIM_FLAG_CC1OF) != RESET)
{
TIM_ClearFlag(TIM3, TIM_FLAG_CC1OF);
// ...
}
}
}
void SysTick_Handler(void)
{
++systick_ms;
}
uint16_t uint16_time_diff(uint16_t now, uint16_t before)
{
return (now >= before) ? (now - before) : (UINT16_MAX - before + now);
}