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

Как выдержать интервал между пакетами на шине i2c

Вс фев 11, 2018 15:48:58

Задача такая. Микроконтроллер STM32F1. На шине i2c две микросхемы датчиков, нужно опрашивать их 16 раз в секунду в фоне, не мешая основной задаче.
Для этого реализовал работу с i2c целиком через прерывания и DMA. На вход подаётся набор опкодов, которые управляют последовательностью действий на шине I2C (START, записать 7-битный адрес, читать N байт и так далее, в конце опкод STOP который на шине выставляет состояние STOP).

В конце последовательности должна вызываться указанная мной подпрограмма чтобы решить что дальше делатть.

Далее написал подпрограммы для работы с датчиками. На один датчик просто идёт последовательность чтения/записи регистров, в конце STOP. На второй датчик обмен идёт в два этапа, сначала читаем один регистр, потом STOP, анализируем что получили и в зависимости от этого генерируем новую последовательность опкодов, которую снова запускаем на выполнение.

И так 16 раз в секунду.

По отдельности каждая подпрограмма работает нормально. Проблемы начинаются когда начинаешь их вызывать сразу друг после друга.
Иногда это работает, иногда нет. Причина в том, что последнее прерывание (по которому выполняется опкод STOP и, соответственно, вызов моей подпрограммы) вызывается ДО того, как на шине выставилось состояние STOP. И если я прямо во время этого прерывания "заряжаю" автомат на выполнение следующей последовательности, то периферийный контроллер I2C сбивается с ритма и часто подвисает. То есть, в идеале, после выставления бита STOP в регистре CR1 нужно прождать какое-то время, пока этот STOP реально выполнится, и только после этого начинать следующий обмен по шине.

К сожалению, даташит меня огорчает.
1.jpg
(137.33 KiB) Скачиваний: 286

Как видно, событие (прерывание) EV8_2 вызывается до выставления STOP, а после сигнала STOP никаких событий уже не возникает.

А мне бы хотелось выставить STOP, подождать какое-то время, затем начать следующий цикл обмена. Но такой аппаратной возможности, без тупого ожидания в цикле, я не нашёл. Можно припахать для этого один из таймеров, но хочется обойтись только I2C (библиотека работы с I2C общего плана, не заточенная под конкретный проект).

Кто-нибудь встречался с такой ситуацией?

Re: Как выдержать интервал между пакетами на шине i2c

Пн фев 12, 2018 04:50:23

А мне бы хотелось выставить STOP, подождать какое-то время, затем начать следующий цикл обмена. Но такой аппаратной возможности, без тупого ожидания в цикле, я не нашёл.

Создать отдельную задачу ОС для опроса по I2C. После STOP задачу ставить на паузу на несколько тиков системного таймера, после чего опрашивать следующее устройство.

Re: Как выдержать интервал между пакетами на шине i2c

Ср фев 14, 2018 21:19:56

Ну это по сути то же самое, что задействовать ещё один таймер.
В общем, победил я её. Оказывается, между обращениями к разным чипам вовсе не обязательно выставлять на шину сигнал STOP. Достаточно подать повторный START, потом адрес второго чипа и всё отлично работает. Поэтому теперь все запросы к разным чипам идут одной пачкой, между запросами лишь повторный START. Так что на длительность STOP мне теперь уже плевать, он подаётся один в конце.
Ответить