Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вопрос по I2C
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dimon_rub
Здравствуйте. Вопрос наверно стар но конкретного ответа так я и не нашел. КАКОЙ метод (прерывание или DMA)нужно использовать при работе с STM32F103 по шине I2C с несколькими устройствами. Примеры попадающиеся на просторах в основном проверка в цикле с тайм-аутом (как по мне не очень красиво). Устройства всегда слейв. При этом: одно память чтение/запись не постоянная, второе датчик опрос постоянный. Кроме этого используется АЦП(где тоже соответственно опрос постоянный, сдесь DMA), USART(DMA) и SPI Ethernet(планируется DMA).

СПАСИБО ЗА СОВЕТ!!!
haker_fox
QUOTE (dimon_rub @ Dec 15 2016, 20:21) *
Здравствуйте. Вопрос наверно стар но конкретного ответа так я и не нашел. КАКОЙ метод (прерывание или DMA)нужно использовать при работе с STM32F103 по шине I2C с несколькими устройствами. Примеры попадающиеся на просторах в основном проверка в цикле с тайм-аутом (как по мне не очень красиво). Устройства всегда слейв. При этом: одно память чтение/запись не постоянная, второе датчик опрос постоянный. Кроме этого используется АЦП(где тоже соответственно опрос постоянный, сдесь DMA), USART(DMA) и SPI Ethernet(планируется DMA).

СПАСИБО ЗА СОВЕТ!!!

Да по-бубену biggrin.gif Как вам удобно: поллинг, прерывания, ПДП. Можно даже программную шину сделать... НО! Таймауты должны быть, и полноценная обработка состояний шины (конечный автомат) дабы не повесить всю программу из-за отвалившихся часов. Я не использую ПДП, т.к. не гоняю через I2C большие потоки данных, но использую прерывания.
Obam
По бубну wink.gif
pitt
Цитата(dimon_rub @ Dec 15 2016, 07:21) *
Здравствуйте. Вопрос наверно стар но конкретного ответа так я и не нашел. КАКОЙ метод (прерывание или DMA)нужно использовать при работе с STM32F103 по шине I2C с несколькими устройствами. Примеры попадающиеся на просторах в основном проверка в цикле с тайм-аутом (как по мне не очень красиво). Устройства всегда слейв. При этом: одно память чтение/запись не постоянная, второе датчик опрос постоянный. Кроме этого используется АЦП(где тоже соответственно опрос постоянный, сдесь DMA), USART(DMA) и SPI Ethernet(планируется DMA).

СПАСИБО ЗА СОВЕТ!!!

В приводимых ST примерах есть несколько различных задержек. В большинстве случаев, более уместно использовать прерывания, но не всегда. Например, я использую поллинг для START и STOP clocks - число циклов задержки сопоставимо с затратами на вход и вычод из прерываний, а вот wo всеx остальных случаях, прерывания будут отнимать меньше MCU clocks.
В сети есть множество разнообразных примеров - изучайте их. ST код пригоден исключительно для понимания работы их железа, так как их документация просто отвратительна. Есть еще вариант выключения мосгов и использования Cube, но тогда надо знать правильные молитвы, чтобы все работало ВСЕГДА, но тут я помочь не в состоянии.
Успехов.
dimon_rub
Спасибо. Хотелось услышать людей непосредственно работающих этой штукой. Я то же попробую для начала прерывания (они как то ближе) у а потом ......
KnightIgor
Цитата(dimon_rub @ Dec 15 2016, 16:04) *
Спасибо. Хотелось услышать людей непосредственно работающих этой штукой. Я то же попробую для начала прерывания (они как то ближе) у а потом ......

Мда, сочуствую: начинать с I2C F103 по прерываниям. Это полная катастрофа...
arhiv6
KnightIgor, а почему катастрофа?
Сергей Борщ
QUOTE (arhiv6 @ Dec 16 2016, 08:07) *
KnightIgor, а почему катастрофа?
Присоединяюсь к вопросу. Я сразу начал и с прерываниями и с ПДП и под ОС. Все работет. Что я сделал неправильно?
dimon_rub
Цитата(KnightIgor @ Dec 15 2016, 20:11) *
Мда, сочуствую: начинать с I2C F103 по прерываниям. Это полная катастрофа...


А в чем интересно проблема. Поделитесь ПОЖАЛУЙСТА.
Pridnya
Цитата(KnightIgor @ Dec 15 2016, 23:11) *
Мда, сочуствую: начинать с I2C F103 по прерываниям. Это полная катастрофа...

Цитата(Сергей Борщ @ Dec 16 2016, 09:48) *
Присоединяюсь к вопросу. Я сразу начал и с прерываниями и с ПДП и под ОС. Все работет. Что я сделал неправильно?

Цитата(dimon_rub @ Dec 16 2016, 10:36) *
А в чем интересно проблема. Поделитесь ПОЖАЛУЙСТА.

Я вообще шину I2С использовал только на MCU PIC16 от Microchip, да и то программный вариант: выделяешь два вывода и работаешь. Медленная она, но полезная, когда нечасто нужно опрашивать несколько микросхем на шине I2C или в пределах печатной платы связать все узлы, поддерживающие I2C.

А вообще использую интерфейсы UART и SPI, они быстрые (несколько мегабит или несколько десятков мегабит в секунду), по ним можно передавать большие блоки данных, и здесь удобно пользоваться прерываниями на низких скоростях и DMA на больших.

Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать? Поясните в двух словах, если не сложно! rolleyes.gif
Сергей Борщ
QUOTE (Pridnya @ Dec 16 2016, 11:35) *
А вообще использую интерфейсы UART и SPI
А еще бывают внешние микросхемы, у которых I2C прибит гвоздями. К тому же и UART и SPI - интерфейс "точка-точка" и для опроса нескольких внешних микросхем придется городить огород. У меня на двух проводах I2C висят три заказных индикатора и 124 линии ввода-вывода (кнопки, светодиоды) через расширители, все это разбросано по плате размером с полтора листа A4.
QUOTE (Pridnya @ Dec 16 2016, 11:35) *
Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать?
Про принцип "пустил-забыл" слышали? Передача: дождался освобождения шины, запустил обмен, пошел делать другие дела. Прием: дождался освобождения шины, запустил обмен, жду сигнала от ОС о готовности данных (в это время процессор делает другие полезные дела вместо тупого опроса флагов I2C или тупого шевеления ногами "медленной шины I2C").
zltigo
Цитата(Pridnya @ Dec 16 2016, 11:35) *
Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать? Поясните в двух словах, если не сложно! rolleyes.gif

Вот именно потому, что она МЕДЛЕННАЯ и следует использовать прерывания, дабы не ждать ожидания транзакции. Причем все точно так же обстоит и с помянутыми Вами SPI и UART.
Kabdim
Цитата(Сергей Борщ @ Dec 16 2016, 14:15) *
... 124 линии ввода-вывода (кнопки, светодиоды) через расширители...

Если не секрет, можно вопрос? Кнопки циклично опрашиваются или какой-то доп сигнал "прерывание" используете? Какие расширители используете?
Pridnya
Цитата(Сергей Борщ @ Dec 16 2016, 14:15) *
А еще бывают внешние микросхемы, у которых I2C прибит гвоздями. К тому же и UART и SPI - интерфейс "точка-точка" и для опроса нескольких внешних микросхем придется городить огород. У меня на двух проводах I2C висят три заказных индикатора и 124 линии ввода-вывода (кнопки, светодиоды) через расширители, все это разбросано по плате размером с полтора листа A4.
Про принцип "пустил-забыл" слышали? Передача: дождался освобождения шины, запустил обмен, пошел делать другие дела. Прием: дождался освобождения шины, запустил обмен, жду сигнала от ОС о готовности данных (в это время процессор делает другие полезные дела вместо тупого опроса флагов I2C или тупого шевеления ногами "медленной шины I2C").

Спасибо! В случае SPI для нескольких микросхем потребуется дешифратор 3-8 для CS и три лини SI, SO, SCK. Получается, что можно и I2C использовать с прерываниями, но лучше еще и с RTOS, если я правильно понял. Про принцип, естественно, слышал, сам использую USART передатчик по прерываниям или через DMA.
Цитата(zltigo @ Dec 16 2016, 14:18) *
Вот именно потому, что она МЕДЛЕННАЯ и следует использовать прерывания, дабы не ждать ожидания транзакции. Причем все точно так же обстоит и с помянутыми Вами SPI и UART.

Спасибо!
Сергей Борщ
QUOTE (Kabdim @ Dec 16 2016, 14:05) *
Если не секрет, можно вопрос? Кнопки циклично опрашиваются или какой-то доп сигнал "прерывание" используете? Какие расширители используете?
Расширители PCA9555PW, 6 микросхем по 16 бит. Да, она имеет вывод прерывания с открытым стоком, выводы прерывания всех микросхем объединены, опрос по прерыванию.
jcxz
Цитата(Pridnya @ Dec 16 2016, 12:35) *
Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать? Поясните в двух словах, если не сложно! rolleyes.gif

Бывают и I2C мегабитные. Не ногодрыгательные канеш.

Цитата(Pridnya @ Dec 16 2016, 15:05) *
В случае SPI для нескольких микросхем потребуется дешифратор 3-8 для CS и три лини SI, SO, SCK.

Расширяйте свой кругозор:
Для SPI кроме схемы соединения "звезда" (когда каждому слэйву назначается свой CS), бывают ещё слэйвы, поддерживающие соединение "в цепочку" (каждый слэйв имеет MOSI-вход и MOSI-выход, с MISO - аналогично).
А ещё бывают слэйвы, которым можно задать задержку (в тактах от начала CS) начала данных и просто подать все сигналы MOSI/MISO/SCLK/CS на все слэйвы параллельно - все сигналы общие для всех слэйвов. В последнем случае уже получается похоже на I2C - задержку эту можно считать адресом отдельного слэйва.
zltigo
Цитата(jcxz @ Dec 17 2016, 13:42) *
Бывают и I2C мегабитные. Не ногодрыгательные канеш.

Да, Массово использую I2C FRAM с мегабитным интерфейсом.
KnightIgor
Цитата(Сергей Борщ @ Dec 16 2016, 08:48) *
Присоединяюсь к вопросу. Я сразу начал и с прерываниями и с ПДП и под ОС. Все работет. Что я сделал неправильно?

Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже.
Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор.
alexf
Бывают ситуации когда CPU нечего делать пока идет обмен по I2C и можно без прерываний. У меня в текущем проекте на шине несколько устройств, в то числе разветвитель, которому надо всего один байт в единственный регистр. Все работает, но я довольно криво написал отдельные функции для обмена 1 и 2 байта с адресом и без.
Есть где-нибуть пример универсальной функции с параметрами?
zltigo
Цитата(alexf @ Dec 17 2016, 22:48) *
Бывают ситуации когда CPU нечего делать пока идет обмен по I2C и можно без прерываний.

Если нечего делать, то пусть спит и не тратит энергию. Проснется по прерыванию sm.gif
dimon_rub
Цитата(KnightIgor @ Dec 17 2016, 16:47) *
Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже.
Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор.


А можно кусок кода или пример по обработке (что б не пройти по тем же граблям).
ОГРОМНОЕ СПАСИБО
KnightIgor
Цитата(dimon_rub @ Dec 20 2016, 08:52) *
А можно кусок кода или пример по обработке (что б не пройти по тем же граблям).
ОГРОМНОЕ СПАСИБО

Я приведу кусок - обработчик прерывания. Сразу скажу, что он работает в моей, назовем это так, - экосистеме. Это макросы, различные процедуры, не приведенные здесь. Обработчик - один для нескольких I2C периферий. Поэтому используются управляющие структуры данных. Смотрите не столько на инструкции, сколько на комментарии.
CODE
// -----------------------------------------------------------------------------
// EVENT INTERRUPT HANDLER
// -----------------------------------------------------------------------------
static void I2Cx_EV_IRQHandler(uint8_t port)
{
I2C_Control_Type *ctrl = &control[port];
I2C_TypeDef *i2c = ctrl->i2c;

switch (ctrl->evnt = I2C_Event(i2c, ctrl->readsr2)) {

// - - I2C Started - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

case I2C_EVENT_MASTER_MODE_SELECT_NO_SB: // MASTER, START sent: BUSY, MSL but SB are set

break; // ignore, wait for SB set

case I2C_EVENT_MASTER_MODE_SELECT: // MASTER, (RE)START sent: BUSY, MSL and SB are set

if (ctrl->wcnt > 0) { // PREPARE WRITING: send the slave Address
// with R/W bit ==0
I2C_SEND_ADDR(i2c, ctrl->ptr[0] & ~I2C_Direction_Receiver);

} else { // PREPARE READING:

// For N == 2 set POS bit to move
// NACK to the second byte.

if (ctrl->icnt == 2)
{
I2C_POS(i2c); // ACK is already set

} else {
#if (USE_I2C_RX_DMA1)

// if RX DMA enabled, allow below only for N == 1...

if (ctrl->icnt < 2)
#endif
// For pure interrupt mode RX and
// cases (N != 2) enable RxNE interrupt:
I2C_BUFIE_SET(i2c);
}
// Prevent reading of SR2 to avoid resetting of ADDR bit,
// if two or less bytes to read (cases N == 1 or N == 2).
// See RM0008.PDF, Doc ID 13902 Rev 14, Page 735.

if (ctrl->icnt <= 2)
ctrl->readsr2 = 0;

// Send I2C ID (slave Address to receive).
// Writing DR here preceeded by SR1 reading above clears SB
// with R/W bit ==1
I2C_SEND_ADDR(i2c, ctrl->ptr[0] | I2C_Direction_Receiver);
}
break;

// - - I2C Transmitting - - - - - - - - - - - - - - - - - - - - - - - - - - -

case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: // ADDR sent with /W bit

#if (USE_I2C_TX_DMA1)

// Transmit bytes via DMA

I2C_START_DMA_TX(ctrl);
#else
// WRITE the FIRST data byte:

I2C_WRITE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]); // .icnt-- and .wnt-- inside...
#endif

break;
//
// ATTENTION! - since 03.11.11. does not work without the simple
// case I2C_EVENT_MASTER_BYTE_TRANSMITTING below as if
// I2C_EVENT_MASTER_BYTE_TRANSMITTING occures sometimes
// before I2C_EVENT_MASTER_BYTE_TRANSMITTED.
// Possible reasons (due to the following changes):
// 1). Interrupt priority of I2C has been changed to the highest one;
// 2). The I2C speed has been reduced down to 100kHz from 400kHz,
// the driver was tested before.
//
case I2C_EVENT_MASTER_BYTE_TRANSMITTING: // Data being SENT; TRA, BSY, MSL and
{ // TxE but BTF are set.
uint8_t ex = 0;
uint32_t tp = i2c_SBTimeoutInit(port, 10 * BITS_ONE_BYTE); // Time of two I2C bytes to wait

while (!I2C_BTF(i2c) &&
!(ex = i2c_SBTimeoutExpired(&tp))); // Wait for BTF! It MUST arrive else
// it were a severe hardware error...
if (ex) // BTF still off: expired!
{
I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt);
break;
} // else CONTINUE:
}
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: // Data byte's been SENT; TRA, BSY, MSL and
// both TxE and BTF are set.
if (ctrl->icnt)
{
if (ctrl->wcnt == 0)

// RESTART after the last byte from [WRITE] transaction.
// See RM0008.PDF, Doc ID 13902 Rev 12, Page 733,
// Note to START and Page 734 to "Closing the
// communication"

I2C_START(i2c);

else
// just write the next byte
I2C_WRITE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]); // .icnt-- and .wnt-- inside...

} else {
// The last byte is completely pushed out, ACK from slave got.
// Bus is stretched (BTF is set), issue STOP.
I2C_ISSUE_STOP(i2c);
I2C_SUCCESS_HANDLER(ctrl);
}
break;

// TRAP: where is TRA bit?!
case I2C_EVENT_MASTER_BYTE_TRANSMITTED_BUT_TRA:

I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt);
break;

// - - I2C Receiving - - - - - - - - - - - - - - - - - - - - - - - - - - - -

// +++ case N == 1 (single byte) and N == 2 begin +++


// .icnt is == 1 here if READ ONLY operation started,
// or == 1 + wcnt if RESTART-AFTER-WRITE preceeded.

// +++ case N == 1 (single byte) and N == 2; I2C_readSR2 == 0
// See RM0008.PDF, Doc ID 13902 Rev 14, Page 735.

case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED_SR1: // ADDR sent, bit still set (I2C_readSR2 == 0)
{
I2C_PREPARE_CRITICAL_SECTION(sv);

// To avoid multiply data receiption...
I2C_BEGIN_CRITICAL_SECTION(sv);

// Clear ADDR bit by reading SR2 out (SR1's been read at "switch").
// This starts the receiption immediately.
ctrl->evnt |= I2C_GET_SR2(i2c) << 16;

// Prepare NACK (clear ACK); if POS is set it goes to the second (==last) byte.
// Don't worry about too late NACK setting: all IRQs are disabled!
I2C_NACK_IT(i2c);

if (ctrl->icnt == 1)
// Prepare/issue STOP after the SINGLE byte
I2C_ISSUE_STOP(i2c);

I2C_END_CRITICAL_SECTION(sv);

// Allow SR2 readout at "switch" again to get into RxNE interrupt.
// CONTINUE...
}
// This fucking case is neccessary for reading two bytes @48MHz CPU
// while I2C_readSR2 == 0 after the address has been sent.
// Occured when trying to read MCP4661 (2x Reostat) out.
//
// It seems that the interrupt is generated by ADDR = 1 while the bit
// has not appeared in SR1 yet! At the same time the SB bit is still
// seen in SR1. Madness!
//
case I2C_EVENT_MASTER_MODE_SELECT_SR1:

ctrl->readsr2 = 1; // Allow SR2 readout at "switch" again
break;

// --- case N == 1 (single byte) and N == 2 end ---

// +++ case N > 2:

case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: // ADDR sent, bit cleared

// 1. ADDR has already been cleared at "switch", thus
// 2. the receiption of the first byte must be in
// progress now;
#if (USE_I2C_RX_DMA1)

// Receive bytes via DMA
I2C_START_DMA_RX(ctrl);
#else
// 3. RxNE buffer interrupt is enabled.
// So do nothing here.
#endif

break;

// BTF is set:

case I2C_EVENT_MASTER_BYTE_RECEIVED_BTF:

switch (ctrl->icnt) {

case 2: // N == 2 (two bytes only)

// Here both DR and SHIFT are full with expected
// two bytes because RxNE interrupt has not been
// enabled yet. NACK has been issued to the last
// byte because NACK along with POS were prepared
// before.
// I2C bus is stretched (BTF set). Issue STOP.
// Read data TWICE (both from DR and SHIFT)!
// See Errata about disable IRQ for
// [STOP-read DATA(N-1)-read DATA(N)]

I2C_STOPN_2(ctrl); // surrounded by disabled IRQs...
ctrl->icnt = 0; // All data got.

I2C_SUCCESS_HANDLER(ctrl);
break;

case 3: // N == 3 bytes left to receive

// Here Data(N-2) in DR and Data(N-1) in SHIFT;
// The bus is stretched/pending (BTF is set).

// Prepare NACK for Data(N) and...
I2C_NACK_IT(i2c);

// ...read Data(N-2) out:
// this starts the receiption of the last byte
// with NACK at its end.
I2C_STORE(ctrl, ctrl->ptr[ctrl->indx++]);

// Prepare STOP and read Data(N-1) out:
// See Errata about disable IRQ for [STOP-read DATA(N-1)]
I2C_STOPN_1(ctrl); // surrounded by disabled IRQs
ctrl->icnt = 1;

// One byte left to read as soon as RxNE set
// Enable RxNE interrupt again to read it out.
I2C_BUFIE_SET(i2c);
break;

default:
// RxNE _AND_ BTF are set: store and check if complete.
// This occures also at enabled RxNE interrupt if
// there were no possibility to process RxNE below
// because of too long interrupts of higher priority.
// Store, check if complete:
I2C_STORE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]);
}
break;

case I2C_EVENT_MASTER_BYTE_RECEIVED: // RxNE is set

if (ctrl->icnt == 3) // 3 bytes left to receive:

// Here Data(N-2) in DR and the receiption of Data(N-1)
// must/can be in progress.

// See RM0008.PDF, Doc ID 13902 Rev 12, Page 737:
// DON'T READ the data byte, just disable RxNE interrupt and
// let be interrupted by BTF above (both DR and SHIFT are full)

I2C_BUFIE_CLEAR(i2c);

else // Store, check if complete:
I2C_STORE_NEXT(ctrl, ctrl->ptr[ctrl->indx++]);

break;
// --- case N > 2 end ---

default:
//
// 19.03.2014: At 24MHz an interrupt can occure while no status bits set yet!
// This case is not to consider as an error: exit the interrupt
// and let it shoot again with all bits set.
// It seems to occure when prepared to read only 2 bytes (when
// ctrl->readsr2 is 0).
//
if (ctrl->readsr2 && ctrl->evnt)
I2C_ERROR_HANDLER(port, ctrl->code = ctrl->evnt);
}
ctrl->guard = 1;
}
Aleksandr Baranov
Я бы еще вспомнил процедуру "I2C bus recovery", описанную, например, здесь:
http://www.cs.unc.edu/~stc/FAQs/Interfaces/I2C-AN10216_1.pdf
на странице 17.
Мне приходилось прибегать.
alexf
Если я раз в секунду читаю пару датчиков за 1 мсек, много энергии не с'экономить. Тем более питание от USB.

Но неожиданно оказалось что в HAL, который я не особо жаловал, есть именно то что надо: общая форма чтения/записи Н байт по адресу М.

HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)

HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)


Даже можно задать размер адреса: иногда 1 байт, иногда 2.
dimon_rub
Цитата(KnightIgor @ Dec 20 2016, 20:52) *
Я приведу кусок - обработчик прерывания. Сразу скажу, что он работает в моей, назовем это так, - экосистеме. Это макросы, различные процедуры, не приведенные здесь. Обработчик - один для нескольких I2C периферий. Поэтому используются управляющие структуры данных. Смотрите не столько на инструкции, сколько на комментарии.


СПАСИБО. БУДУ РАЗБИРАТЬСЯ
KnightIgor
Цитата(Aleksandr Baranov @ Dec 21 2016, 00:22) *
Я бы еще вспомнил процедуру "I2C bus recovery", описанную, например, здесь:
http://www.cs.unc.edu/~stc/FAQs/Interfaces/I2C-AN10216_1.pdf
на странице 17.
Мне приходилось прибегать.

О, это вообще отдельная тема! EEPROMы cтрадают такой херней, что затыкаются и держат SDA в нуле. Причем так строго, что иногда и безудержное дергание SCL не помогает. В одной ответственной схеме (охранное устройство) пришлось предусмотреть типа watchdog, который снимал питание с EEPROM, если SDA слишком долго висит в нуле (схему рисовать не буду; описательно - цепочка быстро заряжается высоким SDA, медленно разряжается низким, и, долетев до низа, выключает транзистор, который и обесточивает EEPROM).
jcxz
Просто "безудержное дёргание" и не должно помогать. Ведь есть такая вещь как "clock stretching". SCL надо дёргать с его учётом.
KnightIgor
Цитата(jcxz @ Dec 22 2016, 14:53) *
Просто "безудержное дёргание" и не должно помогать. Ведь есть такая вещь как "clock stretching". SCL надо дёргать с его учётом.

Это был оборот речи. Если периферийный I2C "застретчил" SCL и на том и застрял, то тут уже горю ничем не поможешь.
jcxz
Цитата(KnightIgor @ Dec 22 2016, 15:59) *
Это был оборот речи. Если периферийный I2C "застретчил" SCL и на том и застрял, то тут уже горю ничем не поможешь.

Я не о том. Я говорю, что если тупо подёргать ножкой: set "1", пауза, set "0", пауза, ...
То может оказаться, что для чипа памяти прошёл всего один клок, так как он всё это время держал SCL=0 выбирая данные из одной из своих ячеек.
После каждого SCL="1" ждать надо пока напряжение на линии в реале не станет "1".
zltigo
Цитата(KnightIgor @ Dec 22 2016, 14:14) *
О, это вообще отдельная тема! EEPROMы cтрадают такой херней, что затыкаются и держат SDA в нуле.

Это только для тех, кто не понимает, как работает автомат I2C в этом самом EEPROM и соответственно не понимают, как его вывести в исходное состояние.
А автомат там простой и тупой. Завесить его намертво нереально. Для выведения в исходное, правда, обычно приходится ручками диаграмму отрабатывать. От "безудержного-же дергания",
как и от любого мусора, можно только затыкание получить.


Aleksandr Baranov
В "AN10216-01 I2C Manual" не сказано: "безудержно дергать......". Там довольно определенная последовательность действий.
KnightIgor
Цитата(Aleksandr Baranov @ Dec 22 2016, 17:37) *
В "AN10216-01 I2C Manual" не сказано: "безудержно дергать......". Там довольно определенная последовательность действий.

Вот же к фразе прицепились... Я так ОБРАЗНО обозвал цитату из рекомендации "I2C bus recovery" по ссылочке, подчеркивая, что уже не сама I2C периферия процессора формирует сигналы, а это надо делать "вручную".

Цитата(zltigo @ Dec 22 2016, 16:51) *
Это только для тех, кто не понимает, как работает автомат I2C в этом самом EEPROM и соответственно не понимают, как его вывести в исходное состояние.
А автомат там простой и тупой. Завесить его намертво нереально.

Если автоматы EEPROM разных производителей есть плод Вашей разработки, то нам несказанно повезло иметь возможность наконец распросить Вас, как же там все на самом деле работает! До сих пор понимание глубинных процессов автомата было недоступно, приходилось судить лишь по поведению этого черного ящика по внешним проявлениям и набивать шишки. Я приготовился внимать!
zltigo
Цитата(KnightIgor @ Dec 22 2016, 18:32) *
Если автоматы EEPROM разных производителей есть плод Вашей разработки....

Такое простое дело сложно сделать зачем то по разному. Так что можете верить, или не верить, но они у всех одинаковы и одинаково отрабатывают процесс recovery.
jcxz
Цитата(zltigo @ Dec 22 2016, 20:22) *
Такое простое дело сложно сделать зачем то по разному. Так что можете верить, или не верить, но они у всех одинаковы и одинаково отрабатывают процесс recovery.

Да, должны вроде. Но вот тут у меня FM31T378 почему-то никак не хочет прислушаться к доводам zltigo разума sad.gif
В процессе отладки, после обрыва одной из сессий на полдороге, вдруг перестал отвечать ACK на свой адрес и больше никак не приходит в себя.
И пока даже не понятно, что и делать - даже сброс отключением питания не помогает... sad.gif((
Хотя вроде и не должны микросхемы дохнуть просто от обрыва I2C-транзакции на полдороги. Но уже кажется, что бывают исключения.... wacko.gif
zltigo
Цитата(jcxz @ Dec 23 2016, 00:44) *
Да, должны вроде. Но вот тут у меня FM31T378 почему-то никак не хочет прислушаться к доводам zltigo разума sad.gif
В процессе отладки, после обрыва одной из сессий на полдороге, вдруг перестал отвечать ACK на свой адрес и больше никак не приходит в себя.
И пока даже не понятно, что и делать - даже сброс отключением питания не помогает... sad.gif((
Хотя вроде и не должны микросхемы дохнуть просто от обрыва I2C-транзакции на полдороги. Но уже кажется, что бывают исключения.... wacko.gif

Я писал про логику автомата и выводе его в начальное состояние. То, что что то уже за автоматом I2C сдохло намертво, и совсем не обязательно, что от обмена (если однократный случай)это уже другое дело.
Я использую их-же FM24V10 в тяжелых условиях, посему мучал не только прерыванием транзакций и закорачиванием всего и вся в процессе, но и статикой. Завешивал таким образом многократно. И развешивал.
AVR
Мои 5: когда я работал с I2C на AVR то на коротком кабеле обмен работал без повисаний сколь угодно долго, на длинном же периодически, при скачках напряжения на самой схеме (не внешние помехи), датчик вешал шину и контроллер. Там я решил таймаутом и реинициализацией I2C и всё продолжало работать. Когда работал с Microblaze с его I2C-мастером и уже другим датчиком - тоже повисало и никакие реиниты уже не помогали. С тех пор я решил что шина I2C противная. Тем не менее, мои софтовые реализации (bit-bang) мастера протокола I2C работали без сбоя, равно как и I2C порты на всяких ARM-платах с ОС Linux (через драйвер производителя).
Всю тему не читал, но пробовал ли автор темы просто для эксперимента программно сделать I2C?
jcxz
Цитата(zltigo @ Dec 23 2016, 09:35) *
Я писал про логику автомата и выводе его в начальное состояние. То, что что то уже за автоматом I2C сдохло намертво, и совсем не обязательно, что от обмена (если однократный случай)это уже другое дело.
Я использую их-же FM24V10 в тяжелых условиях, посему мучал не только прерыванием транзакций и закорачиванием всего и вся в процессе, но и статикой. Завешивал таким образом многократно. И развешивал.

Это у Вас несколько иное, просто FRAM. А FM31T37x - это Companion-чип - там внутре два слэйва FRAM + RTC с разными адресами на одной шине. Перестали отвечать оба сразу.
Есть кое-какое подозрение что что-то защёлкнулось и запомнилось в каких-то внутренних регистрах возможно внутри есть какой-то кондёр раз это RTC. Пусть полежит неск. дней без питания - может разрядится и оживёт.
С просто FRAM мы тоже много лет работает (только по SPI - FM25) - не было проблем.
zltigo
Цитата(jcxz @ Dec 23 2016, 18:20) *
Это у Вас несколько иное, просто FRAM. А FM31T37x - это Companion-чип - там внутре два слэйва FRAM + RTC с разными адресами на одной шине. Перестали отвечать оба сразу.

Естественно,что я посмотрел что это перед ответом. Под "их-же" я имел виду того-же производителя а не такой-же чип. Представить, что в таком сдвоенном чипе могли что то налажать я в общем могу. Но вот выход из строя от неправильного цикла обращения, уже нет. По поводу - полежали и заработали - не помню уже за давностью лет подробности, но такое встречал с Flash. Три чипа 512 килобайтных были вставлены в панельки индустриальной PC наоборот и сдохли. Спустя некоторое время случайно были вставлены нормально и ожили. Поскольку такое в условиях сервисного центра случалось несколько раз, то эффект был стабильный и оживали они через месяц-другой.


Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.