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.

[参考译文] MSP430FR5.9941万:通过I2C重新启动读取寄存器

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/616337/msp430fr59941-read-registers-over-i2c-with-restart

部件号:MSP430FR5.9941万

在这个新零件中,我在通过I2C重新启动和注册读数时遇到了一些问题。  我以前的MSP430上使用了旧代码,但它没有很好地移植到新的MSP430上。  当我运行下面的代码时,会出现一个0x40的写入,接着是0x00的写入,接着是重新启动,但是0x40会出现并设置了读取位,然后又出现了另一个意外的0x60写入。  我不知道我做了什么错了,这些例子似乎从未显示如何进行I2C类型的访问:) 任何建议都值得赞赏,我正在努力解决这个问题。

UCB1CTLW0 = UCSWRST; //将eUSI_B置于重置状态
UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK;// I2C主模式,SMCLK
UCB1BRW = 0x8; //波特率= SMCLK / 8
UCB1CTLW0 &=~UCSWRST; //清除复位寄存器
UCB1IE |= UCTXIE0 | UCNACKIE; //传输和nack中断启用
UCB2IE |= UCRXIE | UCNACKIE | UCBCNTIE;//接收中断启用

SlaveFlag =0; //初始化SlaveFlag
TXByteCtr = 2; //加载TX字节计数器


UCB1I2CSA = 0x40;//配置从属地址
While (UCB1CTLW0和UCTXSTP); //确保停止条件已发送

UCB1CTLW0 |= UCTR | UCTXSTT; // I2C TX,启动条件

__bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0

UCB1TXBUF = 0x00;//将地址加载到缓冲区
__bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0

//清除TX标记
UCB1IFG &=~UCTXIFG;//清除TX标志

//切换到RX模式
UCB1CTL1 &=~UCTR;//更改为Rx模式
UCB1IFG &=~UCRXIFG;//清除Rx IFG

UCB1CTL1 || UCTXSTT;//发送启动以重新启动
//while (UCB1CTL1和UCTXSTT);//wait for start to be set which will be a TXIFG interrupt flag.(正在设置启动,它将是TXIFG中断标志。
__bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0

//完成后停止
UCB1CTLW0 |= UCTXSTP; // I2C停止条件
UCB1IFG &=~UCTXIFG; //清除USI_B2 TX int标志


返回0;


#pragma vector=Timer1_A0_vector
__interrupt void Timer1_A0 (void){ // Timer0 A0中断服务例程

//检查按钮状态
IF ((P1IN和BIT0)== BIT0){
button_timer = 0;
其他{
button_timer++;
//如果按钮定时器>阈值开关状态
IF (button_timer >= PWR_BUTTON阈值){
CHANGE_PWR_STE_FLAG =1;
}
}

//用于调试的闪存LED
IF ((P8OUT & BIT0)== BIT0){
P8OUT &=~BIT0;
其他{
P8OUT || BIT0;
}

//清除中断
TA1CTL &=~BIT0;
TA1CCTL0 &=~CCIFG;//清除中断
//TA1CTL &=~(MC_1);//停止计时器_A
__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS+GIE);// ISR退出时清除LPM位
}


#if已定义(__TI_Compiler_version__)||已定义(__ISR_SYSTEMS _ICC__)
#pragma向量= EUSCI_B1_Vector
__interrupt void UI_B1_ISR(void_IAL_ISR_ELSE
#)


编译器#SCI_ELSE (void_US_I_IAL_SCI_)
#endif
{
Switch(__偶 数_in_range(UCB1IV, USI_I2C_UCBIT9IFG))
{
案例USI_NONE: 中断; //矢量0:无中断
案例USI_I2C_UCALIFG:中断; //矢量2:ALIFG
案例USI_I2C_UCNACKIFG: //矢量4:NACKIFG
UCB2CTLW0 |= UCTXSTT; //如果不确认,请重新发送启动
中断;
案例USI_I2C_UCSTIFG:中断; //向量6:STTIFG
案例USI_I2C_UCSTPIFG:中断; //矢量8:STPIFG
案例USI_I2C_UCRXIFG3:中断; //矢量10:RXIFG3
案例USI_I2C_UCTXIFG3:中断; //矢量12:TXIFG3
案例USI_I2C_UCRXIFG2:中断; //矢量14:RXIFG2
案例USI_I2C_UCTXIFG2:中断; //矢量16:TXIFG2
案例USI_I2C_UCRXIFG1:中断; //矢量18:RXIFG1
案例USI_I2C_UCTXIFG1:中断; //矢量20:TXIFG1
案例USI_I2C_UCRXIFG0: //矢量22:RXIFG0
*RXData = UCB2RXBUF; //获取RX数据
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
中断;
案例USI_I2C_UCTXIFG0: //矢量24:TXIFG0
/*IF (TXByteCtr) //检查TX字节计数器
{
UCB1TXBUF = TXData[SlaveFlag];//加载TX缓冲区
TXByteCtr // Decrement TX字节计数
器}
否则
{
UCB1CTLW0 |= UCTXSTP; // I2C停止条件
UCB1IFG &=~UCTXIFG; //清除USI_B2 TX int标志
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
}*/
__BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
中断;
案例USI_I2C_UCBCNTIFG:中断; //矢量26:BCNTIFG
案例USI_I2C_UCCLTOIFG:中断; //向量28:时钟低超时
案例USI_I2C_UCBIT9IFG:中断; //矢量30:第9位
默认值:break;
}
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    “写0x60”的确切含义是什么? 未设置UCTR时,硬件无法写入。

    您是否使用逻辑分析仪或示波器捕获此数据?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    一个逻辑分析器,我可能是昨天晚上弄糊涂了。 现在我认为它正在重新发送从芯片ID,但0x60不是预期的响应。 可能是我错了,但无论哪种方式,我的代码都将最后等待 __bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0,从不到达案例USI_I2C_UCRXIFG0中断。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果不看到逻辑分析器显示的内容,我就无法确定您认为是正确还是不正确。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    给你

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

    这看起来是正确的写+读事务。

    在从属设备传输0x61字节后,主设备发送ACK请求另一字节。 如果您实际上不想接收另一个字节,则必须尽早设置UCTXSTP字节(请参阅《用户指南》中的26.3 .5.2 Tm2部分)。 如果只想接收一个字节,可以同时设置UCTXSTT和UCTXSTP。

    主控制器停止时钟,因为尚未从UCB1RXBUF读取上一个字节(0x61)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    啊,好的,谢谢。 也许这是我的问题。 我不知道为什么代码永远不会达到这一标准 *RXData = UCB1RXBUF;中断处理程序中的点。 我在那里有一个断点,但它从未命中。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    解决了这个问题,我有错误的屏蔽寄存器。 现在,我的代码一直循环读取...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    哦,在三个地方,原始代码使用的是"UCB2"寄存器。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,深夜出错了,现在我不能让它只读一个字节。  我正在尝试在哪里放置停止位,但到目前为止它一直是这样的。  0xFF是部件在其地址0x00处的正确响应。  

    这是我的新代码:

    INT MAIN (void){//
    
    TXData = TXBuffer;
    
    Memset (RXData,0x00,5);
    
    WDTCTL = WDTPW | WDTHOLD;	//停止看门狗计时器
    //禁用GPIO开机默认高阻抗模式以激活
    //以前配置的端口设置
    PM5CTL0 &=~LOCKLPM2;
    //printf ("wtf");
    //fflush (stdout);
    //设置时钟
    sys_clock_init();
    Setup_timer();
    Setup_IO();
    Setup_i2c();
    
    //exp_supply_set (EN_3V3);
    //为I2C模式配置USI_B2
    UCB1CTLW0 = UCSWRST; //将eUSI_B置于重置状态
    UCB1CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK;// I2C主模式,SMCLK
    UCB1BRW = 0x8; //波特率= SMCLK / 8
    UCB1CTLW0 &=~UCSWRST; //清除复位寄存器
    UCB1IE |= UCTXIE0 | UCNACKIE | UCSTIE; //传输和nack中断启用
    UCB1IE |= UCRXIE | UCNACKIE | UCBCNTIE;//接收中断启用
    
    SlaveFlag =0; //初始化SlaveFlag
    TXByteCtr = 2; //加载TX字节计数器
    
    
    UCB1I2CSA = 0x20;//配置从属地址
    While (UCB1CTLW0和UCTXSTP); //确保停止条件已发送
    
    UCB1CTLW0 |= UCTR | UCTXSTT; // I2C TX,启动条件
    
    __bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0
    
    UCB1TXBUF = 0x00;//将地址加载到缓冲区
    __bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0
    
    //清除TX标记
    UCB1IFG &=~UCTXIFG;//清除TX标志
    
    //切换到RX模式
    UCB1CTL1 &=~UCTR;//更改为Rx模式
    UCB1IFG &=~UCRXIFG;//清除Rx IFG
    
    UCB1CTL1 || UCTXSTT;//发送启动以重新启动
    //while (UCB1CTL1和UCTXSTT);//wait for start to be set which will be a TXIFG interrupt flag.(正在设置启动,它将是TXIFG中断标志。
    __bis_sr_register(LPM0_bits | GIE);//输入带中断的LPM0
    
    //完成后停止
    UCB1CTLW0 |= UCTXSTP; // I2C停止条件
    UCB1IFG &=~UCTXIFG; //清除USI_B2 TX int标志
    
    
    返回0;
    
    
    }
    
    #pragma vector=Timer1_A0_vector
    __interrupt void Timer1_A0 (void){ // Timer0 A0中断服务例程
    
    //检查按钮状态
    IF ((P1IN和BIT0)== BIT0){
    button_timer = 0;
    其他{
    button_timer++;
    //如果按钮定时器>阈值开关状态
    IF (button_timer >= PWR_BUTTON阈值){
    CHANGE_PWR_STE_FLAG =1;
    }
    }
    
    //用于调试的闪存LED
    IF ((P8OUT & BIT0)== BIT0){
    P8OUT &=~BIT0;
    其他{
    P8OUT || BIT0;
    }
    
    //清除中断
    TA1CTL &=~BIT0;
    TA1CCTL0 &=~CCIFG;//清除中断
    //TA1CTL &=~(MC_1);//停止计时器_A
    __BIC_SR_REGISTER_ON_EXIT (LPM0_BITS+GIE);// ISR退出时清除LPM位
    }
    
    
    #if已定义(__TI_Compiler_version__)||已定义(__ISR_SYSTEMS _ICC__)
    #pragma向量= EUSCI_B1_Vector
    __interrupt void UI_B1_ISR(void_IAL_ISR_ELSE
    #)
    
    
    编译器#SCI_ELSE (void_US_I_IAL_SCI_)
    #endif
    {
    Switch(__偶 数_in_range(UCB1IV, USI_I2C_UCBIT9IFG))
    {
    案例USI_NONE: 中断; //矢量0:无中断
    案例USI_I2C_UCALIFG:中断; //矢量2:ALIFG
    案例USI_I2C_UCNACKIFG: //矢量4:NACKIFG
    UCB1CTLW0 |= UCTXSTT; //如果不确认,请重新发送启动
    中断;
    案例USI_I2C_UCSTIFG:
    UCB1CTLW0 |= UCTXSTP; // I2C停止条件
    __BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
    中断; //向量6:STTIFG
    案例USI_I2C_UCSTPIFG:中断; //矢量8:STPIFG
    案例USI_I2C_UCRXIFG3:中断; //矢量10:RXIFG3
    案例USI_I2C_UCTXIFG3:中断; //矢量12:TXIFG3
    案例USI_I2C_UCRXIFG2:中断; //矢量14:RXIFG2
    案例USI_I2C_UCTXIFG2:中断; //矢量16:TXIFG2
    案例USI_I2C_UCRXIFG1:中断; //矢量18:RXIFG1
    案例USI_I2C_UCTXIFG1:中断; //矢量20:TXIFG1
    案例USI_I2C_UCRXIFG0: //矢量22:RXIFG0
    UCB1IFG &=~UCRXIFG;//清除Rx IFG
    UCB1CTLW0 |= UCTXSTP; // I2C停止条件
    *RXData = UCB1RXBUF; //获取RX数据
    __BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
    中断;
    案例USI_I2C_UCTXIFG0: //矢量24:TXIFG0
    /*IF (TXByteCtr) //检查TX字节计数器
    {
    UCB1TXBUF = TXData[SlaveFlag];//加载TX缓冲区
    TXByteCtr // Decrement TX字节计数
    器}
    否则
    {
    UCB1CTLW0 |= UCTXSTP; // I2C停止条件
    UCB1IFG &=~UCTXIFG; //清除USI_B2 TX int标志
    __BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
    }*/
    __BIC_SR_REGISTER_ON_EXIT (LPM0_bits);//退出LPM0
    中断;
    案例USI_I2C_UCBCNTIFG:中断; //矢量26:BCNTIFG
    案例USI_I2C_UCCLTOIFG:中断; //向量28:时钟低超时
    案例USI_I2C_UCBIT9IFG:中断; //矢量30:第9位
    默认值:break;
    }
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    AH...启用自动停止生成并设置字节计数将其修复。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您必须先设置UCTXSTP,主机才能发送ACK。 如上所述,将其与UCTXSTT同时设置。