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.

[参考译文] MSP430F5438A:I2C 代码

Guru**** 2589280 points
Other Parts Discussed in Thread: MSP430F5438A, MSP430FR2311, HDC1080

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/758293/msp430f5438a-i2c-code

器件型号:MSP430F5438A
主题中讨论的其他器件: MSP430FR2311HDC1080

您好!

我正在尝试从那里找到 I2C 示例代码、我可以在那里了解如何针对我的目的对其进行自定义。 尝试与具有 I2C 协议的传感器通信。 我使用的是 MSP430F5438A 扩展板和 IDE Code Composer Studio。 以下是与传感器进行通信所需执行的任务:

需要配置传感器(在传感器的多个地址中、我必须写入不同的值、假设我在0x0E 寄存器中写入0x08、在0x0D 中写入0x01、依此类推)

2.从传感器读取原始数据(发送地址、我希望从中读取多个字节)。

我试图了解 MSP430软件中的寄存器级 I2C 代码。 我想知道其中有没有类似的东西?  

我感谢任何建议。 此外、如果任何寄存器级代码都不起作用、请帮助我找到类似类型的示例代码。  

谢谢。

RANA  

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

    你(们)好、Rana

    我们提供了有关 I2C 的系列代码示例、可指导您使用配置 MSP430的 I2C 模块。 您可以在 Resource Explorer 或 TI.com 上获取它

    有关如何读取或写入传感器寄存器的信息、您应该会在传感器数据表中看到 I2C 协议。

    此致

    Gary

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

    高您好、

    感谢您的回答。 我已经提到过、我介绍了寄存器级代码。 此外、我还阅读了数据表。 您提到的来源太宽泛。 您能否参考我可以遵循的具体示例以实现此目的?  

    谢谢、

    RANA。

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

    您使用的传感器是什么? 我将尝试为您找到一些类似的代码。

    此致
    Gary
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    高您好、
    我正在实施 BNO055。

    感谢你能抽出时间。

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

    你(们)好

    您可以参阅此示例、该示例使用 MSP430FR2311作为主器件来读取温度和湿度传感器 HDC1080。 演示代码提供了如何读取寄存器的值、如何将值写入寄存器以及感应数据。 我已随附了使用 Saleae 的本演示的 SCL 和 SDA 捕获。

    e2e.ti.com/.../msp430fr231x_5F00_HDC1080_5F00_Write_5F00_read.ce2e.ti.com/.../HDC1080_5F00_write_5F00_read.logicdata

    有用链接  

    HDC1080产品说明书

    Saleae GUI

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

    e2e.ti.com/.../BNO055_5F00_1.zipHello

    感谢您分享示例代码。 我从您的代码中得到了一些提示。 但我发现配置不同。 但无论如何、我尝试在 MSP430F5438A 中为自己编写代码。 我可以将值写入不同 的寄存器。 此外、我可以使用我的代码读取一个字节、例如、我在读取器件 ID 时获得了适当的值。 现在问题是突发读取。 我喜欢从地址0x08开始读取6个字节。 根据数据表、(BNO055)寄存器地址将自动增加。 我喜欢从地址连续获取数据、这就是将其放入 while 循环的原因。 但它不能正确返回数据(始终为零)。 我要附加代码和 Saleae 文件(BNO055_1正在读取6个字节、而 BNO055_2正在连续读取6个字节)。 您能告诉我突发读取有什么问题吗?

    #include 
    
    #include 
    
    
    void Clock_setup();//现在使用默认 SMCLK ~1MHz
    void I2C_setup_s1 ();//传感器1
    的 I2C 设置 void BNO055_setup_s1 (void);//传感器1配置设置
    unsigned I2C_receive_char (char reg_add);//从传感器
    void I2C_receive_s6 (void、int、char char)接收1个字节;//从传感器 void bart、char //接收来自传感器
    void I2C_Transmit _s1 (char reg_add、char data)的6个字节;//将数据传输到传感器
    
    char accbuffer[6];
    int x_s1;//传感器1
    int y_s1的 x 值;//传感器1
    的 y 值 int z_s1;//传感器1
    的 z 值 volatile unsigned char [5];
    
    void 串行(void)
    void init_serial (void)
    {
    P5SEL |= 0xC0; //对于 TX/RX- UCA1为5.6和5.7
    UCA1CTL1 |= UCSWRST;
    UCA1CTL1 |= UCSSEL_1; //32768Hz
    UCA1BR0=03; //波特率9600
    UCA1BR1 = 0x00;
    UCA1MCTL = 0x06; //调制 SX=3,FX=0
    UCA1CTL0 = 0x00;
    UCA1CTL1 &=~UCSWRST; //在操作模式
    
    中}
    
    void adc_value (int);
    void adc_value (int adc_Data)
    {
    volatile char x=3;
    伏特[3]=伏特[2]=伏特[1]=伏特[0]= 0x30;
    while (ADC_Data > 0)
    {
    伏特[x]=(ADC_Data%10)| 0x30;//分隔单位数字
    ADC_Data = ADC_Data/10; //剩余的数字比最后一个数字
    X-;
    }
    伏特[4]='\0';
    }
    
    void Send_Serial (void);
    void Send_Serial (void)
    {
    volatile char i=0;
    while (volt [i]!='\0')
    {
    UCA1TXBUF =伏[i];
    
    while (UCA1STAT 和 UCBUSY);
    i++;
    }
    UCA1TXBUF = 0x20; //空格
    while (UCA1STAT 和 UCBUSY);
    
    }
    
    void Send_Serial_1 (void);
    void Send_Serial_1 (void)
    {
    volatile char i=0;
    while (volt [i]!='\0')
    {
    UCA1TXBUF =伏[i];
    
    while (UCA1STAT 和 UCBUSY);
    i++;
    }
    UCA1TXBUF = 0x0a; //NL
    while (UCA1STAT 和 UCBUSY);
    UCA1TXBUF = 0x0d; //Enter
    while (UCA1STAT 和 UCBUSY);
    
    }
    
    void main(){
    WDTCTL = WDTPW + WDTHOLD;
    clock_setup();
    I2C_setup_s1 ();
    BNO055_setup_s1 ();
    //char add = I2C_receive_s1 (0x03);
    
    while (1){
    I2C_Receive_s6 (0x08、accbuffer、6);//从加速计读取6个字节的数据
    
    x_s1 =(accbuffer[1]<< 8)| accbuffer[0];
    ADC_Value (x_s1);
    SEND_Serial ();
    y_s1 =(accbuffer[3]<< 8)| accbuffer[2];
    ADC_Value (y_s1);
    SEND_Serial ();
    Z_s1 =(accbuffer[5]<< 8)| accbuffer[4];
    ADC_Value (z_s1);
    SEND_Serial_1 ();
    }
    返回0;
    }
    
    void Clock_setup(){
    P11DIR |= BIT0;//检查 ACLK、默认值为32768Hz
    P11SEL |= BIT0;//检查 ACLK、默认值为32768Hz
    P11DIR |= BIT1;//检查 MCLK、默认值为1.045MHz
    P11SEL |= BIT1;//检查 MCLK、默认值1.045MHz
    P11DIR |= BIT2;//检查 SMCLK、默认值为1.045MHz
    P11SEL |= BIT2;//检查 SMCLK,1.045MHz 默认
    值}
    
    void I2C_setup_s1 (){
    P3SEL |= BIT7; // P5.4 (UCB1_SCL)、P3.7 (UCB1_SDA)
    P5SEL |= BIT4;
    UCB1CTL1 |= UCSWRST; //复位使能
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; //主设备+ I2C 模式+同步
    UCB1CTL1 = UCSSEL_2 + UCSWRST; //使用 SMCLK +仍然复位
    UCB1BR0 = 4; //默认 SMCLK 1M/4 = 250kHz
    UCB1BR1 = 0; //
    UCB1I2CSA = 0x28; // BNO055地址0x28
    UCB1CTL1 &=~UCSWRST; //复位清零
    // UCB1IE |= UCTXIE + UCRXIE; //启用 TX 和 RX 中断
    }
    
    void BNO055_setup_s1 (void){
    I2C_Transmit _s1 (0x07、0x00);//页 ID
    I2C_Transmit _s1 (0x3E、0x00);//功率模式
    I2C_Transmit _s1 (0x3B、0x00);//单位选择 m/s2
    I2C_Transmit _s1 (0x41、0x24);//轴重映射默认值
    I2C_Transmit _s1 (0x42、0x00);//轴映射符号
    I2C_Transmit _s1 (0x3D、0x01);//操作模式=仅 acclr
    
    }
    
    
    char I2C_receive_s1 (char reg_add){
    char Rx_BYTE;
    UCB1CTL1 |= UCTR + UCTXSTT;
    UCB1TXBUF = REG_ADD;
    while (!(UCB1IFG & UCTXIFG)); //等待寄存器地址被发送
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    UCB1CTL1 |= UCTXSTT; //生成重新启动
    //UCB1I2CSA =从器件添加; //从地址
    UCB1CTL1 &=~μ H UCTR; //接收模式
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    RX_BYTE = UCB1RXBUF; //读取字节
    UCB1CTL1 |= UCTXSTP; //生成停止条件
    while (UCB1CTL1 & UCTXSTP); //等待停止条件被发送
    
    return rx_BYTE;
    }
    
    void I2C_receive_s6 (char start_add、char * buffer、unsigned int no_ofbyte){
    unsigned int i;
    //UCB1I2CSA =从器件添加; //从地址
    while (!(UCB1IFG & UCTXIFG)); //等待从器件地址被发送
    UCB1CTL1 |= UCTXSTT + UCTR; //生成起始条件+ I2C 发送(写入)
    UCB1TXBUF = START_ADD; //写入寄存器地址
    while (!(UCB1IFG & UCTXIFG)); //等待寄存器地址被发送
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    UCB1CTL1 |= UCTXSTT; //生成重新启动条件
    //UCB1I2CSA =从器件添加; //从地址
    UCB1CTL1 &=~ UCTR; //接收模式
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    //buffer[0]= UCB1RXBUF; //虚拟读取
    //while (!(UCB1IFG & UCRXIFG)); //等待字节完全被读取
    for (i=0;i 
    

     

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

    > x_s1 =(accbuffer[1]<< 8)| accbuffer[0];
    由于 accbuffer 是"char"、这将丢失 x_s1的高位字节(=0)。 尝试:
    > x_s1 =((unsigned) accbuffer[1]<< 8)|(unsigned) accbuffer[0];

    > for (i=0;<no_ofbyte-1;++i){)
    > Buffer[i]= UCB1RXBUF; //猝发读取
    > while (!(UCB1IFG & UCRXIFG)); //等待字节已被读取
    >}
    在 Rx 字节准备就绪前、第一次读取该字节。 这种事情有时会"意外"工作、但您不应依赖它。 尝试反转 while ()和赋值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    McKenney、您好!

    感谢您的建议。 因此、按照您所说的那样修改代码。 现在得到4个字节并在该 NAK 之后。 对可能的问题有什么看法? 连接是 SCL 和 SDA 的输出-

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    根据右下角的日志、您将在 NACK 之前收到5个字节。 这表明您过早地发出 Stop。

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

    您好!

    函数的当前代码如下所示:

    void I2C_receive_s6 (char start_add、char * buffer、unsigned int no_ofbyte){
    unsigned int i;
    //UCB1I2CSA =从器件添加; //从地址
    while (!(UCB1IFG & UCTXIFG)); //等待从器件地址被发送
    UCB1CTL1 |= UCTXSTT + UCTR; //生成起始条件+ I2C 发送(写入)
    UCB1TXBUF = START_ADD; //写入寄存器地址
    while (!(UCB1IFG & UCTXIFG)); //等待寄存器地址被发送
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    UCB1CTL1 |= UCTXSTT; //生成重新启动条件
    //UCB1I2CSA =从器件添加; //从地址
    UCB1CTL1 &=~ UCTR; //接收模式
    while (UCB1CTL1 & UCTXSTT); //等待启动条件被清除
    //buffer[0]= UCB1RXBUF; //虚拟读取
    //while (!(UCB1IFG & UCRXIFG)); //等待字节完全被读取
    for (i=0;i 
    

    现在、在这一点上、看起来我正在获取值。 我要在 e2e.ti.com/.../123.zip 上附加逻辑分析仪文件。 在几个字节为零后、它开始返回值。 但是、在尝试将值发送到 PC 时、我在 TeraTerm 中看不到任何内容。  如果您在 main()中看到我之前的代码,我尝试将数据发送到 PC,如下所示:

    x_s1 =(((unsigned char) accbuffer[1]<< 8)|(unsigned char) accbuffer[0]);
    ADC_Value (x_s1);
    SEND_Serial ();
    y_s1 =(((unsigned char) accbuffer[3]<<8)|(unsigned char) accbuffer[2]);
    ADC_Value (y_s1);
    SEND_Serial ();
    z_s1 =(((unsigned char) accbuffer[5]<< 8)|(unsigned char) accbuffer[4]);
    ADC_Value (z_s1);
    SEND_Serial_1 (); 

     转换中出现问题?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我不知道为什么您只获得5个字节。 我也没有您的设备。 我在您的代码中确实看到了一些"异常"的情况、但我无法将它们与您的症状联系起来:
    1) 1)您应该在设置 STT 之前适当地设置 UCTR
    2) 2)您应该在最后一个 Rx 字节到达时(在您退出 for ()循环后)发送 Stop。
    I2C 单元具有一些古咒特性、这些东西可能会在一段时间内起作用。 这是示例程序中的巨大价值。
    ----------------------------
    如果您在串行链路上根本看不到任何内容、则应检查连接。 我假设您从书中得到 MCTL 值。 您可能希望尝试在启动时发送固定字符串("BNO0055 Test"或某些此类)、以便找出症状。
    ----------------------------
    > x_s1 =(((unsigned char) accbuffer[1]<< 8)|(unsigned char) accbuffer[0]);
    这与以前有同样的缺陷。 尝试:
    >x_s1 =((unsigned) accbuffer[1]<< 8)|(unsigned) accbuffer[0];
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你(们)好

    感谢 Bruce 提供宝贵的建议。
    以下是我的一些建议
    您是否注意到 BNO055需要400ms 启动(在数据表第13页中)并具有开关时间限制(第21页)、您应该注意输出数据速率(第31页)。 这可能是您第一次读取0的原因。
    对于第二个问题、建议您单独测试 UART、您只需首先向 PC 发送一个字节、以查看其是否可以正常工作。

    此致
    Gary