Как использовать прерывание АЦП на синей таблетке STM32
В настоящее время я использую платы STM32F1xx из http://dan.drown.org/stm32duino/package_STM32duino_index.json< /а> Чтобы запрограммировать мою синюю таблетку, но я не могу найти, как написать прерывание для АЦП. Я настроил регистры для вывода прерывания по завершении, но не могу найти, как написать код прерывания.
Я попробовал функцию «ISR(ADC_vect)», которая работает для Arduino, но компилятор жалуется, что «ISR» не распознается. Я пытался найти документацию для STM32duino, но то немногое, что я смог найти, даже не упоминало АЦП или какие-либо процедуры обработки прерываний. Я безуспешно искал на форуме STM32duino. Если кто знает как это решить или где найти информацию о коде прерывания для плат STM32 буду очень рад :)
@Beacon of Wierd, 👍2
Обсуждение3 ответа
Лучший ответ:
Как вы уже обнаружили, переопределяемая функция __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
сначала нужно включить прерывание (я не знаю, делает это обертка 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
Я не смог найти функцию, вызываемую напрямую, но есть хороший пример, объясняющий, как прикреплять прерывания к АЦП, который хорошо работает: 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
- Stm32 Blue Pill Внутренняя Конфигурация Опорного напряжения АЦП
- Выход AnalogRead() колеблется, даже если контакт заземлен
- Запуск АЦП, запускаемый TIMER1_COMPB
- Регистр ADCH Arduino Uno завис на значении 255 при чтении из ISR
- Как соединить автономный многоканальный adc с последовательным?
- Нарастающий и спадающий фронт на GPIO_STM32G4
- Проблема с прерыванием PCF8574
- Использование millis() и micros() внутри процедуры прерывания
Быстрый гугл выдал мне
void ADC_IRQHandler(){ ... }
. Не уверен, что это правильно, так как я не знаком с STM32., @Gerben@Gerben Не сработало :(, @Beacon of Wierd