2015-02-04 3 views
0

Мне было интересно, нашел ли кто-нибудь способ определить намерение мастера, связанного с чипом stm32f40x? С точки зрения прошивки на чипе stm32f40x ADDRess, посланная ведущим, недоступна, а также бит r/w (бит 0 адреса), содержащийся в нем, также недоступен. Итак, как я могу предотвратить столкновения? Кто-нибудь еще занимался этим? Если да, то какие методы вы использовали? Мое предварительное решение ниже для справки. Я задерживал любые записи в регистр данных DR до тех пор, пока не произойдет прерывание TXE. Сначала я подумал, что будет слишком поздно, и байт мусора будет выведен из строя, но, похоже, он работает.Нет встроенного микропрограммного обеспечения периферийным устройством I2C чипов STM32F40x

static inline void LLEVInterrupt(uint16_t irqSrc) 
{ 
    uint8_t i; 
    volatile uint16_t status; 
    I2CCBStruct* buffers; 
    I2C_TypeDef* addrBase; 

    // see which IRQ occurred, process accordingly... 
    switch (irqSrc) 
    { 
     case I2C_BUS_CHAN_1: 
      addrBase = this.addrBase1; 
      buffers = &this.buffsBus1; 
      break; 
     case I2C_BUS_CHAN_2: 
      addrBase = this.addrBase2; 
      buffers = &this.buffsBus2; 
      break; 
     case I2C_BUS_CHAN_3: 
      addrBase = this.addrBase3; 
      buffers = &this.buffsBus3; 
      break; 
     default: 
      while(1); 
    } 

    // ...START condition & address match detected 
    if (I2C_GetITStatus(addrBase, I2C_IT_ADDR) == SET) 
    { 
     // I2C_IT_ADDR: Cleared by software reading SR1 register followed reading SR2, or by hardware 
     // when PE=0. 
     // Note: Reading I2C_SR2 after reading I2C_SR1 clears the ADDR flag, even if the ADDR flag was 
     // set after reading I2C_SR1. Consequently, I2C_SR2 must be read only when ADDR is found 
     // set in I2C_SR1 or when the STOPF bit is cleared. 
     status = addrBase->SR1; 
     status = addrBase->SR2; 

     // Reset the index and receive count 
     buffers->txIndex = 0; 
     buffers->rxCount = 0; 

     // setup to ACK any Rx'd bytes 
     I2C_AcknowledgeConfig(addrBase, ENABLE); 
     return; 
    } 

    // Slave receiver mode 
    if (I2C_GetITStatus(addrBase, I2C_IT_RXNE) == SET) 
    { 
     // I2C_IT_RXNE: Cleared by software reading or writing the DR register 
     // or by hardware when PE=0. 

     // copy the received byte to the Rx buffer 
     buffers->rxBuf[buffers->rxCount] = (uint8_t)I2C_ReadRegister(addrBase, I2C_Register_DR); 
     if (RX_BUFFER_SIZE > buffers->rxCount) 
     { 
      buffers->rxCount++; 
     } 
     return; 
    } 

    // Slave transmitter mode 
    if (I2C_GetITStatus(addrBase, I2C_IT_TXE) == SET) 
    { 
     // I2C_IT_TXE: Cleared by software writing to the DR register or 
     // by hardware after a start or a stop condition or when PE=0. 

     // send any remaining bytes 
     I2C_SendData(addrBase, buffers->txBuf[buffers->txIndex]); 
     if (buffers->txIndex < buffers->txCount) 
     { 
      buffers->txIndex++; 
     } 
     return; 
    } 

    // ...STOP condition detected 
    if (I2C_GetITStatus(addrBase, I2C_IT_STOPF) == SET) 
    { 
     // STOPF (STOP detection) is cleared by software sequence: a read operation 
     // to I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to 
     // I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral). 
     // From the reference manual RM0368: 
     // Figure 163. Transfer sequence diagram for slave receiver 
     // if (STOPF == 1) {READ SR1; WRITE CR1} 
     // clear the IRQ status 
     status = addrBase->SR1; 
     // Write to CR1 
     I2C_Cmd(addrBase, ENABLE); 

     // read cycle (reset the status? 
     if (buffers->txCount > 0) 
     { 
      buffers->txCount = 0; 
      buffers->txIndex = 0; 
     } 

     // write cycle begun? 
     if (buffers->rxCount > 0) 
     { 
      // pass the I2C data to the enabled protocol handler 
      for (i = 0; i < buffers->rxCount; i++) 
      { 
       #if (COMM_PROTOCOL == COMM_PROTOCOL_DEBUG) 
       status = ProtProcRxData(buffers->rxBuf[i]); 
       #elif (COMM_PROTOCOL == COMM_PROTOCOL_PTEK) 
       status = PTEKProcRxData(buffers->rxBuf[i]); 
       #else 
       #error ** Invalid Host Protocol Selected ** 
       #endif 
       if (status != ST_OK) 
       { 
        LogErr(ST_COMM_FAIL, __LINE__); 
       } 
      } 
      buffers->rxCount = 0; 
     } 
     return; 
    } 

    if (I2C_GetITStatus(addrBase, I2C_IT_AF) == SET) 
    { 
     // The NAck received from the host on the last byte of a transmit 
     // is shown as an acknowledge failure and must be cleared by 
     // writing 0 to the AF bit in SR1. 
     // This is not a real error but just how the i2c slave transmission process works. 
     // The hardware has no way to know how many bytes are to be transmitted, so the 
     // NAck is assumed to be a failed byte transmission. 
     // EV3-2: AF=1; AF is cleared by writing ‘0’ in AF bit of SR1 register. 
     I2C_ClearITPendingBit(addrBase, I2C_IT_AF); 
     return; 
    } 

    if (I2C_GetITStatus(addrBase, I2C_IT_BERR) == SET) 
    { 
     // There are extremely infrequent bus errors when testing with I2C Stick. 
     // Safer to have this check and clear than to risk an 
     // infinite loop of interrupts 
     // Set by hardware when the interface detects an SDA rising or falling 
     // edge while SCL is high, occurring in a non-valid position during a 
     // byte transfer. 
     // Cleared by software writing 0, or by hardware when PE=0. 
     I2C_ClearITPendingBit(addrBase, I2C_IT_BERR); 
     LogErr(ST_COMM_FAIL, __LINE__); 
     return; 
    } 

    if (I2C_GetITStatus(addrBase, I2C_IT_OVR) == SET) 
    { 
     // Check for other errors conditions that must be cleared. 
     I2C_ClearITPendingBit(addrBase, I2C_IT_OVR); 
     LogErr(ST_COMM_FAIL, __LINE__); 
     return; 
    } 

    if (I2C_GetITStatus(addrBase, I2C_IT_TIMEOUT) == SET) 
    { 
     // Check for other errors conditions that must be cleared. 
     I2C_ClearITPendingBit(addrBase, I2C_IT_TIMEOUT); 
     LogErr(ST_COMM_FAIL, __LINE__); 
     return; 
    } 

    // a spurious IRQ occurred; log it 
    LogErr(ST_INV_STATE, __LINE__); 
} 
+1

Я не понимаю вас. Что вы имеете в виду при столкновении? Если вы выполняете роль подчиненного устройства и программы, инициировав свой адрес, модуль i2c фильтрует все сообщения для вас, используя запрограммированный адрес. – LPs

ответ

0

Я не уверен, если я вас понимаю. Можете ли вы предоставить дополнительную информацию или пример о том, что вы хотели бы сделать.

Может быть, это помогает: Мой опыт, что во многих реализациях I2C R/W-Bit используется вместе с 7-битовым адресом, поэтому в большинстве случаев, не существует каких-либо дополнительных функций для установки или сбросить R/W-бит.

Таким образом, для чтения данных с ведомых должны использоваться все адреса за пределами 128, и все адреса более 127 должны использоваться для записи данных на ведомые устройства.

0

Кажется, что нет способа определить, является ли транзакция, инициированная при получении адреса, чтением или записью, даже если аппаратное обеспечение знает, установлен ли LSbit или очищен. Намерение мастера будет известно только после того, как произойдет прерывание/бит RXNE или TXE.

Смежные вопросы