|
Вопрос по I2C |
|
|
|
Dec 15 2016, 12:21
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

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

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (dimon_rub @ Dec 15 2016, 20:21)  Здравствуйте. Вопрос наверно стар но конкретного ответа так я и не нашел. КАКОЙ метод (прерывание или DMA)нужно использовать при работе с STM32F103 по шине I2C с несколькими устройствами. Примеры попадающиеся на просторах в основном проверка в цикле с тайм-аутом (как по мне не очень красиво). Устройства всегда слейв. При этом: одно память чтение/запись не постоянная, второе датчик опрос постоянный. Кроме этого используется АЦП(где тоже соответственно опрос постоянный, сдесь DMA), USART(DMA) и SPI Ethernet(планируется DMA).
СПАСИБО ЗА СОВЕТ!!! Да по-бубену  Как вам удобно: поллинг, прерывания, ПДП. Можно даже программную шину сделать... НО! Таймауты должны быть, и полноценная обработка состояний шины (конечный автомат) дабы не повесить всю программу из-за отвалившихся часов. Я не использую ПДП, т.к. не гоняю через I2C большие потоки данных, но использую прерывания.
--------------------
Выбор.
|
|
|
|
|
Dec 15 2016, 13:25
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(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, но тогда надо знать правильные молитвы, чтобы все работало ВСЕГДА, но тут я помочь не в состоянии. Успехов.
--------------------
|
|
|
|
|
Dec 15 2016, 14:04
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Спасибо. Хотелось услышать людей непосредственно работающих этой штукой. Я то же попробую для начала прерывания (они как то ближе) у а потом ......
|
|
|
|
|
Dec 16 2016, 07:36
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(KnightIgor @ Dec 15 2016, 20:11)  Мда, сочуствую: начинать с I2C F103 по прерываниям. Это полная катастрофа... А в чем интересно проблема. Поделитесь ПОЖАЛУЙСТА.
|
|
|
|
|
Dec 16 2016, 09:35
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 11-01-11
Из: Орел
Пользователь №: 62 159

|
Цитата(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 использовать? Поясните в двух словах, если не сложно!
|
|
|
|
|
Dec 16 2016, 11:15
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
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").
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 16 2016, 11:18
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Pridnya @ Dec 16 2016, 11:35)  Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать? Поясните в двух словах, если не сложно!  Вот именно потому, что она МЕДЛЕННАЯ и следует использовать прерывания, дабы не ждать ожидания транзакции. Причем все точно так же обстоит и с помянутыми Вами SPI и UART.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 16 2016, 12:05
|
Частый гость
 
Группа: Свой
Сообщений: 142
Регистрация: 11-01-11
Из: Орел
Пользователь №: 62 159

|
Цитата(Сергей Борщ @ 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. Спасибо!
|
|
|
|
|
Dec 17 2016, 11:42
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Pridnya @ Dec 16 2016, 12:35)  Но вот совсем не пойму, а какой смысл использовать на медленной шине I2C прием и передачу по прерываниям, и еще DMA для I2C использовать? Поясните в двух словах, если не сложно!  Бывают и 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 - задержку эту можно считать адресом отдельного слэйва.
|
|
|
|
|
Dec 17 2016, 16:47
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Сергей Борщ @ Dec 16 2016, 08:48)  Присоединяюсь к вопросу. Я сразу начал и с прерываниями и с ПДП и под ОС. Все работет. Что я сделал неправильно? Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже. Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор.
Сообщение отредактировал KnightIgor - Dec 17 2016, 16:50
|
|
|
|
|
Dec 20 2016, 06:52
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(KnightIgor @ Dec 17 2016, 16:47)  Вы, в итоге, наверняка сделали все правильно. Речь о том, что именно у F1xx I2C очень кривой. Об этом было много тем здесь, еще до появления других Fxxx, просто многие подзабыли. Достаточно напомнить, что при работе с I2C по прерываниям необходимо заботится о том, чтобы это прерывание не было прервано (самый высокий приоритет для I2C, либо вообще запреты прерываний на определенных этапах обработки I2C). Более того, на малых скоростях тактирования ядра (например, с целью энергосбережения) наблюдались комбинации флагов прерывания, которые никак не упоминались в документации, и для которых не было даже определений в STL. Это вводило в ступор обработчик. Поскольку большинство заводит камни сразу на максимуме, на такой косяк натыкались не многие, похоже. Мне понадобилась пара недель, с последующими доработками при работе с различной I2C периферией, чтобы запустить F103 стабильно. Когда появились F0xx, где I2C переработан, мне хватило и пары часов, чтобы запустить I2C так, что работает до сих пор. А можно кусок кода или пример по обработке (что б не пройти по тем же граблям). ОГРОМНОЕ СПАСИБО
|
|
|
|
|
Dec 20 2016, 20:52
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(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; }
Сообщение отредактировал KnightIgor - Dec 20 2016, 21:17
|
|
|
|
|
Dec 20 2016, 22:22
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
Я бы еще вспомнил процедуру "I2C bus recovery", описанную, например, здесь: http://www.cs.unc.edu/~stc/FAQs/Interfaces/I2C-AN10216_1.pdfна странице 17. Мне приходилось прибегать.
--------------------
ASB
|
|
|
|
|
Dec 21 2016, 00:37
|
Местный
  
Группа: Свой
Сообщений: 420
Регистрация: 22-12-04
Пользователь №: 1 608

|
Если я раз в секунду читаю пару датчиков за 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.
|
|
|
|
|
Dec 21 2016, 08:26
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 10-09-16
Пользователь №: 93 282

|
Цитата(KnightIgor @ Dec 20 2016, 20:52)  Я приведу кусок - обработчик прерывания. Сразу скажу, что он работает в моей, назовем это так, - экосистеме. Это макросы, различные процедуры, не приведенные здесь. Обработчик - один для нескольких I2C периферий. Поэтому используются управляющие структуры данных. Смотрите не столько на инструкции, сколько на комментарии. СПАСИБО. БУДУ РАЗБИРАТЬСЯ
|
|
|
|
|
Dec 22 2016, 12:14
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(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).
|
|
|
|
|
Dec 22 2016, 13:05
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(KnightIgor @ Dec 22 2016, 15:59)  Это был оборот речи. Если периферийный I2C "застретчил" SCL и на том и застрял, то тут уже горю ничем не поможешь. Я не о том. Я говорю, что если тупо подёргать ножкой: set "1", пауза, set "0", пауза, ... То может оказаться, что для чипа памяти прошёл всего один клок, так как он всё это время держал SCL=0 выбирая данные из одной из своих ячеек. После каждого SCL="1" ждать надо пока напряжение на линии в реале не станет "1".
|
|
|
|
|
Dec 22 2016, 14:51
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(KnightIgor @ Dec 22 2016, 14:14)  О, это вообще отдельная тема! EEPROMы cтрадают такой херней, что затыкаются и держат SDA в нуле. Это только для тех, кто не понимает, как работает автомат I2C в этом самом EEPROM и соответственно не понимают, как его вывести в исходное состояние. А автомат там простой и тупой. Завесить его намертво нереально. Для выведения в исходное, правда, обычно приходится ручками диаграмму отрабатывать. От "безудержного-же дергания", как и от любого мусора, можно только затыкание получить.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 22 2016, 15:37
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
В "AN10216-01 I2C Manual" не сказано: "безудержно дергать......". Там довольно определенная последовательность действий.
--------------------
ASB
|
|
|
|
|
Dec 22 2016, 16:32
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Aleksandr Baranov @ Dec 22 2016, 17:37)  В "AN10216-01 I2C Manual" не сказано: "безудержно дергать......". Там довольно определенная последовательность действий. Вот же к фразе прицепились... Я так ОБРАЗНО обозвал цитату из рекомендации "I2C bus recovery" по ссылочке, подчеркивая, что уже не сама I2C периферия процессора формирует сигналы, а это надо делать "вручную". Цитата(zltigo @ Dec 22 2016, 16:51)  Это только для тех, кто не понимает, как работает автомат I2C в этом самом EEPROM и соответственно не понимают, как его вывести в исходное состояние. А автомат там простой и тупой. Завесить его намертво нереально. Если автоматы EEPROM разных производителей есть плод Вашей разработки, то нам несказанно повезло иметь возможность наконец распросить Вас, как же там все на самом деле работает! До сих пор понимание глубинных процессов автомата было недоступно, приходилось судить лишь по поведению этого черного ящика по внешним проявлениям и набивать шишки. Я приготовился внимать!
|
|
|
|
|
Dec 22 2016, 22:44
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(zltigo @ Dec 22 2016, 20:22)  Такое простое дело сложно сделать зачем то по разному. Так что можете верить, или не верить, но они у всех одинаковы и одинаково отрабатывают процесс recovery. Да, должны вроде. Но вот тут у меня FM31T378 почему-то никак не хочет прислушаться к доводам zltigo разума  В процессе отладки, после обрыва одной из сессий на полдороге, вдруг перестал отвечать ACK на свой адрес и больше никак не приходит в себя. И пока даже не понятно, что и делать - даже сброс отключением питания не помогает...  (( Хотя вроде и не должны микросхемы дохнуть просто от обрыва I2C-транзакции на полдороги. Но уже кажется, что бывают исключения....
|
|
|
|
|
Dec 23 2016, 06:35
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(jcxz @ Dec 23 2016, 00:44)  Да, должны вроде. Но вот тут у меня FM31T378 почему-то никак не хочет прислушаться к доводам zltigo разума  В процессе отладки, после обрыва одной из сессий на полдороге, вдруг перестал отвечать ACK на свой адрес и больше никак не приходит в себя. И пока даже не понятно, что и делать - даже сброс отключением питания не помогает...  (( Хотя вроде и не должны микросхемы дохнуть просто от обрыва I2C-транзакции на полдороги. Но уже кажется, что бывают исключения....  Я писал про логику автомата и выводе его в начальное состояние. То, что что то уже за автоматом I2C сдохло намертво, и совсем не обязательно, что от обмена (если однократный случай)это уже другое дело. Я использую их-же FM24V10 в тяжелых условиях, посему мучал не только прерыванием транзакций и закорачиванием всего и вся в процессе, но и статикой. Завешивал таким образом многократно. И развешивал.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 24 2016, 07:09
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(jcxz @ Dec 23 2016, 18:20)  Это у Вас несколько иное, просто FRAM. А FM31T37x - это Companion-чип - там внутре два слэйва FRAM + RTC с разными адресами на одной шине. Перестали отвечать оба сразу. Естественно,что я посмотрел что это перед ответом. Под "их-же" я имел виду того-же производителя а не такой-же чип. Представить, что в таком сдвоенном чипе могли что то налажать я в общем могу. Но вот выход из строя от неправильного цикла обращения, уже нет. По поводу - полежали и заработали - не помню уже за давностью лет подробности, но такое встречал с Flash. Три чипа 512 килобайтных были вставлены в панельки индустриальной PC наоборот и сдохли. Спустя некоторое время случайно были вставлены нормально и ожили. Поскольку такое в условиях сервисного центра случалось несколько раз, то эффект был стабильный и оживали они через месяц-другой.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|