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.

[参考译文] MSP-EXP430F5529LP:I2C 目标(也称为从器件)器件胜出#39;t 发送 ACK

Guru**** 2457760 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1439834/msp-exp430f5529lp-i2c-target-aka-slave-device-won-t-send-an-ack

器件型号:MSP-EXP430F5529LP

工具与软件:

大家好、  

我正在尝试在基于 I2C 的传感器和 MSP430开发板之间建立通信。 请查看下面的代码。 传感器不会发送 ACK。 我尚未使用默认1MHz 更改系统的时钟。 并且 I2C 通信速度为100KHz。

如图所示、我已将4.7k Ω 上拉电阻连接到 I2C 线路。  


#include "driverlib.h"
#include <msp430.h>
#include "inc/hw_memmap.h"
#include "uart_debug.h"

#define    BAUD_RATE    115200
//******************************************************************************
//!
//!   Empty Project that includes driverlib
//!
//******************************************************************************

//******************************************************************************
//!
//!   Local Function Prototypes
//!
//******************************************************************************
static void watchdog_stop (void);
static void init_i2c(void);
static void check_i2c_slave(void);
//******************************************************************************
//!
//!   Local Variables
//!
//******************************************************************************

int main (void)
{

    watchdog_stop();
    init_debug_uart();
    init_i2c();
    //check_i2c_slave();
    while(1)
    {
        debug_print("Debugging Working\n\r");
        check_i2c_slave();
        __delay_cycles(3000000); //3sn
    }
}

//******************************************************************************
//!
//!   Local Function Definitions
//!
//******************************************************************************
static void watchdog_stop (void)
{
    WDTCTL = WDTPW + WDTHOLD;
}

static void init_i2c(void)
{
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN2 | GPIO_PIN1);//P4.1 SDA, P4.2 SCL
    UCB1CTL1 |= UCSWRST;                        // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;       // Master, I2C, Synchronous mode
    UCB1CTL1 = UCSSEL_2 + UCSWRST + UCTR;       // Use SMCLK, keep SW reset
    UCB1BR0 = 10;                               // set prescaler, since SMCLK is 1MHz, /10 will give 100KHz
    UCB1BR1 = 0;
    UCB1I2CSA =  0x74;                          // Set slave address
    UCB1CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
    while (UCB1STAT & UCBBUSY);                 // Wait for the I2C Bus to get free.
}

static void check_i2c_slave (void)
{
    // Send start condition (this happens when the first byte is sent)
    UCB1CTL1 |= UCTR + UCTXSTT; // Transmit mode, send start bit

    while (UCB1CTL1 & UCTXSTT); // Wait for start bit to be transmitted
    debug_print("Start Bit Transmission Complete\r\n");

    // Now, you can send data or address
    //UCB1TXBUF = (0x74) << 1; // Send slave address with write operation

    // Wait for data transmission to complete
    while (UCB1CTL1 & UCTXSTT); // Wait for start condition to be sent
    debug_print("Data Transmission Complete\r\n");

    // For now, let's just stop the transmission.
    UCB1CTL1 |= UCTXSTP; // Send stop condition

    // Wait for stop condition
    while (UCB1CTL1 & UCTXSTP);
    debug_print("Stop Bit Transmission Complete\r\n");
}

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

    您误解了 I2C 时序。 目标确认地址后、UCTXSTT 会清除。 I2C 端口将一直保持时钟、直到有数据可发送。 这意味着由于您从不提供该数据、因此无法完成确认周期(时钟的上升沿)。 因此 UCTXSTT 永远不会清除。

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

    您不确定 I2C 地址(0x74)是否正确? 更笼统地说:您使用的是什么传感器/分线板?

    查看 Adafruit I2C 地址列表(不是权威性的、但很好)、位于0x74的唯一传感器本身就是 PCT2075、它可以有27个不同的地址中的任何一个。 Adafruit 分线板(交付时)地址为0x37。

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

    嗨! 很抱歉我没有在帖子中指定。 我使用的是触摸板 EVB、我们使用的是另一个微控制器上的代码库。 我将其移植到 TI。 地址为0x74、如传感器数据表中所指定。  

    我也尝试过:  
    我有一个由 Micro-Crystal 提供的 RTC 分接板、其地址为0x52。 我曾尝试在 RTC 分接板上运行相同的代码、但 RTC 分接板仍然没有提供 ACK。 因此、我非常确定我编写的代码中存在错误。 同一个 RTC 分线板响应扫描 I2C 总线的 Arduino sketch。 因此我们知道分线板工作正常。  

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

    谢谢你的答复,大卫。  

    你是否建议我取消对下面几行的评论?

    // Now, you can send data or address
    //UCB1TXBUF = (0x74) << 1; // Send slave address with write operation

    如果这是你的建议,那么我尝试了,但它不起作用。  

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

    嗨、David、  
    此代码的工作方式:  

    static void I2C_write(uint16_t regAddr, uint8_t *data, uint8_t size)
    {
        uint8_t data_idx;
        // Wait for any previous stop condition to complete
        while (UCB1CTL1 & UCTXSTP);
    
        // Set the device to transmit mode and send the start condition
        UCB1CTL1 |= UCTR + UCTXSTT;
    
        // Wait for the transmit buffer to be ready to send the slave address
        while (!( UCB1IFG & UCTXIFG));
    
        // Send the high byte of the register address
        UCB1TXBUF = (uint8_t)(regAddr >> 8);  // Send high byte of register address (0x04)
    
        // Wait for the high byte to be transmitted
        while (!(UCB1IFG & UCTXIFG));
    
        // Send the low byte of the register address
        UCB1TXBUF = (uint8_t)(regAddr & 0xFF);  // Send low byte of register address (0x31)
    
        // Wait for the low byte to be transmitted
        while (!(UCB1IFG & UCTXIFG));
    
        // Send the bytes
        for (data_idx = 0; data_idx < size; data_idx++)
        {
            // Send the data byte
            UCB1TXBUF = data[data_idx];
    
            // Wait for the data byte to be transmitted
            while (!(UCB1IFG & UCTXIFG));
        }
    
        // Send the stop condition
        UCB1CTL1 |= UCTXSTP;
    
        // Wait for stop condition to be completed
        while (UCB1CTL1 & UCTXSTP);
    }

    我不知道为什么!

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

    我解释得很仔细,但我会再试一次。

    在把数据写入 TXBUF 之前、你正在等待开始条件标志清零。  要完成地址确认、清除 STT、I2C 端口必须要发送数据。 不同的是、因为在写入数据之前您正在等待启动条件标志清除。

    现在、您正在等待 TXIFG。 它会提前设置。