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.

430 G2553 LAUNCHPAD 简单I2C通信,用TI官方的 using IIC MASTER(slaa382) 代码,改从器件地址后总是悬在while (UCB0CTL1 & UCTXSTP)

Other Parts Discussed in Thread: MSP430G2553, MSP430F2619, MSP430F169, MSP430F2252, TMP101, MSP430G2533

430 G2553 LAUNCHPAD 简单I2C通信,用TI官方的 using IIC MASTER(slaa382) 代码,改从器件地址后总是悬在while (UCB0CTL1 & UCTXSTP)语句过不去。

详细是这样的:

用430 G2553 LAUNCHPAD作简单I2C通信和BQ27441电源板通信。认真读了几百页的SLAU44J(2553用户手册)。认真读了飞利浦I2C协议原版(为理清基本概念)。用www.ti.com/.../litabsmultiplefilelist.tsp   中的标准官方代码,仅仅改动了头文件包含 为 2553,

I2C从器件地址55(7位地址,未加读写控制位) ,引脚从P3改P1,避开加LED的p1.6,用1.4和1.7管脚当 SLC 和 sda。

/*** USCI master library ************************************************************

In this file the usage of the USCI I2C master library without DMA support is
shown. This library uses pointers to specify what data is to be sent.

When calling the TI_USCI_I2C_receive or TI_USCI_I2C_transmit routines
the number of bytes, which are to be transmitted or received have to be passed as
well as a pointer to a data field, that contains(or stores) the data.

This code checks if there is a slave with address 0x50 is connected to the I2C
bus and if the slave device is present, bytes are received and transmitted.

Uli Kretzschmar
MSP430 Systems
Freising
*******************************************************************************/
#include <msp430G2553.h>
#include "TI_USCI_I2C_master.h"

unsigned char timercounter;
unsigned char array[40] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb };
unsigned char store[40] = { 13, 13, 13, 13, 13, 13, 13, 0, 0, 0};


void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;



_EINT();

TI_USCI_I2C_transmitinit(0x55,0x40); // init transmitting with USCI

while ( TI_USCI_I2C_notready() ); // wait for bus to be free

if ( TI_USCI_I2C_slave_present(0x55) ) // slave address may differ from initialization

{
TI_USCI_I2C_receiveinit(0x55,0x40); // init receiving with USCI

while ( TI_USCI_I2C_notready() ); // wait for bus to be free

TI_USCI_I2C_receive(1,store);

while ( TI_USCI_I2C_notready() ); // wait for bus to be free

TI_USCI_I2C_transmitinit(0x55,0x40); // init transmitting with

while ( TI_USCI_I2C_notready() ); // wait for bus to be free

TI_USCI_I2C_transmit(4,array); // start transmitting
}

LPM3;

}

下面是TI_USCI_I2C_master.h头文件

#ifndef USCI_LIB
#define USCI_LIB

#define SDA_PIN BIT7 // msp430x261x UCB0SDA pin
#define SCL_PIN BIT4 // msp430x261x UCB0SCL pin

void TI_USCI_I2C_receiveinit(unsigned char slave_address, unsigned char prescale);
void TI_USCI_I2C_transmitinit(unsigned char slave_address, unsigned char prescale);


void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field);
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field);


unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address);
unsigned char TI_USCI_I2C_notready();


#endif

下面是 :TI_USCI_I2C_master.c

//******************************************************************************
// MSP430 USCI I2C Transmitter and Receiver
//
// Description: This code configures the MSP430's USCI module as
// I2C master capable of transmitting and receiving bytes.
//
// ***THIS IS THE MASTER CODE***
//
// Master
// MSP430F2619
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | |
// | |
// | SDA/P1.1|------->
// | SCL/P1.2|------->
//
// Note: External pull-ups are needed for SDA & SCL
//
// Uli Kretzschmar
// Texas Instruments Deutschland GmbH
// November 2007
// Built with IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include <msp430G2553.h> // device specific header
//#include "msp430x22x4.h"
//#include "msp430x23x0.h"
//#include "msp430xG46x.h"
// ... // more devices are possible

#include "TI_USCI_I2C_master.h"

signed char byteCtr;
unsigned char *TI_receive_field;
unsigned char *TI_transmit_field;

//------------------------------------------------------------------------------
// void TI_USCI_I2C_receiveinit(unsigned char slave_address,
// unsigned char prescale)
//
// This function initializes the USCI module for master-receive operation.
//
// IN: unsigned char slave_address => Slave Address
// unsigned char prescale => SCL clock adjustment
//-----------------------------------------------------------------------------
void TI_USCI_I2C_receiveinit(unsigned char slave_address,
unsigned char prescale){
P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0
UCB0CTL1 = UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = prescale; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slave_address; // set slave address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE = UCNACKIE;
IE2 = UCB0RXIE; // Enable RX interrupt
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmitinit(unsigned char slave_address,
// unsigned char prescale)
//
// This function initializes the USCI module for master-transmit operation.
//
// IN: unsigned char slave_address => Slave Address
// unsigned char prescale => SCL clock adjustment
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmitinit(unsigned char slave_address,
unsigned char prescale){
P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0
UCB0CTL1 = UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = prescale; // set prescaler
UCB0BR1 = 0;
UCB0I2CSA = slave_address; // Set slave address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE = UCNACKIE;
IE2 = UCB0TXIE; // Enable TX ready interrupt
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-receiver mode.
//
// IN: unsigned char byteCount => number of bytes that should be read
// unsigned char *field => array variable used to store received data
//------------------------------------------------------------------------------
void TI_USCI_I2C_receive(unsigned char byteCount, unsigned char *field){
TI_receive_field = field;
if ( byteCount == 1 ){
byteCtr = 0 ;
__disable_interrupt();
UCB0CTL1 |= UCTXSTT; // I2C start condition
while (UCB0CTL1 & UCTXSTT); // Start condition sent?
UCB0CTL1 |= UCTXSTP; // I2C stop condition
__enable_interrupt();
} else if ( byteCount > 1 ) {
byteCtr = byteCount - 2 ;
UCB0CTL1 |= UCTXSTT; // I2C start condition
} else
while (1); // illegal parameter
}

//------------------------------------------------------------------------------
// void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field)
//
// This function is used to start an I2C commuincation in master-transmit mode.
//
// IN: unsigned char byteCount => number of bytes that should be transmitted
// unsigned char *field => array variable. Its content will be sent.
//------------------------------------------------------------------------------
void TI_USCI_I2C_transmit(unsigned char byteCount, unsigned char *field){
TI_transmit_field = field;
byteCtr = byteCount;
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
}

//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
//
// This function is used to look for a slave address on the I2C bus.
//
// IN: unsigned char slave_address => Slave Address
// OUT: unsigned char => 0: address was not found,
// 1: address found
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)
{

unsigned char ie2_bak, slaveadr_bak, ucb0i2cie, returnValue;
ucb0i2cie = UCB0I2CIE; // store old UCB0I2CIE
ie2_bak = IE2; // store IE2 register
slaveadr_bak = UCB0I2CSA; // store old slave address

UCB0I2CIE &= ~ UCNACKIE; // no NACK interrupt
UCB0I2CSA = slave_address; // set slave address
IE2 &= ~(UCB0TXIE + UCB0RXIE); // no RX or TX interrupts
__disable_interrupt();
UCB0CTL1 |= UCTR + UCTXSTT +UCTXSTP; // I2C TX, start condition



while (UCB0CTL1 & UCTXSTP); // wait for STOP condition



returnValue = !(UCB0STAT & UCNACKIFG);
__enable_interrupt();
IE2 = ie2_bak; // restore IE2
UCB0I2CSA = slaveadr_bak; // restore old slave address
UCB0I2CIE = ucb0i2cie; // restore old UCB0CTL1
return returnValue; // return whether or not
// a NACK occured
}

//------------------------------------------------------------------------------
// unsigned char TI_USCI_I2C_notready()
//
// This function is used to check if there is commuincation in progress.
//
// OUT: unsigned char => 0: I2C bus is idle,
// 1: communication is in progress
//------------------------------------------------------------------------------
unsigned char TI_USCI_I2C_notready(){
return (UCB0STAT & UCBBUSY);
}


#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
{
if (UCB0STAT & UCNACKIFG){ // send STOP if slave sends NACK
UCB0CTL1 |= UCTXSTP;
UCB0STAT &= ~UCNACKIFG;
}

}


#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (IFG2 & UCB0RXIFG){
if ( byteCtr == 0 ){
UCB0CTL1 |= UCTXSTP; // I2C stop condition
*TI_receive_field = UCB0RXBUF;
TI_receive_field++;
}
else {
*TI_receive_field = UCB0RXBUF;
TI_receive_field++;
byteCtr--;
}
}
else {
if (byteCtr == 0){
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
}
else {
UCB0TXBUF = *TI_transmit_field;
TI_transmit_field++;
byteCtr--;
}
}
}

总是走到TI_USCI_I2C_master.c的unsigned char TI_USCI_I2C_slave_present(unsigned char slave_address)函数中

while (UCB0CTL1 & UCTXSTP);  语句死循环,查看watch是UCB0CTL1寄存器的UCTXSTP不清零,就是stop信号没发出去。

量 SCL SDA无电压,后加语句
P1REN|=0xFF;(目的是将P1口所有加上上下拉电阻)

P1DIR|=BIT4;(这句加上或者不加应该影响不大,目的是将时钟设为输出)

后,量SCL SDA均有3.5v电压。无示波器,对不起大家。

按理说官方例程不会有错误的,只能是我没调好,但就是卡在那一句while (UCB0CTL1 & UCTXSTP);

外部器件BQ27441板接智能电源I2C开发板EV2300良好,说明外部器件I2C工作正常,可为什么就是不能与我的LAUNCHPAD通讯呢?

  • 这是我的I2C IAR 下的工程和源程序。IAR下能直接打开。

    without DMA support.rar
  • 这是我的C文件和H文件。

    TI_USCI_I2C_master.h
  • 我的main源码,论坛不让一次上传多个附件,麻烦。提前谢谢能关注我问题的TI技术精英,我接触TI有很长一段时间了,对TI各种芯片比较了解。用430只是在两年前,I2C通讯只是在半年前。另外LUANCHPAD的地线我也和bq27441板的地线连接好了,SCl SDA 线顺序应该不会错,也互换试过(无论硬件还是软件)。我不应该怀疑ti官方例程,我的环境只是由MSP430F2619  变成LAUNCHPAD的MSP430G2553. 为什么就不能发出stop呢?

    另外,我发现TI这段代码的原作者在伯克利大学的网站的相同但更详细的代码http://wsn.eecs.berkeley.edu/svn/gina/firmware/drivers/i2c.c

    unsigned char i2c_slave_present(unsigned char slave_address)
    //
    // This function is used to look for a slave address on the I2C bus.  
    // It sends a START and STOP condition back-to-back and wait for an ACK from the slave
    //
    // IN:   unsigned char slave_address  =>  Slave Address
    // OUT:  unsigned char                =>  0: address was not found, 
    //                                        1: address found
    这是 更详细的注解,其中为什么发送
    UCB1CTL1     |=  UCTR + UCTXSTT + UCTXSTP;    // transmitter, start and stop condition
       while (UCB1CTL1 & UCTXSTP);                   // wait for STOP condition
    
    
    他 给的解释是
    / It sends a START and STOP condition back-to-back and wait for an ACK from the slave
    back-to-back 同时发送 开始和停止?奇怪,这是为什么?
    
    
    另外 在ti大牛的本论坛的一个帖子中说,用硬件uci I2C通信, 地址寄存器CSA中给7位地址就行了,不用移位,因为硬件I2C帮我们移位了,这应该是对的,我上面代码中也直接给出原来地址,没有移位,而且我用过移位和不移位的地址,结果都一样。
  • http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/142810.aspx

    这是我看德州仪器外文网站的一段解答,我根据他的解答看了手册中的图片:

  • 这里面说明要写UCBXTXBUF,才能将start发出,我又加语句写了UCBXTXBUF,还是不行。

  • P1SEL |= SDA_PIN + SCL_PIN; // Assign I2C pins to USCI_B0


    硬件I2C怎么知道那个管脚是 SDA 哪个是SCL, 我只是文字define   

    #define SDA_PIN BIT7                                           // msp430x261x UCB0SDA pin
    #define SCL_PIN BIT4

    而已,可是UCIBO怎么知道的? 他怎么分配的管脚?

  • 我现在知道2553只能用p1.6  p1.7作 SCL和sda 我将上面的代码改了后,现象还是一样,停下后,我查看UCBxTXIFG=1。UCNACKIFG=0

    这说明什么?我这么详细的描述了我的情况,非常希望TI专家的指教,谢谢!

  • The UCBxTXIFG bit is set when the START condition is generated and the first data to be transmitted can be written into UCBxTXBUF.

    UCBxTXIFG is set again as soon as the data is transferred from the buffer into the shift register. If there is no data loaded to UCBxTXBUF before the acknowledge cycle, the bus is held during the acknowledge cycle with SCL low until data is written into UCBxTXBUF.
    Data is transmitted or the bus is held as long as the UCTXSTP bit or UCTXSTT bit is not set. 

    以上是从《MSP430x2xx Family User-'s Guide》P535页摘抄的。

    UCNACKIFG = 0,没有中断请求。

    我是初学者,你想问下你I2C有没有接外接电阻?

  • 你好,

         如果你是希望在G2553上实现一个I2C主机的话,可以参考430ware中的msp430g2xx3_uscib0_i2c_06例程,代码如下:

    #include <msp430.h>

    unsigned char TXData;
    unsigned char TXByteCtr;

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x48; // Slave Address is 048h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0TXIE; // Enable TX interrupt

    TXData = 0x00; // Holds TX data

    while (1)
    {
    TXByteCtr = 1; // Load TX byte counter
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    // Remain in LPM0 until all data
    // is TX'd
    TXData++; // Increment data byte
    }
    }

    //------------------------------------------------------------------------------
    // 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.
    //------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    if (TXByteCtr) // Check TX byte counter
    {
    UCB0TXBUF = TXData; // Load TX buffer
    TXByteCtr--; // Decrement TX byte counter
    }
    else
    {
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    }

  • 为什么我在用msp430g2553 launch pad 做IIC时,选用p1.6 p1.7 做端口,并且在上面外接了5K的上拉电阻,把程序烧进去后用示波器看不到波形呢?

    //******************************************************************************
    // MSP430G2xx3 Demo - USCI_B0 I2C Master TX single bytes to MSP430 Slave
    //
    // Description: This demo connects two MSP430's via the I2C bus. The master
    // transmits to the slave. This is the master code. It continuously
    // transmits 00h, 01h, ..., 0ffh and demonstrates how to implement an I2C
    // master transmitter sending a single byte using the USCI_B0 TX interrupt.
    // ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.2MHz
    //
    // /|\ /|\
    // MSP430G2xx3 10k 10k MSP430G2xx3
    // slave | | master
    // ----------------- | | -----------------
    // -|XIN P1.7/UCB0SDA|<-|---+->|P1.7/UCB0SDA XIN|-
    // | | | | |
    // -|XOUT | | | XOUT|-
    // | P1.6/UCB0SCL|<-+----->|P1.6/UCB0SCL |
    // | | | |
    //
    // D. Dang
    // Texas Instruments Inc.
    // February 2011
    // Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10
    //******************************************************************************
    #include "msp430g2553.h"

    unsigned char TXData;
    unsigned char TXByteCtr;

    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x48; // Slave Address is 048h
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0TXIE; // Enable TX interrupt

    TXData = 0x00; // Holds TX data

    while (1)
    {
    TXByteCtr = 1; // Load TX byte counter
    while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
    UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
    // Remain in LPM0 until all data
    // is TX'd
    TXData++; // Increment data byte
    }
    }

    //------------------------------------------------------------------------------
    // 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.
    //------------------------------------------------------------------------------
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    if (TXByteCtr) // Check TX byte counter
    {
    UCB0TXBUF = TXData; // Load TX buffer
    TXByteCtr--; // Decrement TX byte counter
    }
    else
    {
    UCB0CTL1 |= UCTXSTP; // I2C stop condition
    IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    }

  • 我也是刚开始学MSP430,发现调用TI_USCI_I2C_master这个程序来读写EEPROM(例如24C02)有些问题,写进去和读出来的内容不一样,我又查了一下EEPROM的读写,它有几种读写方式,估计可能是地址计数器自动增加导致的,但是TI_USCI_I2C_master这个程序没有提供设定EEPROM的字节地址的功能。于是又求助于I2Croutines这个程序(网上有),但是它是给MSP430F169设计的,我的芯片是MSP430F2252,编译后连接会出错。现在不知道该怎么办,想要自己改TI_USCI_I2C_master似乎难度挺大。还请高手指教,谢谢。

    PS. 我也发现调用TI_USCI_I2C_slave_present程序会死住。

  • hi  Jie Zhu2

    这两个msp430的寄存器名称不一样,改改就可以了。加油

  • 好多寄存器呢,差别挺大的,还是参考网上的LaunchPad 430 G2553 硬件i2c读写EEPROM 24C02的程序,可以了,而且24C02得是字节读写,这样写进去和读出来的值才一样,否则总是错位一个字节。

  • 24C02 是个很通用的EEPROM, 网上可以找到很多读写的函数。 对430来说,只要提供一个底层的驱动接口就可以了。

  • 你好,

    I2C本来是一个很简单的总线。

    你只需要注意一点I2C从机的ADDRESSS是7位的!这一点很重要。

    至于你的程序,不知道你是在哪里copy过来的。太过于繁琐。

    IIC一般就是while(xxx)等待返回,如果你需要可以在等待之前加上一个timer计算超时。

    没必要长篇大论,没有逻辑,而且看得累,自然出问题了不好调试。

    首先建议你把程序逻辑调整好。

    第二,把IIC正常工作的机器和不正常的机器 clk和data的示波器波形抓出来。

    问题很快可以找到。

    希望我的回答可以帮到你。

  • 调iic建议用逻辑分析仪或者示波器辅助进行,方便观察时序

  • 不同I2C slave,有不同的command gap time的,datasheet 里应该会有这些。

    做Start / Stop 的时候要加些延时进去就OK了。

    另外while的时候加个timeout机制啊,超时报错,增加些健壮性,。

    while (UCB0CTL1 & UCTXSTP && timeout){

    timeout--;

    }

  • 这个 i2c_slave_present 程序的作用是产生这样一个序列:

    START - slave address - (ACK) - STOP

    如果可以获得ACK,则证明slave address 是存在的,如果 NACK,就是这个地址无设备相应。 这个程序很常用,很多有相应时间的slave都要做这个loop。

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

    我觉得这行代码写得不好, 虽然同时set STT 和STP,会先处理STT, 但是在START 发出后,如果有ACK的话,是会同时产生 TXIFG的。

    一般 STP 需要在 TXIFG/ RXIFG处理完之后,所以如果这个时候不发数据,程序会一直在等你填TXBUFF

    尝试在 while STP的循环,手动清除一下TX/RX IFG呢。 或者在while STP之前,发送一个数据到TXBUF。

  • kqian0327 说:

    你好,

    I2C本来是一个很简单的总线。

    你只需要注意一点I2C从机的ADDRESSS是7位的!这一点很重要。

    至于你的程序,不知道你是在哪里copy过来的。太过于繁琐。

    IIC一般就是while(xxx)等待返回,如果你需要可以在等待之前加上一个timer计算超时。

    没必要长篇大论,没有逻辑,而且看得累,自然出问题了不好调试。

    首先建议你把程序逻辑调整好。

    第二,把IIC正常工作的机器和不正常的机器 clk和data的示波器波形抓出来。

    问题很快可以找到。

    希望我的回答可以帮到你。

    你好我想问下,我用的msp430g2533,温度传感器用的是tmp101,现在用官方例程,终端进不去,iic没有波形,程序如下

    #include <msp430.h>

    unsigned int RxByteCtr;
    unsigned int RxWord;

    int main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    P1DIR |= BIT0; // P1.0 output
    P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
    UCB0BR1 = 0;
    UCB0I2CSA = 0x4e; // Set slave address
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0RXIE; // Enable RX interrupt
    TACTL = TASSEL_2 + MC_2; // SMCLK, contmode

    while (1)
    {
    RxByteCtr = 2; // Load RX byte counter
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0, enable interrupts
    // Remain in LPM0 until all data
    // is RX'd

    if (RxWord < 0x1d00) // >28C?
    P1OUT &= ~0x01; // No, P1.0 = 0
    else
    P1OUT |= 0x01; // Yes, P1.0 = 1

    __disable_interrupt();
    TACCTL0 |= CCIE; // TACCR0 interrupt enabled
    __bis_SR_register(CPUOFF + GIE); // Enter LPM0, enable interrupts
    // Remain in LPM0 until TACCR0
    // interrupt occurs
    TACCTL0 &= ~CCIE; // TACCR0 interrupt disabled
    }
    }

    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void TA0_ISR(void)
    {
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }

    // The USCIAB0TX_ISR is structured such that it can be used to receive any
    // 2+ number of bytes by pre-loading RxByteCtr with the byte count.
    #pragma vector = USCIAB0TX_VECTOR
    __interrupt void USCIAB0TX_ISR(void)
    {
    RxByteCtr--; // Decrement RX byte counter

    if (RxByteCtr)
    {
    RxWord = (unsigned int)UCB0RXBUF << 8; // Get received byte
    if (RxByteCtr == 1) // Only one byte left?
    UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition
    }
    else
    {
    RxWord |= UCB0RXBUF; // Get final received byte,
    // Combine MSB and LSB
    __bic_SR_register_on_exit(CPUOFF); // Exit LPM0
    }
    }