You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSP430F249T I2C起始条件后传输失败问题求助

MSP430F249T I2C写操作失败:UCTXSTT始终置位、SDA卡低电平问题排查与修复

核心问题分析

  • 总线空闲检查缺失:发送起始条件前未等待总线空闲,导致起始条件无法正常触发
  • NACK处理逻辑错误:从机NACK后未发送停止条件就直接重试起始,导致总线状态混乱
  • 初始化顺序与总线复位不规范:重新初始化时未正确处理总线忙状态,导致SDA引脚被锁定在低电平

具体修复方案

1. 修正I2C初始化函数

调整引脚复用配置顺序,确保USCI模块配置前引脚已正确复用,同时确认分频参数匹配SMCLK频率:

#pragma location = "APP_INTERNAL_SEG"
void i2c_msp_init(unsigned char DevAddr, USHORT ClkIdDivisor)
{
    P5SEL |= 0x06;                            // 先配置I2C引脚复用:SDA(P5.1)、SCL(P5.2)
    UCB1CTL1 = UCSWRST;                       // 进入软件复位模式
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;     // 配置为主机、I2C模式、同步通信
    
    UCB1CTL1 |= UCSSEL_2;                     // 选择SMCLK作为时钟源(保持软件复位状态)
    
    UCB1BR0 = LOBYTE(ClkIdDivisor);           // 设置分频低字节
    UCB1BR1 = HIBYTE(ClkIdDivisor);           // 设置分频高字节
    // 注意:确保SMCLK频率 / (BR1<<8 + BR0) = 目标I2C频率(如100kHz)
    
    UCB1I2CSA = DevAddr;                      // 设置从机地址
    
    UCB1CTL1 &= ~UCSWRST;                     // 退出软件复位,启用USCI模块
}

2. 修正发送起始函数的逻辑

恢复总线空闲检查,正确处理NACK情况,添加标志位清除:

#pragma location = "APP_INTERNAL_SEG"
BOOL i2c_msp_start_tx(void)
{
    int count01;
    int count02;
    
    // 等待总线空闲,避免干扰正在进行的传输
    count01 = 0;
    while(UCB1STAT & UCBBUSY)
    {
        count01++;
        if(count01 > COUNT_MAX)
            return FALSE;
    }
    
    UCB1STAT &= ~UCNACKIFG;                   // 提前清除NACK标志
    UCB1CTL1 |= (UCTR | UCTXSTT);             // 发送起始条件+从机地址(写模式)

    count01 = 0;
    while(UCB1CTL1 & UCTXSTT)                 // 等待起始+地址传输完成
    {
        count01++;
        if(count01 > COUNT_MAX)
        {
            // 超时:发送停止条件释放总线
            UCB1CTL1 |= UCTXSTP;
            while(UCB1CTL1 & UCTXSTP);
            return FALSE;
        }
    }
    
    // 处理从机NACK情况
    count01 = 0;
    while(UCB1STAT & UCNACKIFG)             
    {
        count01++;
        if(count01 > COUNT_MAX)
        {
            UCB1CTL1 |= UCTXSTP;
            while(UCB1CTL1 & UCTXSTP);
            return FALSE;
        }
        
        UCB1STAT &= ~UCNACKIFG;               // 清除NACK标志
        UCB1CTL1 |= UCTXSTP;                  // 先发送停止条件释放总线
        while(UCB1CTL1 & UCTXSTP);            // 等待停止条件完成
        
        // 重新发送起始+地址
        UCB1CTL1 |= (UCTR | UCTXSTT);         
        count02 = 0;
        while(UCB1CTL1 & UCTXSTT)         
        {
            count02++;
            if(count02 > COUNT_MAX)
            {
                UCB1CTL1 |= UCTXSTP;
                while(UCB1CTL1 & UCTXSTP);
                return FALSE;
            }
        }
    }
    
    return TRUE;
}

3. 优化重新初始化的逻辑

避免每次传输都重新初始化I2C模块,若必须重启,需先释放总线:

// 如需重新初始化I2C,先执行以下操作释放总线
void i2c_msp_reset(void)
{
    int count = 0;
    // 尝试发送停止条件释放总线
    UCB1CTL1 |= UCTXSTP;
    while(UCB1CTL1 & UCTXSTP)
    {
        count++;
        if(count > COUNT_MAX)
            break;
    }
    // 进入软件复位模式
    UCB1CTL1 = UCSWRST;
    // 重置引脚(可选,确保引脚状态正常)
    P5SEL &= ~0x06;
    P5DIR &= ~0x06;
    P5OUT |= 0x06;
    __delay_cycles(100);
    P5SEL |= 0x06;
}

额外排查点

  • 用示波器确认SMCLK频率是否符合预期,分频参数是否计算正确(SCL频率=SMCLK/(BR1*256+BR0))
  • 检查从机设备是否上电、地址是否正确(I2C写操作时地址最后一位为0)
  • 确认I2C总线上没有其他设备占用总线,或存在硬件短路(SDA/SCL对地短路会导致引脚卡低)

内容的提问来源于stack exchange,提问作者Andrea

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:27:23