1921ВК028 /АЦП /секвенсор /циклически
Модераторы: ea, dav, bkolbov, Alis, pip, _sva_
1921ВК028 /АЦП /секвенсор /циклически
Программа запускается на демо-борде (плата макетно-отладочная ИС 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; // Читаем очередное значение
}
}
}
Настроен циклический опрос 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; // Читаем очередное значение
}
}
}
-
RabidRabbit
- Сообщения: 136
- Зарегистрирован: 10 июн 2025, 12:11
- Предприятие: HomeWork
Re: 1921ВК028 /АЦП /секвенсор /циклически
Код: Выделить всё
raw_value = ADC->SEQ[0].SFIFO; Re: 1921ВК028 /АЦП /секвенсор /циклически
Виноват. Там конечно же "кв. скобка i кв. скобка". Форум убирает, что в квадратных скобках, без обозначения code
Код: Выделить всё
raw_value[i] = ADC->SEQ[0].SFIFO; // Читаем очередное значение
Последний раз редактировалось Artem_Zxc 16 сен 2025, 09:47, всего редактировалось 2 раза.
-
RabidRabbit
- Сообщения: 136
- Зарегистрирован: 10 июн 2025, 12:11
- Предприятие: HomeWork
Re: 1921ВК028 /АЦП /секвенсор /циклически
А зачем нужна вот эта проверка в начале обработчика прерываний?
Код: Выделить всё
if (ADC->RIS_bit.SEQRIS0)Re: 1921ВК028 /АЦП /секвенсор /циклически
Наверно не нужна...
-
RabidRabbit
- Сообщения: 136
- Зарегистрирован: 10 июн 2025, 12:11
- Предприятие: HomeWork
Re: 1921ВК028 /АЦП /секвенсор /циклически
Я это к тому, что не может ли дёрнуться прерывание от другого флага, который Вы не проверяете. При этом зацикливание в обработчике прерывания обеспечено.
Re: 1921ВК028 /АЦП /секвенсор /циклически
Я ставил счетчик внутри:
и снаружи - количество одинаково.
Так же запускал программу без этого if.
Результат такой же: "сколько-то" прерываний приходит, потом перестают приходить.
Код: Выделить всё
if (ADC->RIS_bit.SEQRIS0)Так же запускал программу без этого if.
Результат такой же: "сколько-то" прерываний приходит, потом перестают приходить.
-
RabidRabbit
- Сообщения: 136
- Зарегистрирован: 10 июн 2025, 12:11
- Предприятие: HomeWork
Re: 1921ВК028 /АЦП /секвенсор /циклически
А если включать прерывания после запуска АЦП? Т.е. вот так
Код: Выделить всё
// Запуск
while(!ADC->ACTL[0].ACTL_bit.ADCRDY);
ADC->SEQSYNC_bit.SYNC0 = 1;
ADC->SEQSYNC_bit.GSYNC = 1;
// Включить обработчик
Энвик_EnableIRQ(ADC_SEQ0_IRQn);Re: 1921ВК028 /АЦП /секвенсор /циклически
Попробовал, результат такой же ((
-
RabidRabbit
- Сообщения: 136
- Зарегистрирован: 10 июн 2025, 12:11
- Предприятие: HomeWork
Re: 1921ВК028 /АЦП /секвенсор /циклически
Попробую проверить на К1921ВГ015, там АЦП примерно такой же.
