1921ВК028 /АЦП /секвенсор /циклически

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

RabidRabbit
Сообщения: 136
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение RabidRabbit »

Код: Выделить всё

  // АЦП
  PMUSYS->ADCPWRCFG_bit.LDOEN = 1;
  PMUSYS->ADCPWRCFG_bit.LVLDIS = 0;
  RCU->ADCSARCLKCFG_bit.CLKSEL = RCU_ADCSARCLKCFG_CLKSEL_PLL1;
  RCU->ADCSARCLKCFG_bit.DIVEN = 0; // частота АЦП 33.3(3) МГц
  RCU->ADCSARCLKCFG_bit.CLKEN = 1;
  RCU->ADCSARCLKCFG_bit.RSTDIS = 1;
  RCU->CGCFGAPB_bit.ADCSAREN = 1;
  RCU->RSTDISAPB_bit.ADCSAREN = 1;
  ADCSAR->ACTL_bit.SELRES = ADCSAR_ACTL_SELRES_12bit;
  ADCSAR->ACTL_bit.ADCEN = 1;
  while ( 0 == ADCSAR->ACTL_bit.ADCRDY ) {}
  
  ADCSAR->EMUX_bit.EM0 = ADCSAR_EMUX_EM0_Cycle;
  ADCSAR->SEQ[0].SCCTL_bit.ICNT = 3;
  ADCSAR->SEQ[0].SCCTL_bit.RCNT = 0;
  ADCSAR->SEQ[0].SRTMR = 33332;
  ADCSAR->SEQ[0].SRQCTL_bit.RQMAX = 1;
  ADCSAR->SEQ[0].SRQSEL_bit.RQ0 = 0;
  ADCSAR->SEQ[0].SRQSEL_bit.RQ1 = 1;
  ADCSAR->SEQ[0].SRQCTL_bit.QAVGVAL = 0;
  ADCSAR->SEQ[0].SRQCTL_bit.QAVGEN = 0;
  
  ADCSAR->IM_bit.SEQIM0 = 1;
  ADCSAR->SEQEN_bit.SEQEN0 = 1;
  
  PLIC_int_enable( IsrVect_IRQ_ADC );
  
  //
  ADCSAR->SEQSYNC_bit.SYNC0 = 1;
  ADCSAR->SEQSYNC_bit.GSYNC = 1;  
обработчик прерывания

Код: Выделить всё

void PLIC_Handler_ADC(void) {
  uint16_t v_val = 0;
  for ( int i = 0; i < 4; ++i ) {
    v_val += (uint16_t)ADCSAR->SEQ[0].SFIFO;
  }
  g_adc_val = v_val / 4;
  g_read_val = true;
  ADCSAR->IC = ADCSAR_IC_SEQIC0_Msk;
}
Фигачит без остановки. Тактирование такое же 33.333333 МГц.
Artem_Zxc
Сообщения: 8
Зарегистрирован: 12 сен 2025, 11:31
Предприятие: RIF

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение Artem_Zxc »

Ну отличие только в этом:

Код: Выделить всё

  RCU->CGCFGAPB_bit.ADCSAREN = 1;
  RCU->RSTDISAPB_bit.ADCSAREN = 1;
Так же проверил ADCClkFreq. При запуске он - 12000000, после настройки - 33333333.
RabidRabbit
Сообщения: 136
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение RabidRabbit »

Что ещё можно глянуть: после пропадания прерываний в отладчике посмотреть содержимое ADC->MIS - какие флаги там взведены, проверить содержимое ADC->IM; ну и вообще посмотреть, не застряло ли оно в "умолчательном" обработчике прерываний. Кстати, в К1921ВГ015 регистр ADC->IC заявлен как "только для записи", а у Вас его чтение в обработчике происходит.
K_Chizhov
Сообщения: 5
Зарегистрирован: 22 авг 2025, 21:15
Предприятие: _

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение K_Chizhov »

Может FIFO переполняется?
Artem_Zxc
Сообщения: 8
Зарегистрирован: 12 сен 2025, 11:31
Предприятие: RIF

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение Artem_Zxc »

Revenons à nos moutons.
Появились новые вводные.
1. Переделал код на программный запуск.

Код: Выделить всё

ADC->EMUX_bit.EM0 = ADC_EMUX_EM0_SwReq;
Уменьшил частоту.
Результат такой же.
2. Самое важное! Определил, что прерывания перестают приходить, только когда подключены внешние сигналы на вход АЦП. Проверил на лабораторном БП, лабораторном генераторе и на развязанном генераторе сигналов (на аккумуляторе). При подключении на вход АЦП сигнала "AVCC3.3" от самой платы все работает!
Пробовал к развязанному источнику сигналов дополнительно развязать входное питание отладочной платы - результат отрицательный, прерывания со временем перестают приходить.
ea
Администратор
Сообщения: 110
Зарегистрирован: 10 окт 2014, 09:08

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение ea »

Artem_Zxc писал(а): 16 сен 2025, 08:40 Программа запускается на демо-борде (плата макетно-отладочная ИС 1921ВК028).
Настроен циклический опрос 2х каналов АЦП, с чтением данных в прерывании секвенсора (SEQ0).
После запуска, программа работает. Данные считываются в массив raw_value, но через какое-то время прерывание ADC_SEQ0_IRQHandler перестает срабатывать. Может сработать ~500 прерываний, а может ~10000, но по итогу прерывание перестает срабатывать.
Пробовал:
- различные варианты настроек секвенсора;
- другие АЦП;
- менял время SRTMR;
- убирал все другое из программы.
Результат такой же.

Подскажите, что я делаю не правильно?

Код:
void periph_init()
{
SystemCoreClockUpdate();
}
//------------------------------------------------------------------------------

//--- Main ----------------------------------------------------------------------
int main()
{
periph_init();
SysTick_Config(200000); // Частота процессора в KHz (200MHz)

//Настройка ADC
PMU->ADCPC_bit.LDOEN0 = 1;
while(!(PMU->ADCPC_bit.LDORDY0));

RCU->ADCCFG_bit.CLKSEL = 1; // SYSCLK=200МГц
RCU->ADCCFG_bit.DIVN = 2; // Выбираем делитель 6 (DIVN=2 & DIVEN=1), 200МГц/6=33,3Мгц
RCU->ADCCFG_bit.DIVEN = 1;
RCU->ADCCFG_bit.CLKEN = 1; // Включаем тактирование
RCU->ADCCFG_bit.RSTDIS = 1; // Снимаем бит сброса

ADC->ACTL[0].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[0].ACTL_bit.CALEN = 1; // калибровка
ADC->ACTL[0].ACTL_bit.ADCEN = 1; // разрешение работы АЦП

ADC->EMUX_bit.EM0 = ADC_EMUX_EM0_Cycle; // Циклически
ADC->SEQ[0].SCCTL_bit.ICNT = 3; //количество записей в FIFO для прерывания +1
ADC->SEQ[0].SCCTL_bit.RCNT = 0; //количество перезапусков
ADC->SEQ[0].SRTMR = 33332; // время задержки перезапуска секвенсора 0
ADC->SEQ[0].SRQCTL_bit.RQMAX = 1; // измерения по N+1 каналу
ADC->SEQ[0].SRQSEL0_bit.RQ0 = 0; // канал опроса
ADC->SEQ[0].SRQSEL0_bit.RQ1 = 1;

ADC->SEQ[0].SRQCTL_bit.QAVGVAL = 0;
ADC->SEQ[0].SRQCTL_bit.QAVGEN = 0;

ADC->IM_bit.SEQIM0 = 1;
ADC->SEQEN_bit.SEQEN0 = 1;//разрешение работы секвенсора

Энвик_EnableIRQ(ADC_SEQ0_IRQn);
// Запуск
while(!ADC->ACTL[0].ACTL_bit.ADCRDY);
ADC->SEQSYNC_bit.SYNC0 = 1;
ADC->SEQSYNC_bit.GSYNC = 1;

while (1)
{
if (BSP_Btn_GetState() == BSP_Btn_State_SB3) {
;
}
}
}

volatile uint32_t raw_value[16];
uint32_t Tmp_i1;

void ADC_SEQ0_IRQHandler(void)
{
int i=0;

if (ADC->RIS_bit.SEQRIS0)
{
ADC->IC_bit.SEQIC0 = 1; // Сбрасываем прерывание
Tmp_i1++;
for ( i = 0; i < 4; i++)
{
raw_value = ADC->SEQ[0].SFIFO; // Читаем очередное значение
}
}
}


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

Для защиты от данного явления необходимо дополнительно обеспечить фильтрацию аналогового питания микроконтроллера.
Artem_Zxc
Сообщения: 8
Зарегистрирован: 12 сен 2025, 11:31
Предприятие: RIF

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение Artem_Zxc »

Сделал опрос АЦП без прерываний (чтение по таймеру). То же самое: при соединении земли внешнего источника сигнала с AGND (DGND) АЦП перестают приходить данные от АЦП. Пробовал переинициализировать АЦП, тоже не помогает. Понятно что будет фильтр, но если рядом стоит мощный контактор, то ... .
Расскажите пожалуйста, что именно происходит и как онлайн восстановить работу АЦП.
RabidRabbit
Сообщения: 136
Зарегистрирован: 10 июн 2025, 12:11
Предприятие: HomeWork

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение RabidRabbit »

Пробовали делать сброс блоку АЦП?

Код: Выделить всё

RCU->RSTDISAPB_bit.ADCSAREN = 0;
RCU->RSTDISAPB;
RCU->RSTDISAPB_bit.ADCSAREN = 1;
и потом заново провести инициализацию АЦП?
Artem_Zxc
Сообщения: 8
Зарегистрирован: 12 сен 2025, 11:31
Предприятие: RIF

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение Artem_Zxc »

Да, и так и по-всякому пробовал.
ea
Администратор
Сообщения: 110
Зарегистрирован: 10 окт 2014, 09:08

Re: 1921ВК028 /АЦП /секвенсор /циклически

Сообщение ea »

Добрый день.
Мы проводили эксперимент при подключении входного аналогового сигнала с внешнего источника: "0" на pin "DGND" (в документации "AGND") и обнаружили прекращение прерываний секвенсора АЦП в случае воздействия на плату с микроконтроллером сильной электромагнитной помехи.

Для защиты от данного явления необходимо обеспечить фильтрацию аналогового питания микроконтроллера.

При подключении входного аналогового сигнала от самой платы: pin "AVCC3.3" на pin "Порт АЦП" прерывания работают стабильно
Ответить

Вернуться в «32-разрядные микроконтроллеры»