Главная Новости

STM32F4 АЦП

Опубликовано: 06.09.2018

видео STM32F4 АЦП

STM32Cube ADC+PWM Регулировка яркости светодиодов используя ШИМ,АЦП и stm32f4 discovery

В последнее время было много экспериментов по STM32, о которых я не писал, хотелось запилить статью про USB амперметр-вольтметр. Чем крупнее задумываешь статью, тем ниже шанс что она появится В итоге материал завис на 3 месяца, в общем лучше буду как и раньше писать небольшие заметки, желающие могут самостоятельно слепить из маленьких кирпичиков необходимую девайсину. Текущая задача — ознакомиться с работой АЦП, на простом примере.



Цель: считываем измеренное значение с точностью 12 бит(4096), если оно больше 512 зажигаем PD12, больше 1024 — зажигаем PD13, больше 2048 — PD14, 3078 — PD15. Если кому то нужно перевести в вольты,

напряжение = (3.3/4096)*измеренное значение. Остальные пояснения по ходу.

Вначале нам нужно определиться с входом АЦП, советую на компе держать Cube MX это генератор кода, но лично мне он нравится наличием побочных плюшек, т.е. можно посмотреть сколько каких ресурсов, где какие входы/выходы.


STM32Cube ADC настройка АЦП для регулярного канала STM32F407 discovery

Сразу видно что IN0 выделен красным, т.е. его юзать нельзя.

В итоге ковыряемся в схеме и определяем, что на PA0 подключена кнопка, об этом кстати нам и сообщает куб.


Программирование МК STM32. УРОК 18. HAL. ADC. Regular Channel. DMA

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

RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1 ,ENABLE ) ; //включаем тактирование ацп1 ADC_DeInit ( ) ; //сбрасываем настройки АЦП по умолчанию RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA , ENABLE ) ; //включаем тактирование портаА GPIO_InitTypeDef porta_setup ; //создаем структуру porta_setup. GPIO_Mode = GPIO_Mode_AN ; //режим - аналоговый вход porta_setup. GPIO_Pin = GPIO_Pin_1 ; //первая ножка GPIO_Init (GPIOA , & porta_setup ) ; //записать настройки

Ножки могут быть цифровым входом-выходом, если на этой же ножке подцеплена альтернативная функция — UART, SPI, USB, ADC…. то нужно об этом сообщить в программе, что и сделано.

Теперь уже переходим к настройке непосредственно АЦП

ADC_InitTypeDef adc_setup ; //создаем структуру adc_setup. ADC_ContinuousConvMode = DISABLE ; //не делать длительных преобразований adc_setup. ADC_Resolution = ADC_Resolution_12b ; //разрешение 12 бит adc_setup. ADC_ScanConvMode = DISABLE ; //однократное преобразование adc_setup. ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None ; //не использовать триггер adc_setup. ADC_DataAlign = ADC_DataAlign_Right ; //выравнивание результата по правому краю ADC_Init (ADC1 , & adc_setup ) ; //записать настройки ADC_Cmd (ADC1 ,ENABLE ) ; //включить АЦП

Continuous conversion mode — преобразование начинается после завершения предыдущего. Нам это ни к чему.

Scan mode — режим используется для сканирования группы аналоговых каналов. Отключаем.

Conversion on external trigger and trigger polarity — преобразование может выполняться по внешнему событию, например по захвату таймера или по внешнему прерыванию. Отключаем.

Чтение значений АЦП. Минимальное количество циклов для преобразования считается как разрешение + 3, для 12 bits: 3 + 12 = 15 ADCCLK cycles. Работаем в режиме одиночного преобразования. По окончанию преобразования, устанавливается флаг EOC.

Регистр в который помещается результат 16 битный, а так как данные у нас 12 бит максимум, поэтому результат можно выравнивать либо по левому краю, либо по правому.

Настройка ножек для включения светодиодов

GPIO_InitTypeDef port_setup ; //создаем структуру RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOD , ENABLE ) ; //включаем тактирование портаD port_setup. GPIO_Mode = GPIO_Mode_OUT ; //ножка как выход port_setup. GPIO_OType = GPIO_OType_PP ; //режим пуш-пул port_setup. GPIO_PuPd = GPIO_PuPd_DOWN ; //подтяжка к земле port_setup. GPIO_Pin = GPIO_Pin_All ; //настройка для всего порта port_setup. GPIO_Speed = GPIO_Speed_2MHz ; //скорость 2мгц GPIO_Init (GPIOD , & port_setup ) ; //записать настройки

Полный исходник

#include "stm32f4xx.h" #include "stm32f4xx_adc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_rcc.h" int result ; u16 readADC1 (u8 channel ) { //настройка - канал 1, время преобразования 3 цикла ADC_RegularChannelConfig (ADC1 , channel , 1 , ADC_SampleTime_3Cycles ) ; //начать преобразование ADC_SoftwareStartConv (ADC1 ) ; // ждем окончания преобразования while ( ADC_GetFlagStatus (ADC1 , ADC_FLAG_EOC ) == RESET ) ; // возвращаем полученное значение return ADC_GetConversionValue (ADC1 ) ; } int main ( void ) { RCC_APB2PeriphClockCmd (RCC_APB2Periph_ADC1 ,ENABLE ) ; ADC_DeInit ( ) ; RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA , ENABLE ) ; //настройка альтернативной GPIO_InitTypeDef porta_setup ; //функции ножки PA1 GPIO_StructInit ( & porta_setup ) ; porta_setup. GPIO_Mode = GPIO_Mode_AN ; porta_setup. GPIO_Pin = GPIO_Pin_1 ; GPIO_Init (GPIOA , & porta_setup ) ; ADC_InitTypeDef adc_setup ; adc_setup. ADC_ContinuousConvMode = DISABLE ; adc_setup. ADC_Resolution = ADC_Resolution_12b ; adc_setup. ADC_ScanConvMode = DISABLE ; adc_setup. ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None ; adc_setup. ADC_DataAlign = ADC_DataAlign_Right ; ADC_Init (ADC1 , & adc_setup ) ; ADC_Cmd (ADC1 ,ENABLE ) ; GPIO_InitTypeDef port_setup ; RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOD , ENABLE ) ; port_setup. GPIO_Mode = GPIO_Mode_OUT ; port_setup. GPIO_OType = GPIO_OType_PP ; port_setup. GPIO_PuPd = GPIO_PuPd_DOWN ; port_setup. GPIO_Pin = GPIO_Pin_All ; port_setup. GPIO_Speed = GPIO_Speed_2MHz ; GPIO_Init (GPIOD , & port_setup ) ; while ( 1 ) { result = readADC1 (ADC_Channel_1 ) ; if ( result > 512 ) // (3,3/4096)*512 = 0,4125V { GPIO_SetBits (GPIOD ,GPIO_Pin_12 ) ; } else { GPIO_ResetBits (GPIOD ,GPIO_Pin_12 ) ; } if ( result > 1024 ) //0,825 { GPIO_SetBits (GPIOD ,GPIO_Pin_13 ) ; } else { GPIO_ResetBits (GPIOD ,GPIO_Pin_13 ) ; } if ( result > 2048 ) //1,65 { GPIO_SetBits (GPIOD ,GPIO_Pin_14 ) ; } else { GPIO_ResetBits (GPIOD ,GPIO_Pin_14 ) ; } if ( result > 3072 //2,475 { GPIO_SetBits (GPIOD ,GPIO_Pin_15 ) ; } else { GPIO_ResetBits (GPIOD ,GPIO_Pin_15 ) ; } } }

Вот так это все работает:

КРЕДИТ - БЛОК






Новости
rss