Почему Arduino Due останавливается после одного вызова ADC_Handler?
В приведенном ниже простом примере я просто программно запускаю прием АЦП, а затем устанавливаю цифровой выход встроенного светодиода в обработчике прерываний. Однако я не знаю, почему программа, похоже, останавливается.
void setup() {
Serial.begin(115200);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
adc_enable_channel(ADC, ADC_CHANNEL_6);
adc_enable_interrupt(ADC, ADC_IER_EOC6);
pmc_enable_periph_clk(ID_ADC);
NVIC_EnableIRQ(ADC_IRQn);
Serial.println("GO");
}
void loop()
{
Serial.println("RUNNING");
adc_start(ADC);
}
void ADC_Handler(void)
{
digitalWrite(13,HIGH);
adc_get_status(ADC);
}
Я знаю, что вызывается обработчик, потому что загорается светодиод. Основные циклы, похоже, перестают работать после этого, так как они больше ничего не печатают. Если я не инициирую приобретение в главном цикле, оно будет длиться вечно. Аналогично, если я не включу прерывание или NVIC.
Я не могу объяснить такое поведение.
@Adam V. Steele, 👍1
Обсуждение1 ответ
Лучший ответ:
Замораживание произойдет, если только
биты ADC_ISR 0-15 не будут равны 0 в конце обработчика прерываний. В этом случае ISR возвращает бит 6, установленный для включенного канала (6). Для многих прерываний бит может быть сброшен до 0, просто прочитав ADC_ISR
. Однако для прерываний в конце преобразования необходимо прочитать преобразованный регистр данных для этого канала, чтобы бит ISR был установлен в 0.
Поэтому этот код не будет остановлен. (Я включил некоторые дополнительные распечатки, чтобы прояснить значения регистра в каждый момент времени.)
volatile uint32_t LAST = 0;
volatile uint32_t CHAN6 = 0;
volatile uint32_t ISR1 = 0;
volatile uint32_t ISR2 = 0;
void setup() {
Serial.begin(115200);
adc_enable_channel(ADC, ADC_CHANNEL_6);
adc_enable_interrupt(ADC, ADC_IER_EOC6);
pmc_enable_periph_clk(ID_ADC);
NVIC_ClearPendingIRQ(ADC_IRQn);
NVIC_EnableIRQ(ADC_IRQn);
Serial.println("GO");
adc_configure_trigger(ADC, ADC_TRIG_SW,0);
}
void loop()
{
Serial.println(ISR1,BIN);
Serial.println(ISR2,BIN);
adc_start(ADC);
delay(1000);
}
void ADC_Handler(void)
{
ISR1 = adc_get_status(ADC); // chan 6 bit =1
LAST = adc_get_latest_value(ADC);
ISR1 = adc_get_status(ADC); // chan 6 bit =1 (still)
CHAN6 = adc_get_channel_value(ADC, ADC_CHANNEL_6);
ISR2 = adc_get_status(ADC); // chan 6 bit = 0
}
Однако я отмечу, что в таблице данных для чипа на странице 1322 указано, что чтение одного из регистров ADC_CDR очищает соответствующий бит EOC. Чтение ADC_LCDR очищает бит DRDY и бит EOC, соответствующие последнему преобразованному каналу.
Это кажется ложным. Чтение ADC_LCDR не очищает бит состояния и приведет к зависанию. ADC_CDR6
необходимо прочитать специально, чтобы избежать зависания.
- Запуск передачи SPI с помощью прерывания в Arduino Due
- Контакт клавиатуры как прерывание (проводка или программирование)
- Почему функция обработчика NVIC_EnableIRQ запускается только один раз?
- Комментарии изменяют поведение компиляции (переопределение слабой ссылки sysTickHook)
- Генерация комплементарного ШИМ с внешним триггером с помощью Arduino Due
- Использование millis() и micros() внутри процедуры прерывания
- Подсчет импульсов с прерыванием
- Arduino Due vs Mega 2560
В вашем коде настройки нет ссылки на "ADC_Handler", поэтому я сомневаюсь, что это действительно называется., @PMF
Возможный дубликат: https://arduinoprosto.ru/q/19924/arduino-due-interrupt-based-adc-hangs-processing?rq=1, @PMF
@PMF Как и в случае с другими ISR, он переопределяет слабую ссылку в "Arduino15\пакеты\arduino\оборудование\sam\1.6.12\ядра\arduino\coretex_handlers.c". Это определенно называется, потому что светодиод загорается, только если есть эта цифровая запись., @Adam V. Steele