This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR2433:I2C 通信错误

Guru**** 2540720 points
Other Parts Discussed in Thread: MSP430FR2433

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1048867/msp430fr2433-i2c-communication-error

器件型号:MSP430FR2433

您好2E2、

我使用的是 MSP430FR2433、我想通过 I2C 与 PN532板通信。 我的目标是将以下数组(version_buff[9]={0X00,0X00,0XFF,0X0XFF,0XD4,0X02,0XD5,0X00,})发送到 PN532,然后将其响应保存在一个变量中。 我正在使用一个示例代码、但是当我发送 UCB0TXBUF = TransmitRegAddr (我不知道原因)时、它应该读取一些内容并在中断中再次输入。 第二次我不进入中断并且我卡在__ bis_SR_register 行(LPM0_bits + GIE)中。

如果有人可以帮助我解决错误、或者通过其他方式发送我之前提到的数组、然后读取响应。

谢谢你。

#include "nfc.h"
#include "msp430.h"


typedef enum I2C_ModeEnum{
    IDLE_MODE,
    NACK_MODE,
    TX_REG_ADDRESS_MODE,
    RX_REG_ADDRESS_MODE,
    TX_DATA_MODE,
    RX_DATA_MODE,
    SWITCH_TO_RX_MODE,
    SWITHC_TO_TX_MODE,
    TIMEOUT_MODE
} I2C_Mode;

/*constantes de NFC*/
unsigned char TransmitBuffer[9] = {0};
unsigned char TXByteCtr = 0;
unsigned char ReceiveIndex = 0;
unsigned char ReceiveBuffer[50];
unsigned char RXByteCtr = 0;
unsigned char TransmitIndex = 0;
unsigned char imagen[150];

I2C_Mode MasterMode = IDLE_MODE;
unsigned char TransmitRegAddr = 0;

unsigned char nfc_buf[NFC_CMD_BUF_LEN];
static const unsigned char version_buff[9] = {0X00,0X00,0XFF,0X01,0XFF,0XD4,0X02,0XD5,0X00,};
unsigned char checksum;

I2C_Mode I2C_Master_WriteReg(unsigned char dev_addr, unsigned char reg_addr, const unsigned char *reg_data, unsigned char count);
I2C_Mode I2C_Master_ReadReg(unsigned char dev_addr, unsigned char reg_addr, unsigned char count);
void CopyArray(const unsigned char *source, unsigned char *dest, unsigned char count);
void Configuracion_I2C(void);


unsigned int get_version(void);

int main()
{
   WDTCTL = WDTPW | WDTHOLD;

   Configuracion_I2C();

   PM5CTL0 &= ~LOCKLPM5;

   __enable_interrupt();

       while(1)
        {
           get_version();

           unsigned int versiondata = get_version();  //guardar version en versiondata
                 if (! versiondata) {          //Si devuelve 0 es que no ha detectado
                         while (1);
                           }
                   while(1);

        }
}



void Configuracion_I2C(void)
{
    UCB0CTLW0 = UCSWRST;                                        // Enable SW reset
       UCB0CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
       UCB0BRW = 160;                                          // fSCL = SMCLK/160 = ~100kHz
       UCB0I2CSA = PN532_I2C_ADDRESS;                          // Slave Address
       UCB0CTLW0 &= ~UCSWRST;                                  // Clear SW reset, resume operation
       UCB0IE |= UCNACKIE;

       P1SEL1 &= ~BIT3;
       P1SEL0 |= BIT3;

       P1SEL1 &= ~BIT2;
       P1SEL0 |= BIT2;
}


I2C_Mode I2C_Master_ReadReg(unsigned char dev_addr, unsigned char reg_addr, unsigned char count)
{
    /* Initialize state machine */
    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;
    RXByteCtr = count;
    TXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
    UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB0IE |= UCTXIE;                        // Enable TX interrupt

    UCB0CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
   __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts*/

    return MasterMode;

}


I2C_Mode I2C_Master_WriteReg(unsigned char dev_addr, unsigned char reg_addr, const unsigned char *reg_data, unsigned char count)
{

    /* Initialize state machine */
    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;

    //Copy register data to TransmitBuffer
    CopyArray(reg_data, TransmitBuffer, count);

    TXByteCtr = count;
    RXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB0I2CSA = dev_addr;
    UCB0IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
    UCB0IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB0IE |= UCTXIE;                        // Enable TX interrupt

    UCB0CTLW0 |= UCTR;
    UCB0CTLW0 |= UCTXSTT;                   // I2C TX, start condition
    __bis_SR_register(LPM0_bits + GIE);              // Enter LPM0 w/ interrupts

    return MasterMode;
}

void CopyArray(const unsigned char *source, unsigned char *dest, unsigned char count)
{
    unsigned char copyIndex = 0;
    for (copyIndex = 0; copyIndex < count; copyIndex++)
    {
        *dest = *source;
        source++;
        dest++;
    }
}



#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //Must read from UCB0RXBUF
  unsigned char rx_val = 0;
  switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE:          break;         // Vector 0: No interrupts
    case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
      break;
    case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
    case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
    case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
    case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
    case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
    case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
    case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0
        rx_val = UCB0RXBUF;
        if (RXByteCtr)
        {
          ReceiveBuffer[ReceiveIndex++] = rx_val;
          RXByteCtr--;
        }

        if (RXByteCtr == 1)
        {
          UCB0CTLW0 |= UCTXSTP;
        }
        else if (RXByteCtr == 0)
        {
          UCB0IE &= ~UCRXIE;
          MasterMode = IDLE_MODE;
          __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
        }
        break;
    case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
        switch (MasterMode)
        {
          case TX_REG_ADDRESS_MODE:
              UCB0TXBUF = TransmitRegAddr;
              if (RXByteCtr)
                  MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
              else
                  MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
              break;

          case SWITCH_TO_RX_MODE:
              UCB0IE |= UCRXIE;              // Enable RX interrupt
              UCB0IE &= ~UCTXIE;             // Disable TX interrupt
              UCB0CTLW0 &= ~UCTR;            // Switch to receiver
              MasterMode = RX_DATA_MODE;    // State state is to receive data
              UCB0CTLW0 |= UCTXSTT;          // Send repeated start
              if (RXByteCtr == 1)
              {
                  //Must send stop since this is the N-1 byte
                  while((UCB0CTLW0 & UCTXSTT));
                  UCB0CTLW0 |= UCTXSTP;      // Send stop condition
              }
              break;

          case TX_DATA_MODE:
              if (TXByteCtr)
              {
                  UCB0TXBUF = TransmitBuffer[TransmitIndex++];
                  TXByteCtr--;
              }
              else
              {
                  //Done with transmission
                  UCB0CTLW0 |= UCTXSTP;     // Send stop condition
                  MasterMode = IDLE_MODE;
                  UCB0IE &= ~UCTXIE;                       // disable TX interrupt
                  __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
              }
              break;

          default:
              __no_operation();
              break;
        }
        break;
    default: break;
  }
}


unsigned int get_version(void)
{
    unsigned int version;


     I2C_Master_WriteReg(PN532_I2C_ADDRESS , 0, version_buff, 8);

     I2C_Master_ReadReg(PN532_I2C_ADDRESS ,0, 12);
     CopyArray(ReceiveBuffer, nfc_buf, 12);

    version = nfc_buf[7];
    version <<= 8;
    version |= nfc_buf[8];
    version <<= 8;
    version |= nfc_buf[9];
    version <<= 8;
    version |= nfc_buf[10];

    return version;
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我注意到 I2C_Master_WriteReg ()中的计数值8与缓冲区/数组大小9不同。 如果 PN532需要9个字节、那么这也许是它没有响应的原因。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已将 I2C_Master_WriteReg ()中的计数值更改为9、问题仍然存在。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这种症状听起来很像 NACK。 不幸的是、ISR 不会对 UCNACKIFG 执行任何操作、因此结果将是挂起。 您可以尝试在此处设置断点、或在 CCS Registers 视图中查看 USCI_B0:UCB0IFG。

    您使用的地址是什么、即 PN532_I2C_ADDRESS 的值是什么? 如果您使用的是 Adafruit 板(#789)、其产品页面显示应为0x48。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的帮助、我纠正了一些错误、现在我可以发送数据、也可以读取这些错误。 唯一的问题是现在我一直读取0x80、而不是读取 pn532应该发送的内容。。 我不知道为什么。 我想我正在发送它所需的命令...

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您发送的确切内容(返回0x80s)? 我不熟悉此器件、但可能有人会看到一些东西。

    我找不到协议定义(NXP 数据表主要讨论板载 MCU)、但 Adafruit 确实有一个 Arduino 驱动程序、您可以参考它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    例如、当我键入命令以获取 pn532版本(0x00 0x00 0xFF 0x01 0xFE 0xD4 0x02 0x2A 0x00)时、我得到的值是0x80我将返回消息的大小告知它的次数。

    另一方面、如果我写入(0x00 0x00 0x00 0xFF 0x02 0xFE 0xD4 0x02 0x2A 0x00)、我得到0x01并且它停止、则不会进入中断来读取它接收到的下一个字节并永久停止。

    我认为正确的命令是第二个命令、但它不会发出标志来进入中断以读取下一个字节、它只读取第一个字节(0x01)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我(仍然)不知道此协议是如何工作的、但根据您描述的内容、您编写了一个(9字节)请求"数据包"、然后读回一个(8字节?) 响应数据包。

    您开始使用的代码是围绕"寄存器"协议模型构建的、在该模型中、您可以读取/写入器件中的"存储器"、并由1字节的"寄存器编号"进行寻址。 此模型在 I2C 器件中很常见、但我开始怀疑它不适合此器件。

    具体而言

    1) 1) WriteReg 将为每个请求添加您提供的"reg_number"

    2) ReadReg 将首先向器件写入(reg_number)、然后才从器件读取响应。 (此操作是该状态机的主要原因。)

    您可能需要浏览协议文档、了解这些额外操作将产生什么影响。

    您可能能够将此程序转变为请求/响应模型(可能通过更改状态机?)、因为大部分代码仍然相关。 或者、合并示例 msp430fr243_euscib0_i2c_10.c 和_i2c_15.c 可能更容易:

    https://dev.ti.com/tirex/explore/node?node=AJ4FbEhpy0QN9VgmlO5i8g__IOGqZri__LATEST

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、我认为你是对的。 其理念是、我必须向 PN532发送命令、在接收到命令后、它将根据需要的字节数进行响应。 我修改了代码、以便它只发送我需要的命令、然后直接读取响应。 我现在得到的错误是它始终响应0xFF。

    例如、如果我发送以下命令00 00 FF 02 FE D4 02 2A 00、则获取 PN532版本、并应给出以下响应: [00  00 FF 00 FF 00]和[00 00 00 FF D5 03 32 01 06 07 E8]。 我始终得到的唯一答案是0xFF。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    不完全是 RFID、但 TI BQ 器件的 I2C 接口可能会有所帮助:https://training.ti.com/rapid-proto-fund-i2c-smbus 

    但是、最好使用 I2C 总线分析器(甚至是存储示波器)进行调试