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-EXP430FR2355:I2C 无法读取多个完整字节

Guru**** 2577385 points
Other Parts Discussed in Thread: MSP430FR2355

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/939323/msp-exp430fr2355-i2c-cannot-read-more-than-one-complete-byte

器件型号:MSP-EXP430FR2355
主题中讨论的其他器件:MSP430FR2355

您好!

在 I2C 传输中、我似乎无法读取多个完整字节。 我使用的是一个主器件和一个从器件。 MSP430FR2355是主器件、而 Maxim 的 DS1307实时时钟是从器件。

如何正确读取多个字节? 我有什么问题吗?

DS1307的数据表: cdn.sparkfun.com/.../DS1307.pdf

读取1个字节

这是读取一个字节时发生的情况(看起来是正确的):

图1:

以下是读取数据后的存储器转储: 

(mspdebug) MD 0x0540 00540:C0 0f 08 00 00 08 00 01 00 00 00 00 00 00 |.......... | 00550:00 00 00 00 00 00 00 00 00 00 00 00 68 00 ff 03 | H..| 00560:68 00 00 00 00 00 00 00 00 00 00 61 00 08 40 00 |小时 A..@ 00570:FF 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f |???????????| (mspdebug) MD 0x056C 0056c:08 40 00 00 ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f |@…………………………………………………………………………………………… 0057c:FF 3f ff 3f 01 00 03 00 00 00 00 00 00 00 00 00 00 00 |..?.......... | 0058c:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.......... | 0059c:02 00 00 00 00 ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ?????????|

读取2个字节

当我读取两个字节时、数据线在第三个帧的第7个字节(要读取的第二个字节)之后挂起低电平:

图2:

它在大约15ms 内保持低电平:

图3:

这些是尝试读取两个字节后的内存转储:

(mspdebug) MD 0x0540
00540:C0 0f 08 00 00 08 00 00 02 00 10 00 00 00 |.......... |
00550:00 00 00 00 00 00 00 00 00 00 00 00 68 00 ff 03 | H..|
00560:68 00 00 00 00 00 00 00 00 00 00 61 00 08 40 00 |小时 A..@
00570:FF 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f |???????????|
(mspdebug) MD 0x056C
0056c:08 40 00 00 ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f |@……………………………………………………………………………………………
0057c:FF 3f ff 3f 01 00 03 00 00 00 00 00 00 00 00 00 00 00 |..?.......... |
0058c:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.......... |
0059c:02 00 00 00 00 ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ff 3f ?????????| 

读取5个字节

当尝试读取5个字节时、SDA 线路挂起低电平、这与读取2个字节时类似:

图4:

但是、在 SDA 和 SCL 再次释放之前、似乎有人尝试在130ms 的时间范围内再次开始传输:

图5:

代码

这是我读取1个字节的代码。 读取2个字节和读取5个字节只是由于 NNBytes = 2和 NNBytes = 5而有所不同。

#include 
#include 

void Init_gpio();
const int NNBytes = 1;
volatile uint8_t RXData;

int main (void)
{
WDTCTL = WDTPW | WDTHOLD;

//配置 GPIO */
Init_gpio ();

PM5CTL0 &&=~


~LOCKLPM5;//将 P2.3配置为输入开关以发送 I2C;

= P2IT3 |= 3 | BITS= 3 | BIT23;= BIT23;= BIT3 | BIT23;= BIT23;= BIT23;= BIT23;= BIT23;= BIT23;= BIT23;=

P2IFG = 0;
P2IE |= BIT3;

//配置 I2C */
P1OUT &=~BIT0; //清除 P1.0输出锁存
器 P6OUT &=~BIT6; //清除 P6.6输出锁存
器 P1DIR |= BIT0; //对于 LED
P6DIR |= BIT6; //对于 LED
P1SEL0 |= BIT2 | BIT3; // I2C 引脚:SDA | SCL

//为 I2C 模式配置 USCI_B0
UCB0CTLW0 |= UCSWRST; //软件复位使能
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;// I2C 模式、主控模式、SYNC
UCB0CTLW1 |= UCASTP_2; //生成自动停止
//到达 UCB0TBCNT 后
UCB0BRW = 0x0008; //波特率= SMCLK / 8
UCB0TBCNT = NNBytes; //要接收的字节数
UCB0I2CSA = 0x0068; //从地址
UCB0CTL1 &=~UCSWRST;
UCB0IE |= UCRXIE | UCBCNTIE;

__bis_SR_register (LPM0_bits|GIE);//输入 LPM0,带中断

}

#if defined (__TI_COMPIAR VERSION_VERSION__);__bis_void
PORT_2 (#_IAR COMPONENTS_EXTER_NOT_VERSIONENT_




)(#_INTER_NOTI_NOTI_NOTIF_INSION_NOT_INTRIBU_INSION_IN_INTRIBU_NOT_IN_INTRIBU_NOT_INTRIBU_INGS_)(#COMPIAR)(#COMPLETE_INTRIBU_INTR
#endif
{
//_delay_cycles (2000);
if (P2IFG 和 BIT3){
P1OUT |= BIT0; //在 P1.0上切换 LED
while (UCB0CTL1 & UCTXSTP); //确保发送了停止条件
//if (UCB0BCNT!=无核武器国家)
UCB0CTL1 |= UCTXSTT; // I2C 启动条件
UART_PUs ("start");
UART_putc (0x0A);//新行
P2IFG &=~BIT3;
}


#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = USCI_B0_Vector
__interrupt void USCIB0_ISR (void)
#Elif defined (__GSCSIR__)
#_attribute_(UIB0_) NOT_ERROR

(UIB0 COMPONIE)(void)(UIB0_COMPONIE) NOT_ERROR (UIB0_COMPONENT!
#endif
{
switch (__even_in_range (UCB0IV、USCI_I2C_UCBIT9IFG))
}
USCI_NONE 案例:中断; //向量0:无中断
USCI_I2C_UCALIFG 案例:中断; //向量2:ALIFG
USCI_I2C_UCNACKIFG 案例: //向量4:NACKIFG
UCB0CTL1 |= UCTXSTT; // I2C 启动条件
中断;
案例 USCI_I2C_UCSTTIFG:中断; //向量6:STTIFG
案例 USCI_I2C_UCSTPIFG:中断; //向量8:STPIFG
USCI_I2C_UCRXIFG3案例:中断; //向量10:RXIFG3
USCI_I2C_UCTXIFG3案例:中断; //向量14:TXIFG3
USCI_I2C_UCRXIFG2案例:中断; //向量16:RXIFG2
USCI_I2C_UCTXIFG2案例:中断; //向量18:TXIFG2
USCI_I2C_UCRXIFG1案例:中断; //向量20:RXIFG1
USCI_I2C_UCTXIFG1案例:中断; //向量22:TXIFG1
USCI_I2C_UCRXIFG0案例: //向量24:RXIFG0
RXData = UCB0RXBUF; //获取 RX 数据
//_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
中断;
案例 USCI_I2C_UCTXIFG0:中断; //向量26:TXIFG0
USCI_I2C_UCBCNTIFG 案例: //向量28:BCNTIFG
P1OUT ^= BIT0; //在 P1.0上切换 LED
中断;
USCI_I2C_UCCLTOIFG 案例:中断; //向量30:时钟低电平超时
USCI_I2C_UCBIT9IFG 案例:中断; //向量32:第9位
默认值:break;
}
}

void Init_GPIO()
{
P1DIR = 0xFF;P2DIR = 0xFF;
P1REN = 0xFF;P2REN = 0xFF;
P1OUT = 0x00; P2OUT = 0x00;
}

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

    我看到的是启动 I2C 系统以接收数据(UCTR 复位)、但从器件地址指示发送。 (LSB = 0)

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

    您是指特定的图吗? (我编辑了原始帖子、在每个图的上方添加了图标签。)

    或者您是指代码中的第39行吗? UCB0I2CSA = 0x0068; // Slave address

    从机地址为1101000、即0x68。 我的理解是、如果 UCTR 为0、eUSCI 模块将自动将1附加到要接收的 LSB。 或者、UCB0I2CSa=0xD1=11010001? 我没有明确地将 UCTR 设置为低电平、因为它在加电时默认为低电平。 在我看来、即使数据全部为0、图1在读取1个字节时似乎是正确的。 图1中的传输在读取1个字节后以 NACK 和 Stop 命令结束。

    但是、在图2中、发送相同地址时、LSB = 1进行读取、但只读取15位、SDA 和 SCL 保持低电平。 (即第二个字的第8个时钟周期不会变为高电平并保持低电平。 SCL 的最后一个高电平是第二个字的第7位。)

    读取1个字节图1:

    尝试读取2个字节图2:

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

    您好、Gary、

    您是否在 http://dev.ti.com/tirex/explore/node?node=AG0ne77m6uNB3UfuU6Ea5g__IOGqZri__LATEST 上查看过 I2C 代码示例

    Srinivas

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

    Srinivas、

    我尚未使用 driverlib.h 库。 我的代码基于来自此链接 MSP430FR235x、MSP430FR215x 代码示例(修订版 D)的 msp430fr235x_euscib0_i2c_10.c

    此代码实现了与您链接的代码相同的功能、无需使用 driverlib.h 我粘贴了下面的原始示例代码。

    我正在运行的代码是下面列出的代码的修改版本、它列在该线程的第一个帖子中。 我的代码和以下代码之间的主要修改如下:

    • 进入 LPM0而不发送 I2C START 命令
    • 按下按钮发送 I2C START 命令(P2.3)
    • I2C ISR 完成后、我的代码返回 LPM0而不是退出

    msp430fr235x_euscib0_IwC_10.c 代码示例

    /*-版权所有-、BSD_EX
    *版权所有(c) 2016、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *
    ***
    *
    * MSP430代码示例免责声明
    *
    * MSP430代码示例是自包含的低级程序
    ,通常*以
    高度*简明的方式演示单个外设功能或器件功能。 为此、代码可能依赖于器件的加电默认
    值*寄存器值和时钟配置等设置、
    并且在组合多个示例中的代码时必须*小心以避免潜在的副作用
    *。 另请参阅 www.ti.com/grace 了解 GUI、并参阅 www.ti.com/msp430ware
    *了解外设配置的 API 函数库方法。
    *
    *--/版权--*
    //*********
    // MSP430FR235x 演示- eUSCI_B0 I2C 主设备 RX 多个来自 MSP430从设备的字节
    //
    //说明:此演示通过 I2C 总线连接两个 MSP430。 主
    器件//从从器件读取5个字节。 这是主代码。 从器件
    //发送器的数据从0开始,并随每次传输递增。
    // USCI_B0 RX 中断被用来知道何时接收到新数据。
    // ACLK =默认 REFO ~32768Hz、MCLK = SMCLK = BRCLK = DCODIV ~1MHz。
    ////
    ***** 与"msp430fr235x_euscib0_i2c_11.c"**//
    
    /|\/|\
    // MSP430FR2355 10k 10k MSP430FR2355
    // 从器件 || 主器件
    // -------- |||---
    // | P1.2/UCB0SDA|-|--|-|-|P1.2/UCB0SDA |
    // | || | |
    // | || | |
    // | P1.3/UCB.S.|<-|--- 高于|P1.3/UCB.S. |
    // | | | P1.0|->LED
    //
    // Cash Hao
    // Texas Instruments Inc.
    // 2016年11月
    //使用 IAR 嵌入式工作平台 v6.50.0和 Code Composer Studio v6.2.0构建
    //*********
    #include 
    
    volatile unsigned char RXData;
    
    int main (void)
    {
    WDTCTL = WDTPW | WDTHOLD;
    
    //配置 GPIO
    P1OUT &=~BIT0; //清除 P1.0输出锁定
    P1DIR |= BIT0; //表示 LED
    P1SEL0 |= BIT2 | BIT3; // I2C 引脚
    
    //禁用 GPIO 上电默认高阻抗模式以激活
    //先前配置的端口设置
    PM5CTL0 &=~LOCKLPM5;
    
    //将 USCI_B0配置为 I2C 模式
    UCB0CTLW0 |= UCSWRST; //软件复位被启用
    UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;// I2C 模式、主控模式、同步
    UCB0CTLW1 |= UCASTP_2; //生成自动停止
    //到达 UCB0TBCNT 后
    UCB0BRW = 0x0008; //波特率= SMCLK /8
    UCB0TBCNT = 0x0005; //要接收的字节数
    UCB0I2CSA = 0x0048; //从器件地址
    UCB0CTL1 &=~UCSWRST;
    UCB0IE |= UCRXIE | UCNACKIE | UCBCNTIE;
    
    while (1)
    {
    _DELAY_CYCLES (2000);
    while (UCB0CTL1 & UCTXSTP); //确保发送了停止条件
    UCB0CTL1 |= UCTXSTT; // I2C 启动条件
    
    _bis_SR_register (LPM0_bits|GIE);//输入 LPM0、带中断
    }
    }
    
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
    #pragma vector = USCI_B0_vector
    __interrupt void USCIB0_ISR (void)
    #elif defined (__GCUN__)
    void __attribute__((interrupt (USCI_B0_vector)#interrupt
    
    ) USCIB0_ISR (void)(void USCIB0!)编译器错误!
    #endif
    {
    switch (__even_in_range (UCB0IV、USCI_I2C_UCBIT9IFG))
    }
    USCI_NONE 案例:中断; //向量0:无中断
    USCI_I2C_UCALIFG 案例:中断; //向量2:ALIFG
    USCI_I2C_UCNACKIFG 案例: //向量4:NACKIFG
    UCB0CTL1 |= UCTXSTT; // I2C 启动条件
    中断;
    案例 USCI_I2C_UCSTTIFG:中断; //向量6:STTIFG
    案例 USCI_I2C_UCSTPIFG:中断; //向量8:STPIFG
    USCI_I2C_UCRXIFG3案例:中断; //向量10:RXIFG3
    USCI_I2C_UCTXIFG3案例:中断; //向量14:TXIFG3
    USCI_I2C_UCRXIFG2案例:中断; //向量16:RXIFG2
    USCI_I2C_UCTXIFG2案例:中断; //向量18:TXIFG2
    USCI_I2C_UCRXIFG1案例:中断; //向量20:RXIFG1
    USCI_I2C_UCTXIFG1案例:中断; //向量22:TXIFG1
    USCI_I2C_UCRXIFG0案例: //向量24:RXIFG0
    RXData = UCB0RXBUF; //获取 RX 数据
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
    中断;
    案例 USCI_I2C_UCTXIFG0:中断; //向量26:TXIFG0
    USCI_I2C_UCBCNTIFG 案例: //向量28:BCNTIFG
    P1OUT ^= BIT0; //在 P1.0上切换 LED
    中断;
    USCI_I2C_UCCLTOIFG 案例:中断; //向量30:时钟低电平超时
    USCI_I2C_UCBIT9IFG 案例:中断; //向量32:第9位
    默认值:中断;
    }
    }
    

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

    我已经回到了原始示例代码、它似乎可以正常工作。

    使用按钮来中断按钮有什么作用?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
     >   Uart_puts("START");
     >   uart_putc(0x0A); // new line

    What do these functions do exactly? I don't see any UART setup, so if one of them was e.g. spinning waiting for TXIFG it would never return.

    在主接收器模式下、I2C 单元将继续并在不询问的情况下读取第一个字节、然后停止等待您读取 RXBUF、如果您仍然停留在端口 ISR 中、则不会读取 RXBUF。

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

    啊,是的! 我发布的代码不完整、并且有一些 UART 设置。 这两个函数使用 UART 发送字符串和字符。

    我认为您是对的;我删除了这些 UART 线、按下按钮后可以读取5个字节。 因此,这就是 ISR 应该尽可能短;P 的原因