Как использовать прерывание АЦП на синей таблетке STM32

В настоящее время я использую платы STM32F1xx из http://dan.drown.org/stm32duino/package_STM32duino_index.json< /а> Чтобы запрограммировать мою синюю таблетку, но я не могу найти, как написать прерывание для АЦП. Я настроил регистры для вывода прерывания по завершении, но не могу найти, как написать код прерывания.

Я попробовал функцию «ISR(ADC_vect)», которая работает для Arduino, но компилятор жалуется, что «ISR» не распознается. Я пытался найти документацию для STM32duino, но то немногое, что я смог найти, даже не упоминало АЦП или какие-либо процедуры обработки прерываний. Я безуспешно искал на форуме STM32duino. Если кто знает как это решить или где найти информацию о коде прерывания для плат STM32 буду очень рад :)

, 👍2

Обсуждение

Быстрый гугл выдал мне void ADC_IRQHandler(){ ... }. Не уверен, что это правильно, так как я не знаком с STM32., @Gerben

@Gerben Не сработало :(, @Beacon of Wierd


3 ответа


Лучший ответ:

1

Как вы уже обнаружили, переопределяемая функция __irq_adc() определена слабо здесь и привязан к таблице векторов прерываний здесь.

Если вы определили его, но он не работает, возможно, это связано с тем, что вы полностью избавились от вызова attachInterrupt(), который делает больше, чем просто назначает обработчик прерывания; он также разрешает прерывание для этого АЦП. Итак:

myADC.calibrate();
myADC.setSampleRate(ADC_SMPR_1_5);
adc_enable_irq(ADC1, ADC_EOC);
myADC.setPins(&pin, 1);

extern "C" void __irq_adc() {
// обработка прерывания
// обязательно проверяйте статусы и очищайте флаги, как показано в обработчике по умолчанию
}

Не уверен, что extern "C" понадобится, возможно, понадобится, вам придется проверить и выяснить.

,

Это работало, хотя это работало, только если я использовал «attachInterrupt» на ADC, похоже, не работал только с регистрами: / Может быть, нужно вызвать attachInterrupt, чтобы связать функцию __irq_adc с таблицей векторов прерываний? Кроме того, для его работы требовался внешний "C"., @Beacon of Wierd

@BeaconofWierd Я не понимаю. Вы все еще используете attachInterrupt() вместо прямого переопределения __irq_adc()? Что именно работает?, @SoreDakeNoKoto

Я пытался просто добавить функцию __irq_adc(), но тогда она не вызывалась. Когда я также использовал attachInterrupt(), вызывалась функция __irq_adc(). Я пытался включать и отключать прерывания с помощью регистров, чтобы увидеть, была ли проблема в этом, но я по-прежнему мог использовать __irq_adc(), только если я сначала вызывал attachInterrupt() где-то в коде. Я убедился, что использовал правильный регистр для включения прерываний, отключив их после вызова attachInterrupt()., @Beacon of Wierd

@BeaconofWierd Это странно. Для ясности, вы добавили adc_enable_irq(ADC1, ADC_EOC); вместо attachInterrupt(), как я упоминал выше? Поскольку при этом я не вижу никакой разницы с существующим вызовом attachInterrupt() в STM32ADC.cpp. Также помните, что вы не можете тестировать с пустым __irq_adc(), вам нужно по крайней мере очистить флаг EOC, как показано в обработчике по умолчанию, иначе ваш код будет казаться зависшим. Также сначала избавьтесь от любых других регистровых операций., @SoreDakeNoKoto

Если это все еще не работает, опубликуйте весь свой скетч. Кажется, у меня где-то есть STM32..., @SoreDakeNoKoto

А, добавление adc_enable_ird также заставило это работать :) Вероятно, это лучший способ, чем вызов attachInterrupt(), при его использовании, похоже, возникла проблема, когда я не мог использовать 1,5 цикла для шага расчета, поэтому теперь и это исправлено :). Работало даже со всеми моими регистровыми вознями ^^ Большое спасибо :) Теперь моя скорость выборки БОЛЕЕ 9000!!! ;Д, @Beacon of Wierd

А, отлично. Начинал задаваться вопросом, были ли другие махинации в их библиотеке ADC., @SoreDakeNoKoto


0

сначала нужно включить прерывание (я не знаю, делает это обертка stm32 для arduino или нет):

NVIC_EnableIRQ(ADC1_IRQn);

тогда вам нужно написать ISR, как сказал Гербен:

extern "C" void ADC1_IRQHandler()
{
    //очистить флаг АЦП
}

extern "C", потому что [насколько мне известно] проекты arduino написаны на C++.

,

К сожалению, он не работает с библиотекой STM32duino :( Однако я нашел примеры того, как прикреплять прерывания к АЦП, для тех, кто хочет именно этого: https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/libraries/STM32ADC/examples/SingleConversionInterrupt/SingleConversionInterrupt. я не Хотя мне нужна как можно большая скорость для моего приложения, поэтому мне придется копать глубже, чтобы попытаться найти функцию, вызываемую самим ISR., @Beacon of Wierd


1

Я не смог найти функцию, вызываемую напрямую, но есть хороший пример, объясняющий, как прикреплять прерывания к АЦП, который хорошо работает: https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F1/libraries/STM32ADC/examples/SingleConversionInterrupt/SingleConversionInterrupt.ino

Если кто-то знает реальную функцию, вызываемую напрямую, было бы здорово добавить сюда, но до тех пор этот пример делает то, что мне нужно, и, надеюсь, поможет другим, столкнувшимся с той же проблемой.

,

Если вы перевернете стек вызовов в этом примере, вы получите ADC1->handlers[ADC_EOC] = yourfunction; и ADC1egs->CR1 |= (1U<<(ADC_EOC +ADC_CR1_EOCIE_BIT));, чтобы включить IRQ. Насколько я вижу., @Gerben

Да, я следовал коду туда, где выполнялась функция в ADC1->handlers[ADC_EOC], и она была внутри функции adc_irq, если я правильно помню, она даже была определена с помощью ключевого слова __weak, так что я был уверен, что у меня есть правильный, но почему-то и эта функция не работала, когда я писал свою версию :(, @Beacon of Wierd