Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 13:43:00

Решаю задачу с внешним АЦП Cirrus Logic CS5532 24-битное 3,8kSps/
У данного девайся, работающего по SPI, два режима преобразования: однократный и непрерывный режимы.
Что касается однократного, все просто: отправляю команду, жду определенное количество клоков и получаю данные (8+32 клока на SCLK), ну так она сделана.
А вот в непрерывном режиме, микросхема свою линии SDO притягивает к нулю, при готовности данных. А это именно линия MISO stm32 SPI/
И вот тут вопрос, как мне формировать прерывание при спадающем фронте на MISO, для чтения данных.
Можно ли как-то заставить GPIO работать с двумя функциями? На прием при чтении с шины SPI и вызывать прерывание при спаде фронта в пассивном режиме (когда SPI не работает)?

Сейчас мысль такая: объединить MISO на какой-нибудь GPIO и на этом GPIO настроить прерывание по спаду.
Вроде все должно работать, но мне не нравится, что и без того мало оставшихся ножек, дополнительное использование ножки GPIO.
И смущает, что когда войду в обработку прерывания и начну выполнение HAL_SPI_Read...... не войдет ли он в цикл бесконечного повторно вызвав прерывание это же? Или как-то можно запретить повторное маской, пока не знаю как практически реализовать.

Буду благодарен за любой совет.

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 14:32:25

Буду благодарен за любой совет.

Как насчет проверить все что ты тут понаписывал на практике?

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 15:45:45

Да, вот проверяю.

Есть уже засада. Почему-то не хочет работать конструкция: while(b_en_ext == 0)
Код:
   cmd_cs5532(cmd);
   b_en_ext = 0;

   while(b_en_ext == 0){
   __NOP();
   }

   uint8_t test = 0;
   read_byte(&test, 1); // Clear SDO
   read_byte(convert_result, 4); // Get data conversion
   b_en_ext = 0;

Что сделал: посадил CS ADC CS5532 на землю, она все равно одна у меня в проекте.
Освободилась ножка микроконтроллера, её задействовал как вход прерывания и объединил с MISO. Вызов прерывания по спаду фронта, ну общем, что и надо.
Далее в переменную b_en_ext = 0; помещаю ноль и отправляю команду на начало преобразования. Когда оно зокончено, SDO притягивает MISO к нуля и вызывается прерывание. Там простая обработка :
Код:
   if(b_en_ext == 0 ) b_en_ext = 1;

т.е. устанавливаю в 1;
ну и, по идее, должен выйти из цикла..... но ни тут то было...переменную вижу, она =1 а из цикла не выходит.

кто, что может сказать?
Последний раз редактировалось tuniks Пн фев 24, 2020 16:05:51, всего редактировалось 1 раз.

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:04:51

Код:
volatile bool b_en_ext;

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:15:28

Код:
volatile bool b_en_ext;


Спасибо, этот вариант теперь работает.

Но вот есть ли возможность как-то назначить две функции или получать прерывание прямо от MISO?

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:20:51

Но вот есть ли возможность как-то назначить две функции или получать прерывание прямо от MISO?

Если уже работает прерывание по спаду, то неужели тяжело проверить сработает ли оно если пин сконфигурирован как MISO?

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:33:23

Но вот есть ли возможность как-то назначить две функции или получать прерывание прямо от MISO?

Чем не подходит самоочевидное решение: При ожидании готовности АЦП-данных (ожидании спада на MISO) держать его в режиме GPIO + прерывание, а внутри ISR - переключить мультиплексор на SPI? По окончании приёма - переключить обратно на GPIO и прерывание.

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:37:16

[uquote="tuniks",url="/forum/viewtopic.php?p=3796336#p3796336"]....Чем не подходит самоочевидное решение: При ожидании готовности АЦП-данных (ожидании спада на MISO) держать его в режиме GPIO + прерывание, а внутри ISR - переключить мультиплексор на SPI? По окончании приёма - переключить обратно на GPIO и прерывание.


Понятно, придется на регистрах писать (ну и осваивать).

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 16:52:03

Чем не подходит самоочевидное решение: При ожидании готовности АЦП-данных (ожидании спада на MISO) держать его в режиме GPIO + прерывание

Если у него F1, то там для MISO даже режим будет обычный вход, т.к. SPI этот пин не контролирует, ему просто нужно значение считывать, точно так же как это делается через чтение IDR, т.е. весьма вероятно и для EXTI ничего менять не нужно. Если не F1, то режим для MISO будет уже другой, но вряд ли это на что-то повлияет.

Re: stm32 SPI получение прерывания от линии MISO

Пн фев 24, 2020 17:36:41

[uquote="jcxz",url="/forum/viewtopic.php?p=3796353#p3796353"]...Если у него F1, то там для MISO даже режим будет обычный вход, т.к. SPI этот пин не контролирует, ему просто нужно значение считывать, точно так же как это делается через чтение IDR, т.е. весьма вероятно и для EXTI ничего менять не нужно. Если не F1, то режим для MISO будет уже другой, но вряд ли это на что-то повлияет.


Сейчас для теста 070, в рабочем проекте будет 373.

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

Конечно спасибо всем за помощь и советы.

Добавлено after 33 minutes 25 seconds:
Ну, да. Просто читаю значение регистра IDR, и все удовольствие.
Тут же отрабатываю timeout, на случай зацикливания.

Ещё раз спасибо за урок.

Re: stm32 SPI получение прерывания от линии MISO

Вс мар 01, 2020 21:47:19

"Reflector", Если не F1, то режим для MISO будет уже другой, но вряд ли это на что-то повлияет.

Не скажу про F1, а вот про F0 обязательно нужно включать альтернативную функцию. Иначе работает, но очень нестабильно. Пробовал на F030. На анализаторе сигнал отличается от "считанного по MISO" - теряются биты данных.

Re: stm32 SPI получение прерывания от линии MISO

Вс мар 15, 2020 10:27:06

Для решения задачи ТС не надо никаких "прерываний по фронту". Раз АЦП работает в непрерывном режиме, значит время преобразования - известное и фиксированное. И не нужно ждать готовности, а просто запускать транзакцию чтения по SPI через фиксированное время после старта преобразования (с определённым запасом). И делать это периодически на связке таймер+DMA+SPI, запрограммировав таймер на период == периоду преобразования АЦП.

Re: stm32 SPI получение прерывания от линии MISO

Чт сен 03, 2020 09:14:39

Для решения задачи ТС не надо никаких "прерываний по фронту". Раз АЦП работает в непрерывном режиме, значит время преобразования - известное и фиксированное. И не нужно ждать готовности, а просто запускать транзакцию чтения по SPI через фиксированное время после старта преобразования (с определённым запасом). И делать это периодически на связке таймер+DMA+SPI, запрограммировав таймер на период == периоду преобразования АЦП.


Вернулся на форум с другой проблемой, но решил ответить и Вам.
У меня уже все давно реализовано и работает. А вот Ваша идея не подошла бы мне. Во-первых, в моем приборе пользователь может задавать до 10 различных скоростей преобразования АЦП. Для этого мне нужно было бы создавать таблицу соответствия скорости и интервала таймера. И устанавливать заведомо больший интервал. Это бы бы снизило фактическую скорость преобразования, а мне это нельзя. Во-вторых, первое преобразование, после старта, всегда больше времени занимает. Значит я должен был либо установить время на первое больше чем самый большой интервал таймера или для каждого преобразования свою вторую таблицу.

Там все просто, никто не мешал разрешить прерывание на ножке gpio (MISO) по спаду, и АЦП, при готовности данных опускала уровень в ноль и я забирал данные с микросхемы, ну и так дальше...

Re: stm32 SPI получение прерывания от линии MISO

Чт сен 03, 2020 10:54:07

Во-первых, в моем приборе пользователь может задавать до 10 различных скоростей преобразования АЦП. Для этого мне нужно было бы создавать таблицу соответствия скорости и интервала таймера.
Пускай таблица, разве это проблема?

И устанавливать заведомо больший интервал.
Во-первых: Если АЦП и МК тактируются от одного источника частоты, то "заведомо больший" - не нужно. Можно точный установить.
Во-вторых: Я не читал мануал на CS5532, но по опыту работы с другими (аналогичными) АЦП знаю, что такие АЦП как правило имеют буфер результата, в котором этот результат хранится. И этот буфер продолжает его хранить и после запуска следующего преобразоваия, до тех пор пока результат следующего преобразования не перепишет предыдущий результат. Так что - в непрерывном режиме нет никакой необходимости успевать считать результат быстро, можно считать его чуть позже, во время выполнения следущего преобразования. И тогда поблема с "заведомо большим интервалом" надумана.
И вообще - непрерывный режим он на то и непрерывный, чтобы следущее преобразование запускать сразу после завершения предыдущего. Если же у вас следущее преобразование запускается только после чтения предыдущего - это уже не непрерывный режим. Да и вообще - в таком случае у вас нет никакой фиксированной и стабильной частоты преобразований. Частота преобразований получится плавающей.

или для каждого преобразования свою вторую таблицу.
Ну и что? У Вас не хватает памяти на таблицу из 20 значений что-ли???? :dont_know:

Там все просто, никто не мешал разрешить прерывание на ножке gpio (MISO) по спаду, и АЦП, при готовности данных опускала уровень в ноль и я забирал данные с микросхемы, ну и так дальше...
Всё просто, только работаете Вы видимо поэтому без DMA, дёргаясь на каждое слово данных в прерывание. А с DMA можно было уменьшить загрузку CPU, обрабатывая данные АЦП пакетно. :beer:

Добавлено after 3 minutes:
Там все просто, никто не мешал разрешить прерывание на ножке gpio (MISO) по спаду, и АЦП, при готовности данных опускала уровень в ноль и я забирал данные с микросхемы, ну и так дальше...
И что - после забирания данных Вы вручную (каким-то сигналом или командой) запускаете новое преобразование АЦП? Или всё-таки оно само его запускает?

Re: stm32 SPI получение прерывания от линии MISO

Пт сен 04, 2020 17:19:05

....И что - после забирания данных Вы вручную (каким-то сигналом или командой) запускаете новое преобразование АЦП? Или всё-таки оно само его запускает?


Микросхема АЦП работает следующим образом: после установки всех параметров отправляется команда на непрерывное преобразование. Непрерывное на то и непрерывное, что не требует перезапуска. Разумеется есть буфер выходных данных у неё. После преобразования она опускает MISO в ноль. Нужно обратиться и прочитать 0х00 и за ним 4 байта результат преобразования, т.е. 5 байт. А она спокойно продолжает работать, ни какой команды отправлять не требуется (если только не остановка непрерывного преобразования). Поэтому "дергаюсь" не на каждое слово данных, а только на конечный результат окончания преобразования АЦП и читаю сразу все 5 байт. Можно и через DMA, но в скорости выигрыша не будет и контроллер и так почти ни чем кроме этого не занят.

Re: stm32 SPI получение прерывания от линии MISO

Вс сен 06, 2020 16:54:03

Микросхема АЦП работает следующим образом: после установки всех параметров отправляется команда на непрерывное преобразование. Непрерывное на то и непрерывное, что не требует перезапуска. Разумеется есть буфер выходных данных у неё. После преобразования она опускает MISO в ноль.
Значит - вполне можно опрашивать чип по таймеру. Первое чтение - через интервал немного больше периода следования данных, а последующие - с периодом равным периоду преобразования. И готовность можно не отслеживать, или отследить её только первый раз, для первого преобразования.
DMA даже если сейчас не нужно, потом может пригодиться для разгрузки CPU (или для экономии батарейки). А по таймерным прерываниям его проще использовать.
Ответить