Цитата(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;
}