Встроенный АЦП и непонятные моменты

ejsanyo

Active member
Продолжаем работать с периферией. И вот вопрос: кто-нибудь ещё кроме меня пробовал пользовать АЦП? Если да, какие ваши впечатления и как вам удалось заставить работать его лучше всего?
Расскажу пока о своих текущих наблюдениях:
  • Странности встречают нас сразу на этапе настройки: источник опоры выбирают два бита, EXTPAD и EXTEN, что даёт выбор между встроенным ИОНом, когда они оба 0, внешним входом, когда они оба 1 (наверное), и...чем ещё? Или эти два бита следует изменять вместе и синхронно, иначе будет нерабочая схема?
  • Посмотрим далее в HAL_ADC_Init():
    C:
    #ifdef MIK32V0    hadc->Instance->ADC_CONFIG |= (hadc->Init.EXTRef << ADC_CONFIG_EXTREF_S) |   /* Настройка источника опорного напряжения */
    (hadc->Init.EXTClb << ADC_CONFIG_EXTPAD_EN_S); /* Выбор внешнего источника опорного напряжения */
    #else // MIK32V2
    hadc->Instance->ADC_CONFIG = (hadc->Instance->ADC_CONFIG & (~ADC_CONFIG_SAH_TIME_M)) |
    ((hadc->Instance->ADC_CONFIG >> 1) & ADC_CONFIG_SAH_TIME_M) |
    (hadc->Init.EXTRef << ADC_CONFIG_EXTREF_S) | /* Настройка источника опорного напряжения */
    (hadc->Init.EXTClb << ADC_CONFIG_EXTPAD_EN_S); /* Выбор внешнего источника опорного напряжения */
    #endif // MIK32V0
    }
    Ого, да здесь ещё и разные версии чипа всплывают! И если для "MIK32V0" всё просто и понятно, то что проворачивает код с ADC_CONFIG для актуальной версии "MIK32V2"? Мне пока как-то не очевидно что, но без этого, похоже, АЦП адекватно не работает.
  • Кстати про этот параметр, SAH_TIME: как правило, при замедлении скорости работы в АЦП уровень шумов снижается, но, похоже, не с этим контроллером. Пробовал менять значение этих битов, и единственная замеченная разница, что при уменьшении значения ниже какого-то порога, АЦП, похоже, перестаёт работать. А младшие разряды отсчётов дёргаются примерно одинаково.
  • Величина встроенной опоры у моего чипа оказалась где-то в районе 1,215В (смотрел уровень напряжения на входе, которое давало результат 0x0FFF). Пробовал подстраивать её, меняя значения битов COEF_REFICLB и COEF_REFVCLB от нуля до максимума, и...похоже это не даёт ничего. По крайней мере, разницу в шумах я не заметил. Так что не понятно, то ли подстройка на самом деле не работает, то ли я что-то делаю не так?
 

Евгений

New member
Пробовал ацп от встроенного опорного. Работает. Есть небольшой шум.
С внешним работает как то криво - все что выше 1,2 вольт = 4093. Пришлось собирать делитель 3->1.2, чтобы переменником можно было покрутить.
С настройками не баловался сейчас пока отложил этот модуль в сторону.
 

ejsanyo

Active member
Ещё такой странный момент обнаружил: когда по очереди переключаю аналоговые входы 0->1->2->0... и в каждом канале делаю однократное измерение, то в результатах получается какая-то зависшая дичь, не зависящая от фактического сигнала на этих входах! 😵
Удалось заставить адекватно работать в многоканальном режиме только так:
  • Включаю циклические измерения HAL_ADC_ContinuousEnable(&hadc);
  • Переключаю канал hadc.Init.Sel = ADC_CHANNEL0; и HAL_ADC_ChannelSet(&hadc);
  • Делаю небольшую паузу. Наверно, чтобы успел переключиться внутренний коммутатор. А то у меня иногда захватывались данные из предыдущего канала.
  • Читаю результат HAL_ADC_GetValue(&hadc);
  • Переключаю на следующий канал hadc.Init.Sel = ADC_CHANNEL1; и HAL_ADC_ChannelSet(&hadc);
  • Делаю небольшую паузу.
  • Читаю результат HAL_ADC_GetValue(&hadc);
  • Переключаю на следующий канал...
  • ...
  • ...
Кстати, похоже, что в циклическом режиме регистр ADC_VALID не работает - там всегда висит 0.
 

papakaplo

New member
Помогите проинициализировать ADC для 1.5 пина. Не могу запустить, по нулям всё показывает. Не понимаю что записывать в регистр SAH_TIME, и как в регистре SEL выбрать АЦП0 для 1.5 пина
C:
        PM->CLK_APB_P_SET |=PM_CLOCK_APB_P_ANALOG_REGS_M;    //включаем на шине APB_P аналоговые блоки
        ANALOG_REG ->ADC_CONFIG |= ADC_CONFIG_EN_M;            //Включаем питание АЦП

        GPIO_1->DIRECTION_IN =  1<<(5);
        PAD_CONFIG ->PORT_1_CFG  |= 1<<10;
        PAD_CONFIG ->PORT_1_CFG  |= 1<<11;

        ANALOG_REG ->ADC_CONFIG |= 0x800;
        ANALOG_REG ->ADC_CONFIG |=1<<4;


        ANALOG_REG ->ADC_CONFIG &=~ADC_CONFIG_EXTREF_M;        // Выбор источника опорного напряжения:«1» внешний;«0» встроенный
        ANALOG_REG ->ADC_CONFIG &=~ADC_CONFIG_EXTPAD_EN_M;    // Выбор источника внешнего опорного напряжения («1» внешний вывод или «0» настраиваемый ОИН)
        ANALOG_REG->ADC_CONTINUOUS = 1; //запуск непрерывного измерения
 

ejsanyo

Active member
Помогите проинициализировать ADC для 1.5 пина. Не могу запустить, по нулям всё показывает. Не понимаю что записывать в регистр SAH_TIME, и как в регистре SEL выбрать АЦП0 для 1.5 пина
HAL-ом в принципе не пользуетесь? Попробуйте сначала библиотечными функциями, а как хоть что-то получится, дальше смотрите в чём разница. Тем более, что, как выяснилось ранее c HAL_ADC_Init(), нам что-то явно не договаривают про нюансы этого блока. :censored:
Гляньте также исходники в архиве, про моё поделие, конечно же в папке FW. Там у меня как раз используется канал ADC0 aka нога 1.5.
 
Сверху