添加至 MSP430F5418A I2C通信问题 wiki 页面

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.

MSP430F5418A I2C通信问题

Other Parts Discussed in Thread: MSP430F5418A

Hi all,

MSP430F5418A在用I2C通信过程中,需要将slave的地址装到寄存器中,我用的是7位地址模式,但是还有一位读/写位放在什么位置呢?

是和地址放到一起吗?

还有,如果我是想从slave中读数据,那么先要将地址写入,之后再写入要读去哪个寄存器,才开始读。整个过程中是不是需要读和写的过程转换?如果需要的话,应该如何

转换数据方向?

 

谢谢

 

Nick

  • Hi

    还是我,另外一个问题,当slave收到数据之后,会给master一个ACK,这个ACK是slave自动发的吧?master在检测到

    ACK之后,才会继续发送下一个数据吗?

    谢谢

    Nick

  • Nick您好,

    UCB0I2CSA装载了slave的7位地址,往这个寄存器写入的就是从机的地址。

    通过清除或置位(UCBxCTL1)寄存器的UCTR位来设置主机的读或者写,UCTR = 0为读(接收),UCTR = 1为写(发送)。

    如果是从slave中读数据,需要按照你说的方法操作,先将要读取的寄存器地址写入slave中,然后紧跟着读取slave寄存器的数据。可以通过修改UCTR来实现读或者写的操作。

  • 还是我,另外一个问题,当slave收到数据之后,会给master一个ACK,这个ACK是slave自动发的吧?master在检测到

    ACK之后,才会继续发送下一个数据吗?

    1、ACK是由slave自动发送的;

    2、ACK是一个握手标志,如果没有检测到ACK,那么说明从机通信失败,需要重新建立通信过程。

  • Hi,

    十分感谢您及时的回复。

    Nick

  • Hi,

    我在用i2c通信过程又遇到了以下问题:

    我在发送数据过程中,为什么只发送了几个byte就从ISR中跳出来了?而且在发送数据过程中,STAT寄存器中SCLLOW

    位始终置位,这是对的吗?

    我的程序如下所示:

    #include "msp430x54xA.h"

    unsigned char *PTxData;                     // Pointer to TX data

    unsigned char TXByteCtr;

    #define VCC3P3_PwrOn         (P8OUT |= BIT5)

    #define VCC3P3_PwrGood       (P8IN & BIT6)

    #define LED_ON               (P3OUT &= ~(BIT6))

    #define LED_OFF              (P3OUT |= BIT6)

    const unsigned char TxData[] =              // Table of data to transmit

    {

     0x01,

     0x0b,

     0x02,

     0x00,

     0x00,

     0x03,

     0x32,

     0x00,

    };

    void test_mcu_port_init(void);

    void main(void)

    {

     WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

     test_mcu_port_init();

     VCC3P3_PwrOn;

     while(!(VCC3P3_PwrGood))

     {

    ;

     }

     LED_ON;

     P3SEL |= 0x80;                            // Assign I2C pins to USCI_B0

     P5SEL |= 0x10;

     UCB1CTL1 |= UCSWRST;                      // Enable SW reset

     UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode

     UCB1CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset

     UCB1BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz

     UCB1BR1 = 0;

     UCB1I2CSA = 0x4a;                         // Slave Address is 048h

     UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

     UCB1IE |= UCTXIE;                         // Enable TX interrupt

    //  while (1)

    //  {

       __delay_cycles(50);                     // Delay required between transaction

       PTxData = (unsigned char *)TxData;      // TX array start address

                                               // Place breakpoint here to see each

                                               // transmit operation.

       TXByteCtr = sizeof TxData;              // Load TX byte counter

       UCB1CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition

       __bis_SR_register(GIE);     // Enter LPM0, enable interrupts

       __no_operation();                       // Remain in LPM0 until all data

                                               // is TX'd

       while (UCB1CTL1 & UCTXSTP);             // Ensure stop condition got sent

    //  }

    }

    void test_mcu_port_init(void)

    {

    /*将所有端口恢复到初始值*/

    P1OUT &= 0x00;

    P2OUT &= 0x00;

    P3OUT &= 0x00;

    /*LED为关闭状态*/

    LED_OFF;

    P4OUT &= 0x00;

    /*I/O扩展芯片中断管脚拉高*/

    P4OUT |= BIT6;

    P5OUT &= 0x00;

    P6OUT &= 0x00;

    P7OUT &= 0x00;

    /*关闭1.8V的MOSFET*/

    P7OUT |= BIT4;

    P8OUT |= 0x00;

    /*定义所有端口方向和功能选择*/

    P1SEL |= 0x00;

    P1DIR |= 0x5b;

    P2SEL |= 0x00;

    P2DIR |= 0xe7;

    P3SEL |= 0xbf;

    P3DIR |= 0x40;

    P4SEL |= 0x59;

    P4DIR |= 0xae;

    P5SEL |= 0xd0;

    P5DIR |= 0x25;

    P6SEL |= 0x03;

    P6DIR |= 0x78;

    P7SEL |= 0x0b;

    P7DIR |= 0xb4;

    P8SEL |= 0x00;

    P8DIR |= 0x3f;

    }

    //------------------------------------------------------------------------------

    // The USCIAB0TX_ISR is structured such that it can be used to transmit any

    // number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData

    // points to the next byte to transmit.

    //------------------------------------------------------------------------------

    #pragma vector = USCI_B1_VECTOR

    __interrupt void USCI_B1_ISR(void)

    {

     switch(__even_in_range(UCB1IV,12))

     {

     case  0: break;                           // Vector  0: No interrupts

     case  2: break;                           // Vector  2: ALIFG

     case  4: break;                           // Vector  4: NACKIFG

     case  6: break;                           // Vector  6: STTIFG

     case  8: break;                           // Vector  8: STPIFG

     case 10: break;                           // Vector 10: RXIFG

     case 12:                                  // Vector 12: TXIFG

       if (TXByteCtr)                          // Check TX byte counter

       {

         UCB1TXBUF = *PTxData++;               // Load TX buffer

         TXByteCtr--;                          // Decrement TX byte counter

       }

       else

       {

         UCB1CTL1 |= UCTXSTP;                  // I2C stop condition

         UCB1IFG &= ~UCTXIFG;                  // Clear USCI_B0 TX int flag

       }

     default: break;

     }

    }

    请帮忙解答一下

    Thx

    Nick

  • Nick,您好,

    建议您参考一下TI最近刚推出的一个MSP430的一个驱动库,其中就包括了I2C的使用,可以参考一下这部分代码。

    www.ti.com.cn/.../msp430ware

  • Hi,

    1,当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节回答“ACK”,如果没有空间接收数据了,就不会发“ACK”,所以是需要检测到“ACK”后再发送下个数据个Slave.

  • 是的,ACK是slave发送,发完第8bit后,master会release SDA给slave,等待ACK,如果slave不把SDA拉低,则会触发NACK,如果拉低会触发UCB0TXIFG,因为我们一般在NCAK中断中放置STOP或者重发,在TXIFG被置位后说明slave收到了改数据,才再开始发送下一个数据

  • 实现这个功能可以这样做,不接受数据了,在RXIFG中断中read RXBUF,然后generate NACK。

  • 这是从机这边的程序。

    在主机端,接收到NACK时generate stop就行了。