2015-02-04 12 views
0

stm32f40x 칩과 통신하는 마스터의 의사 결정 방법을 찾은 사람이 있는지 궁금해하고 있었습니까? stm32f40x 칩의 펌웨어 측면에서 마스터가 보낸 ADDRess를 사용할 수 없으며 여기에 포함 된 r/w 비트 (주소의 비트 0)도 사용할 수 없습니다. 그렇다면 어떻게 충돌을 방지 할 수 있습니까? 다른 사람이이 문제를 다루었습니까? 그렇다면 어떤 기법을 사용 했습니까? 내 임시 해결책은 아래 참조 용입니다. TXE 인터럽트가 발생할 때까지 DR 데이터 레지스터에 대한 모든 쓰기가 지연되었습니다. 나는 처음에는 이것이 너무 늦을 것이라고 생각했고, 쓰레기 더미는 클럭 아웃 될 것이지만 작동하는 것으로 보인다.STM32F40x 칩의 I2C 주변 장치에서 펌웨어에 사용할 수있는 r/w 비트가 없음

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

나는 당신을 잡을 수 없다. 충돌과 무슨 뜻이야? 주소를 초기화하여 slave 및 programm로 작동하는 경우 i2c 모듈은 사전 프로그래밍 된 주소를 사용하여 모든 메시지를 필터링합니다. – LPs

답변

0

나는 당신을 이해하는 경우에 shure가 아니다. 더 많은 정보 또는 당신이하고 싶은 일에 대한 예를 제공해 주시겠습니까?

아마이을하는 데 도움이 : 내 경험이 많은 I2C 구현에 R/W 비트는 시대의 가장 있도록 설정하는 추가 기능이없는, 7 비트 주소와 함께 사용되는 또는 R/W 비트를 리셋하십시오.

따라서 128을 넘는 모든 주소는 슬레이브에서 데이터를 읽는 데 사용해야하며 127 이상의 모든 주소는 슬레이브에 데이터를 쓰는 데 사용해야합니다.

0

하드웨어가 LS 비트가 설정되어 있는지 또는 해제되어 있는지를 알더라도 주소를 수신하여 시작된 트랜잭션이 읽기인지 또는 쓰기인지를 결정할 방법이없는 것처럼 보입니다. 마스터의 의도는 일단 RXNE 또는 TXE 인터럽트/비트가 발생하면 알 수 있습니다.