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.

MSP430G2553硬件I2C读写24C32的问题

Other Parts Discussed in Thread: MSP430G2553

我参考TI官网的例子,例子是用的CCSv5搞的,
我用IAR,基本上不怎么用改动。
可是我仿真时发现卡在下面这句话了:
__bis_SR_register(GIE); // Enter LPM0 w/ interrupts
    UCB0CTL1 |= UCTXSTP;                // I2C stop condition
    while (UCB0CTL1 & UCTXSTP) {        // Ensure stop condition got sent
    }
就是while循环那个地方。请高手指教,谢谢!

  • 楼主,

      你可以用示波器看看IIC上面的信号,查看一下通信是否正常。有没有发送结束位。另外记得IIC的硬件上需要上拉SCL和SDA两根信号线。

    谢谢

  • 你好,

    你听在while语句是有原因的,应该是从机没有找到,所以程序死到wihile.

    你用示波器截取波形我们看一下,应该只发了从机地址然后程序就死掉了。

    因为从机没有ack

  • __bis_SR_register(GIE); // Enter LPM0 w/ interrupts

    / /  前后有矛盾

  • 你好,

    你可以把完成的.C文件贴出来吗?

    我们一起看一下你读写的操作,以及EEPROM的7位地址写操作是否正确。

    但是还是希望你能同时把IIC两个信号线的波形截图出来。

    谢谢

  • 没有发送结束位。上拉接啦。

  • 什么意思?怎么前后矛盾了?能明示吗?谢谢!


  • #include "msp430G2553.h"
    #include "I2Croutines.h"

    #define     SlaveAddress   0x50

    unsigned char read_val[150];
    unsigned char write_val[150];
    unsigned int address;

    int main(void)
    {
        unsigned int i;

        WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

        InitI2C();                    // Initialize I2C module
    //
        EEPROM_ByteWrite(AT24C02, 0x0000, 0x12);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion
        EEPROM_ByteWrite(AT24C02, 0x0001, 0x34);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion
        EEPROM_ByteWrite(AT24C02, 0x0002, 0x56);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion
        EEPROM_ByteWrite(AT24C02, 0x0003, 0x78);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion
        EEPROM_ByteWrite(AT24C02, 0x0004, 0x9A);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion
        EEPROM_ByteWrite(AT24C02, 0x0005, 0xBC);
        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
                                                  // completion

    //    for (i = 0; i < 255; i++) {
    //        EEPROM_ByteWrite(AT24C02, i, 0xff);
    //        EEPROM_AckPolling();                      // Wait for EEPROM write cycle
    //                                                  // completion
    //    }

        read_val[0] = EEPROM_RandomRead(AT24C02, 0x0000);  // Read from address 0x0000
        read_val[1] = EEPROM_CurrentAddressRead(AT24C02);  // Read from address 0x0001
        read_val[2] = EEPROM_CurrentAddressRead(AT24C02);  // Read from address 0x0002
        read_val[3] = EEPROM_CurrentAddressRead(AT24C02);  // Read from address 0x0003
        read_val[4] = EEPROM_CurrentAddressRead(AT24C02);  // Read from address 0x0004
        read_val[5] = EEPROM_CurrentAddressRead(AT24C02);  // Read from address 0x0005

        // Fill write_val array with counter values
        /*for (i = 0; i <= sizeof(write_val); i++) {
            write_val[i] = i;
        }

        address = 0x0000;                         // Set starting address at 0
        // Write a sequence of data array
        EEPROM_PageWrite(AT24C02, address, write_val, sizeof(write_val));
        // Read out a sequence of data from EEPROM
        EEPROM_SequentialRead(AT24C02, address, read_val, sizeof(read_val));*/

        __bis_SR_register(LPM4);
        __no_operation();
    }

    这是主函数。

  • #include "msp430G2553.h"
    #include "I2Croutines.h"


    int PtrTransmit;
    unsigned char I2CBufferArray[66];
    unsigned char I2CBuffer;

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Initialization of the I2C Module
    /*----------------------------------------------------------------------------*/
    void InitI2C(void)
    {
    //  I2C_PORT_SEL |= SDA_PIN + SCL_PIN;        // Assign I2C pins to USCI_B0
        P1SEL |= BIT6 + BIT7;                   // Assign I2C pins to USCI_B0
        P1SEL2 |= BIT6 + BIT7;                  // Assign I2C pins to USCI_B0

        // Recommended initialization steps of I2C module as shown in User Guide:
        UCB0CTL1 |= UCSWRST;                    // Enable SW reset
        UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;   // I2C Master, synchronous mode
        UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST;   // Use SMCLK, TX mode, keep SW reset
        UCB0BR0 = SCL_CLOCK_DIV;                // fSCL = SMCLK/12 = ~100kHz
        UCB0BR1 = 0;
    //    UCB0I2CSA = eeprom_i2c_address;         // define Slave Address
                                                // In this case the Slave Address
                                                // defines the control byte that is
                                                // sent to the EEPROM.
        UCB0I2COA = 0x01A5;                     // own address.
        UCB0CTL1 &= ~UCSWRST;                   // Clear SW reset, resume operation

    //    if (UCB0STAT & UCBBUSY) {               // test if bus to be free
    //                                             // otherwise a manual Clock on is
    //                                              // generated
    //        I2C_PORT_SEL &= ~SCL_PIN;               // Select Port function for SCL
    //        I2C_PORT_OUT &= ~SCL_PIN;               //
    //        I2C_PORT_DIR |= SCL_PIN;                // drive SCL low
    //        I2C_PORT_SEL |= SDA_PIN + SCL_PIN;     // select module function for the
    //                                               // used I2C pins
    //    };
    }

    /*---------------------------------------------------------------------------*/
    // Description:
    //   Initialization of the I2C Module for Write operation.
    /*---------------------------------------------------------------------------*/
    void I2CWriteInit(unsigned char DeviceAddress)
    {
        UCB0CTL1 |= UCTR;               // UCTR=1 => Transmit Mode (R/W bit = 0)
        UCB0I2CSA = DeviceAddress;      // define Slave Address

        IFG2 &= ~UCB0TXIFG;
        IE2 &= ~UCB0RXIE;               // disable Receive ready interrupt
        IE2 |= UCB0TXIE;                // enable Transmit ready interrupt
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Initialization of the I2C Module for Read operation.
    /*----------------------------------------------------------------------------*/
    void I2CReadInit(unsigned char DeviceAddress)
    {
        UCB0CTL1 &= ~UCTR;              // UCTR=0 => Receive Mode (R/W bit = 1)
        UCB0I2CSA = DeviceAddress;    // define Slave Address

        IFG2 &= ~UCB0RXIFG;
        IE2 &= ~UCB0TXIE;               // disable Transmit ready interrupt
        IE2 |= UCB0RXIE;                // enable Receive ready interrupt
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Byte Write Operation. The communication via the I2C bus with an EEPROM
    //   (2465) is realized. A data byte is written into a user defined address.
    /*----------------------------------------------------------------------------*/
    void EEPROM_ByteWrite(unsigned char DeviceAddress,
            unsigned int WordAddress,
            unsigned char Data)
    {
       unsigned char adr_hi;
        unsigned char adr_lo;

        while (UCB0STAT & UCBUSY) { // wait until I2C module has
        }                           // finished all operations.

    //    // for 2465
    //    adr_hi = Address >> 8;              // calculate high byte
    //    adr_lo = Address & 0xFF;            // and low byte of address
    //
    //    I2CBufferArray[2] = adr_hi;         // Low byte address.
    //    I2CBufferArray[1] = adr_lo;         // High byte address.
    //    I2CBufferArray[0] = Data;
    //    PtrTransmit = 2;                    // set I2CBufferArray Pointer

        // for 24C04, 24C08 and 24C16, the device address contain word address
        if (WordAddress & 0x700) {
            DeviceAddress |= (WordAddress >> 8);
        }

        // for 24C01 and 24C02
        adr_hi = WordAddress >> 8;              // calculate high byte
        adr_lo = WordAddress & 0xFF;            // and low byte of address
        I2CBufferArray[2] = adr_hi;         // High byte address.
        I2CBufferArray[1] = adr_lo;         // High byte address.
        I2CBufferArray[0] = Data;
        PtrTransmit = 2;                    // set I2CBufferArray Pointer

        I2CWriteInit(DeviceAddress);
        __disable_interrupt();

        UCB0CTL1 |= UCTXSTT;                // start condition generation
                                            // => I2C communication is started
        __bis_SR_register(GIE); // Enter LPM0 w/ interrupts
        UCB0CTL1 |= UCTXSTP;                // I2C stop condition
        while (UCB0CTL1 & UCTXSTP) {        // Ensure stop condition got sent
        }
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Page Write Operation. The communication via the I2C bus with an EEPROM
    //   (24xx65) is realized. A data byte is written into a user defined address.
    /*----------------------------------------------------------------------------*/
    void EEPROM_PageWrite(unsigned char DeviceAddress,
            unsigned int StartAddress,
            unsigned char * Data,
            unsigned int Size)
    {
        volatile unsigned int i = 0;
        volatile unsigned char counterI2cBuffer;
    //    unsigned char adr_hi;
        unsigned char adr_lo;
        unsigned int currentAddress = StartAddress;
        unsigned int currentSize = Size;
        unsigned int bufferPtr = 0;
        unsigned char moreDataToRead = 1;

        while (UCB0STAT & UCBUSY) {     // wait until I2C module has
        }                               // finished all operations.


        // Execute until no more data in Data buffer
        while (moreDataToRead) {
    //        adr_hi = currentAddress >> 8;           // calculate high byte
            adr_lo = currentAddress & 0xFF;         // and low byte of address

            // for 24C04, 24C08 and 24C16, the device address contain word address
            if (currentAddress & 0x700) {
                DeviceAddress |= (currentAddress >> 8);
            }

            // Chop data down to MAX_BYTE_PER_PAGE-byte packets to be transmitted at a time
            // Maintain pointer of current start address
            if (currentSize > MAX_BYTE_PER_PAGE) {
                bufferPtr += MAX_BYTE_PER_PAGE;
                counterI2cBuffer = MAX_BYTE_PER_PAGE - 1;
                PtrTransmit = MAX_BYTE_PER_PAGE;       // set I2CBufferArray Pointer
                currentSize -= MAX_BYTE_PER_PAGE;
                currentAddress += MAX_BYTE_PER_PAGE;

                // Get start address
    //            I2CBufferArray[MAX_BYTE_PER_PAGE + 1] = adr_hi; // High byte address.
                I2CBufferArray[MAX_BYTE_PER_PAGE] = adr_lo; // Low byte address.
            } else {
                bufferPtr = bufferPtr + currentSize;
                counterI2cBuffer = currentSize - 1;
                PtrTransmit = currentSize;        // set I2CBufferArray Pointer.
                moreDataToRead = 0;
                currentAddress = currentAddress + currentSize;

                // Get start address
    //            I2CBufferArray[currentSize + 1] = adr_hi; // High byte address.
                I2CBufferArray[currentSize] = adr_lo; // Low byte address.
            }

            // Copy data to I2CBufferArray
            unsigned char temp;
            for (i; i < bufferPtr; i++) {
                temp = Data[i];                     // Required or else IAR throws a
                                                    // warning [Pa082]
                I2CBufferArray[counterI2cBuffer] = temp;
                counterI2cBuffer--;
            }

            I2CWriteInit(DeviceAddress);
            __disable_interrupt();

            UCB0CTL1 |= UCTXSTT;                    // start condition generation
                                                    // => I2C communication is started
            __bis_SR_register(LPM0_bits + GIE);
            // Enter LPM0 w/ interrupts
            UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
            while (UCB0CTL1 & UCTXSTP)
                ;              // Ensure stop condition got sent

            EEPROM_AckPolling();                 // Ensure data is written in EEPROM
        }
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Current Address Read Operation. Data is read from the EEPROM. The current
    //   address from the EEPROM is used.
    /*----------------------------------------------------------------------------*/
    unsigned char EEPROM_CurrentAddressRead(unsigned char DeviceAddress)
    {
        while (UCB0STAT & UCBUSY) {     // wait until I2C module has
        }                               // finished all operations

     

        I2CReadInit(DeviceAddress);

        UCB0CTL1 |= UCTXSTT;            // I2C start condition
        while (UCB0CTL1 & UCTXSTT) {    // Start condition sent?
        }
        UCB0CTL1 |= UCTXSTP;            // I2C stop condition
        __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
        while (UCB0CTL1 & UCTXSTP) {
        }                               // Ensure stop condition got sent
        return I2CBuffer;
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Random Read Operation. Data is read from the EEPROM. The EEPROM
    //   address is defined with the parameter Address.
    /*----------------------------------------------------------------------------*/
    unsigned char EEPROM_RandomRead(unsigned char DeviceAddress,
            unsigned int WordAddress)
    {
        unsigned char adr_hi;
        unsigned char adr_lo;

        while (UCB0STAT & UCBUSY) {             // wait until I2C module has
        }                                       // finished all operations

        // for 24C04, 24C08 and 24C16, the device address contain word address
        if (WordAddress & 0x700) {
            DeviceAddress |= (WordAddress >> 8);
        }

    // for 24xxx
    //    adr_hi = WordAddress >> 8;                  // calculate high byte
    //    adr_lo = WordAddress & 0xFF;                // and low byte of address
    //
    //    I2CBufferArray[1] = adr_hi;             // store single bytes that have to
    //    I2CBufferArray[0] = adr_lo;             // be sent in the I2CBuffer.
    //    PtrTransmit = 1;                        // set I2CBufferArray Pointer

    //    adr_hi = WordAddress >> 8;                  // calculate high byte
        adr_lo = WordAddress & 0xFF;                // and low byte of address

    //    I2CBufferArray[1] = adr_hi;             // store single bytes that have to
        I2CBufferArray[0] = adr_lo;             // be sent in the I2CBuffer.
        PtrTransmit = 0;

        // Write Address first
        I2CWriteInit(DeviceAddress);
        __disable_interrupt();

        UCB0CTL1 |= UCTXSTT;                    // start condition generation
                                                // => I2C communication is started
        __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0 w/ interrupts
    //    __bis_SR_register( GIE);     // Enter LPM0 w/ interrupts


        // Read Data byte
        I2CReadInit(DeviceAddress);

        UCB0CTL1 |= UCTXSTT;                    // I2C start condition
        while (UCB0CTL1 & UCTXSTT) {            // Start condition sent?
        }
        UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
        __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0 w/ interrupts
        while (UCB0CTL1 & UCTXSTP) {            // Ensure stop condition got sent
        }

        return I2CBuffer;
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Sequential Read Operation. Data is read from the EEPROM in a sequential
    //   form from the parameter address as a starting point. Specify the size to
    //   be read and populate to a Data buffer.
    /*----------------------------------------------------------------------------*/
    void EEPROM_SequentialRead(unsigned char DeviceAddress,
            unsigned int WordAddress,
            unsigned char * Data,
            unsigned int Size)
    {
    //    unsigned char adr_hi;
        unsigned char adr_lo;
        unsigned int counterSize;

        // for 24C04, 24C08 and 24C16, the device address contain word address
        if (WordAddress & 0x700) {
            DeviceAddress |= (WordAddress >> 8);
        }

        while (UCB0STAT & UCBUSY) {             // wait until I2C module has
        }                                       // finished all operations


    //    adr_hi = WordAddress >> 8;                  // calculate high byte
    //    adr_lo = WordAddress & 0xFF;                // and low byte of address
    //
    //    I2CBufferArray[1] = adr_hi;             // store single bytes that have to
    //    I2CBufferArray[0] = adr_lo;             // be sent in the I2CBuffer.
    //    PtrTransmit = 1;                        // set I2CBufferArray Pointer

    //    adr_hi = WordAddress >> 8;                  // calculate high byte
        adr_lo = WordAddress & 0xFF;                // and low byte of address

    //    I2CBufferArray[1] = adr_hi;             // store single bytes that have to
        I2CBufferArray[0] = adr_lo;             // be sent in the I2CBuffer.
        PtrTransmit = 0;

        // Write Address first
        I2CWriteInit(DeviceAddress);
        __disable_interrupt();
        UCB0CTL1 |= UCTXSTT;                    // start condition generation
                                                // => I2C communication is started
        __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0 w/ interrupts
    //    __bis_SR_register( GIE);     // Enter LPM0 w/ interrupts


        // Read Data byte
        I2CReadInit(DeviceAddress);

        UCB0CTL1 |= UCTXSTT;                    // I2C start condition
        while (UCB0CTL1 & UCTXSTT) {            // Start condition sent?
        }

        for (counterSize = 0; counterSize < Size; counterSize++) {
            __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupts
            Data[counterSize] = I2CBuffer;
        }
        UCB0CTL1 |= UCTXSTP;                    // I2C stop condition
        __bis_SR_register(LPM0_bits + GIE);     // Enter LPM0 w/ interrupts
        while (UCB0CTL1 & UCTXSTP) {            // Ensure stop condition got sent
        }
    }

    /*----------------------------------------------------------------------------*/
    // Description:
    //   Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
    //   in progress. It can be used to determine when a write cycle is completed.
    /*----------------------------------------------------------------------------*/
    void EEPROM_AckPolling(void)
    {
        while (UCB0STAT & UCBUSY) {             // wait until I2C module has
        }                                       // finished all operations

        do {
            UCB0STAT = 0x00;                    // clear I2C interrupt flags
            UCB0CTL1 |= UCTR;                   // I2CTRX=1 => Transmit Mode (R/W bit = 0)
            UCB0CTL1 &= ~UCTXSTT;
            UCB0CTL1 |= UCTXSTT;                // start condition is generated
            while (UCB0CTL1 & UCTXSTT) {        // wait till I2CSTT bit was cleared
                if (!(UCNACKIFG & UCB0STAT)) {  // Break out if ACK received
                    break;
                }
            }
            UCB0CTL1 |= UCTXSTP;                // stop condition is generated after
                                                // slave address was sent => I2C communication is started
            while (UCB0CTL1 & UCTXSTP) {        // wait till stop bit is reset
            }
            __delay_cycles(500);                // Software delay
        } while (UCNACKIFG & UCB0STAT);
    }

    /*---------------------------------------------------------------------------*/
    /*  Interrupt Service Routines                                               */
    /*     Note that the Compiler version is checked in the following code and   */
    /*     depending of the Compiler Version the correct Interrupt Service       */
    /*     Routine definition is used.                                           */
    //#if __VER__ < 200
    //interrupt [USCIAB0TX_VECTOR] void TX_ISR_I2C(void)
    //#else
    //#pragma vector=USCIAB0TX_VECTOR
    //__interrupt void TX_ISR_I2C(void)
    //#endif
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
        if (UCB0TXIFG & IFG2) {                         // TX
            UCB0TXBUF = I2CBufferArray[PtrTransmit];    // Load TX buffer
            PtrTransmit--;                              // Decrement TX byte counter
            if (PtrTransmit < 0) {
                while (!(IFG2 & UCB0TXIFG)) {           // wait for tx complete
                }
                IE2 &= ~UCB0TXIE;                       // disable interrupts.
                IFG2 &= ~UCB0TXIFG;                     // Clear USCI_B0 TX int flag
                __bic_SR_register_on_exit(LPM0_bits);   // Exit LPM0
            }
        } else if (UCB0RXIFG & IFG2) {                  // RX
            I2CBuffer = UCB0RXBUF;                      // store received data in buffer
            __bic_SR_register_on_exit(LPM0_bits);       // Exit LPM0
        }
    }

    这是I2C对应的驱动程序。

    截图稍后补上。