STM32 NVIC ADC прерывание не запускается

У меня есть STM32F411VET, и я хочу, чтобы прерывание запускалось после завершения преобразования АЦП. В документации говорится следующее:

В режиме одиночного преобразования АЦП выполняет одно преобразование. Этот режим запускается с битом CONT в 0 одним из следующих способов:

  • установка бита SWSTART в регистре ADC_CR2 (только для обычного канала) После завершения преобразования выбранного канала:

Если был преобразован обычный канал:

  • Преобразованные данные сохраняются в 16-битном регистре ADC_DR.
  • Установлен флаг EOC (конец преобразования).
  • Прерывание генерируется, если установлен бит EOCIE.

Затем АЦП останавливается.

Таким образом, у меня есть следующий код:

Включение прерываний

SET_BIT(ADC1->CR1, ADC_CR1_EOCIE);      // enable interrupt generation
NVIC_EnableIRQ(ADC_IRQn);       // allow interrupt in NVIC
__enable_irq();     // change cpu flags to enable interrupts

Настройка ADC

void ConfigureADC()
{
    // PA1 - ADC_IN1
    SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_0 | GPIO_MODER_MODE1_1); 
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);      // enable ADC1 clock
    SET_BIT(ADC1->CR2, ADC_CR2_ADON);       // enable ADC1
    SET_BIT(ADC1->CR1, ADC_CR1_RES_1);      // 8-bit conversion
    SET_BIT(ADC->CCR, ADC_CCR_ADCPRE_0);    // prescaler - /4
    SET_BIT(ADC1->SQR3, 1);     // channel 1 (PA1)
    SET_BIT(ADC1->CR2, ADC_CR2_CONT);       // Continious mode
}

Обработчик прерывания

void ADC_IRQHandler()
{
    vConverted = true;
    CLEAR_BIT(ADC1->SR, ADC_SR_EOC);        // Software clears EOC flag
}

В режиме отладки или при чтении непосредственно из регистра ADC1->DR я получаю прекрасный результат.

Меня беспокоит то, что я не могу отладить обработчик прерывания в uVision5 (IDE, которую я использую).

Проблема в том, что обработчик прерывания не выполняется, и я не знаю, как его правильно отладить.


Спасибо всем за помощь.


person hrust    schedule 27.04.2017    source источник
comment
Вы должны иметь возможность отлаживать обработчик прерывания в uVision 5 без проблем, если это происходит, поэтому я был бы очень обеспокоен этим.   -  person Realtime Rik    schedule 28.04.2017
comment
@RealtimeRik Я не могу поставить точку останова ни на одной строке обработчика прерывания   -  person hrust    schedule 28.04.2017
comment
Ты должен быть способен. Вы уверены, что обработчик, в который вы пытаетесь установить точку останова, действительно включен в окончательную сборку? Обычно, когда вы не можете этого сделать, функция фактически отсутствует в сборке. Попробуйте поискать в файле карты, вы можете обнаружить, что у вас есть только обработчик по умолчанию.   -  person Realtime Rik    schedule 28.04.2017
comment
@RealtimeRik Все три блока кода, представленные в вопросе, являются частью main.c файла, который является единственным файлом, который я создал. Таким образом, обработчик находится рядом с функцией main.   -  person hrust    schedule 28.04.2017
comment
Подумать только, но попробуйте объявить функцию недействительной ADC_IRQHandler (void).   -  person Realtime Rik    schedule 28.04.2017
comment
@RealtimeRik Я пытался переместить саму функцию до и после основной функции (в настоящее время она находится в самом конце файла), а также иметь прототип функции в самом начале, сразу после включения. Я также пробовал сделать заявление extern, потому что делал все, что мог придумать. Могут ли быть другие обработчики прерываний (как я могу проверить это в режиме отладки) или чип, имеющий какой-либо сбой (исключение ядра)?   -  person hrust    schedule 28.04.2017
comment
Если вы не можете установить точку останова, вероятно, по какой-то причине она не нарушает слабую привязку обработчика по умолчанию в таблице векторов и, следовательно, не включается в сборку. Возможно, для этого важен параметр void.   -  person Realtime Rik    schedule 28.04.2017
comment
@RealtimeRik Проблема была тривиальной, использовался компилятор C ++, а не C. Таким образом, привязка не была переписана. Должен ли я удалить этот вопрос сейчас?   -  person hrust    schedule 28.04.2017
comment
Возможно, вам стоит опубликовать ответ вместо того, чтобы удалять вопрос.   -  person linuxfan says Reinstate Monica    schedule 28.04.2017
comment
Вы должны иметь возможность отметить свой ответ как полученный через день или два.   -  person Realtime Rik    schedule 28.04.2017


Ответы (2)


Следует отметить, что используется C ++, и из-за этого имена скомпилированных функций не совпадают с именами в коде, поэтому они не привязываются / не заменяются. Обработчик IRQ не упоминался и, следовательно, не был включен в скомпилированный код.

Чтобы сделать функции "C" связанными, необходимо использовать extern "C".

extern "C"
{
    void ADC_IRQHandler();
    // Other handlers
}

Чтобы получить дополнительную информацию о extern "C", обратитесь к этому ответу.

person hrust    schedule 28.04.2017
comment
Да, обработчики прерываний должны быть написаны на C, по крайней мере, вектор. Это то, что я получил, объявив, что void xxx () не имеет параметра void. Я должен был заметить, что на самом деле это был С ++ - person Realtime Rik; 28.04.2017
comment
Вы должны упомянуть об этом в своем первоначальном вопросе. В противном случае это пустая трата времени. - person 0___________; 29.04.2017

Просто проверьте, вызываете ли вы SET_BIT (ADC1-> CR1, ADC_CR1_EOCIE); после ADC_Configure

person 0___________    schedule 27.04.2017
comment
Я устанавливаю флаг прерывания и включаю прерывания в самый последний момент после завершения всех настроек. - person hrust; 28.04.2017
comment
1. Посмотрите, как называется вектор-обработчик в векторной таблице (некоторые файлы запуска не определяют все имена векторных подпрограмм). Обработчик прерывания может отличаться в зависимости от используемой инструментальной цепочки. - person 0___________; 28.04.2017