Однократное и непрерывное измерение ADC: различия между версиями

Материал из MIK32 микроконтроллер
Нет описания правки
Нет описания правки
Строка 84: Строка 84:
[[Файл:Вывод UART в примере один.png|мини|Вывод UART в примере 1]]
[[Файл:Вывод UART в примере один.png|мини|Вывод UART в примере 1]]
Подадим на вывод Port0.9 напряжение 0.6В. Вывод UART можно видеть на рисунке.
Подадим на вывод Port0.9 напряжение 0.6В. Вывод UART можно видеть на рисунке.
Теперь изменим ИОН на внешний от вывода ADC_REF - Port1.10. Это можно сделать в конфигураторе, либо в функции ADC_Init, которая должна выглядеть так:<syntaxhighlight lang="c" line="1">
static void ADC_Init(void)
{
    hadc.Instance = ANALOG_REG;
    hadc.Init.Sel = ADC_CHANNEL5;
    hadc.Init.EXTRef = ADC_EXTREF_ON; /* Выбор источника опорного напряжения: «1» - внешний; «0» - встроенный */
    hadc.Init.EXTClb = ADC_EXTCLB_ADCREF; /* Выбор источника внешнего опорного напряжения: «1» - внешний вывод; «0» - настраиваемый ОИН */
    HAL_ADC_Init(&hadc);
}
</syntaxhighlight>

Версия от 10:32, 17 февраля 2023

В примере будут запущены измерения ADC (АЦП) в однократном и непрерывном режиме.

Работа с конфигуратором (В разработке)

Для начала настроем в конфигураторе тактирование mik32, например, от внешнего кварца 32МГц. Затем настроем делители шины. Так как АЦП тактируется от шины APB_P_CLK, то зададим делители AHB_DIV и APB_P_DIV. В данном примере оставим делители по умолчанию. В итоге вкладка с тактированием должна выглядеть так:

(Картинка тактирования из конфигуратора. В работе)

Затем перейдем к настройке самого АЦП. Для этого откроем вкладку АЦП и нажмем включить.

После этого появится настройки канала и источника опорного напряжения (ИОН). Выберем 5-й канал АЦП, которому соответствует вывод Port0.9.

Настройки ADC в конфигураторе

В АЦП есть 3 источника опорного напряжения. Внутренний считается встроенным в АЦП. Настраиваемый ИОН и источник от внешнего вывода ADC_REF считаются внешними по отношению к внутреннему ИОН АЦП. Выберем "Внутренний".

В итоге настройки таймера в конфигураторе должны выглядеть как на рисунке.

Нажимаем кнопку сохранения и генерации. В итоге у нас появится проект для PlatformIo. Далее работа идет в visual studio code.

Использование библиотеки HAL_ADC

В сгенерированном проекте в файле main.c должна быть функция ADC_Init, в которой будут заданы настройки для ADC. Выглядит она так:

static void ADC_Init(void)
{
    hadc.Instance = ANALOG_REG;

    hadc.Init.Sel = ADC_CHANNEL5;
    hadc.Init.EXTRef = ADC_EXTREF_OFF; /* Выбор источника опорного напряжения (внешний или встроенный) */
    hadc.Init.EXTClb = ADC_EXTCLB_ADCREF; /* Выбор источника внешнего опорного напряжения (внешний вывод или настраиваемый ОИН) */

    HAL_ADC_Init(&hadc);
}

Кроме этого в функции SystemClock_Config приведены настройки для тактирования. Убедитесь что в PeriphClkInit.PMClockAPB_P присутствует PM_CLOCK_ANALOG_REG_M. Для смены функции вывода на аналоговую должен быть затактирован контроллер выводов (в PeriphClkInit.PMClockAPB_M должен быть PM_CLOCK_PAD_CONFIG_M или PMCLOCKAPB_M_DEFAULT). Сама функция должна выглядеть примерно так:

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInit = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

    RCC_OscInit.OscillatorEnable = RCC_OSCILLATORTYPE_OSC32K | RCC_OSCILLATORTYPE_OSC32M;   
    RCC_OscInit.OscillatorSystem = RCC_OSCILLATORTYPE_OSC32M;                          
    RCC_OscInit.AHBDivider = 0;                             
    RCC_OscInit.APBMDivider = 0;                             
    RCC_OscInit.APBPDivider = 0;                             
    RCC_OscInit.HSI32MCalibrationValue = 0;                  
    RCC_OscInit.LSI32KCalibrationValue = 0;
    HAL_RCC_OscConfig(&RCC_OscInit);

    PeriphClkInit.PMClockAHB = PMCLOCKAHB_DEFAULT;    
    PeriphClkInit.PMClockAPB_M = PMCLOCKAPB_M_DEFAULT | PM_CLOCK_WU_M | PM_CLOCK_PAD_CONFIG_M;     
    PeriphClkInit.PMClockAPB_P = PMCLOCKAPB_P_DEFAULT | PM_CLOCK_UART_0_M | PM_CLOCK_ANALOG_REG_M;     
    PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_NO_CLK;
    PeriphClkInit.RTCClockCPUSelection = RCC_RTCCLKCPUSOURCE_NO_CLK;
    HAL_RCC_ClockConfig(&PeriphClkInit);
}

Для демонстрации вывода текста в PeriphClkInit.PMClockAPB_P присутствует PM_CLOCK_UART_0_M. У вас его может не быть так как UART нужно включить отдельно. В начале main.c можно видеть объявление структуры с набором настроек для АЦП, которую использует функция инициализации ADC_Init.

ADC_HandleTypeDef hadc;

void SystemClock_Config(void);
static void ADC_Init(void);

Для запуска однократного измерения следует использовать функцию HAL_ADC_Single. Для получения значения используйте функцию HAL_ADC_WaitAndGetValue. Функция main должна выглядеть примерно так:

int main()
{    

    SystemClock_Config();
    
    ADC_Init();

    uint16_t value = 0;

    while (1)
    {    
        HAL_ADC_Single(&hadc);
        value = HAL_ADC_WaitAndGetValue(&hadc);
        xprintf("ADC%d: %d (V = %d,%d)\n", hadc.Init.Sel, value, (value*1200/4095)/1000, (value*1200/4095)%1000);

        for (volatile int i = 0; i < 1000000; i++);
    }
       
}
Вывод UART в примере 1

Подадим на вывод Port0.9 напряжение 0.6В. Вывод UART можно видеть на рисунке.

Теперь изменим ИОН на внешний от вывода ADC_REF - Port1.10. Это можно сделать в конфигураторе, либо в функции ADC_Init, которая должна выглядеть так:

static void ADC_Init(void)
{
    hadc.Instance = ANALOG_REG;

    hadc.Init.Sel = ADC_CHANNEL5;
    hadc.Init.EXTRef = ADC_EXTREF_ON; /* Выбор источника опорного напряжения: «1» - внешний; «0» - встроенный */
    hadc.Init.EXTClb = ADC_EXTCLB_ADCREF; /* Выбор источника внешнего опорного напряжения: «1» - внешний вывод; «0» - настраиваемый ОИН */

    HAL_ADC_Init(&hadc);
}