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.

[参考译文] MSP430G2553:使用 I2C 连接加速计和气体传感器以及 UART 以查看值

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1376212/msp430g2553-use-i2c-to-interface-accelerometer-and-gas-sensors-and-uart-to-see-the-values

器件型号:MSP430G2553
主题中讨论的其他器件:MSP430FR2433

工具与软件:

大家好!

我要将 MSP 与 MPU-6050和 CCS811气体传感器进行连接、想通过 UART 查看相关值。

为此、我编码了两个函数、一个将整数值转换为字符串、另一个使用 UART 模块打印;在 main 函数中、我这样做:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while (1)
{
acc_comm();
//int_to_string(xAccel, num);
//uart_puts(num);
//int_to_string(yAccel, num);
//uart_puts(num);
//int_to_string(zAccel, num);
//uart_puts(num);
gases_comm();
//int_to_string(co2Lvl, num);
//uart_puts(num);
//int_to_string(tvocLvl, num);
//uart_puts(num);
// do something with the data
__delay_cycles(500000);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

当我取消注释函数调用时、通信失败。

我想知道导致此问题发生的原因。 我想 I2C 线路不能空闲、但没有这方面的确认;你们的任何帮助都会非常感谢。

为了便于参考、我将两个函数代码保留在此处:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void int_to_string(int num, unsigned char *str)
{
unsigned char i = 0, j = 0;
char aux[5];
do
{
aux[i++] = num % 10 + '0';
num /= 10;
}
while(num > 0);
while(i--)
{
str[j++] = aux[i];
}
str[j] = '\0';
}
void uart_puts(unsigned char *str)
{
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

此外、I2C 和 UART 的配置代码与 TI 开发人员专区中的示例相同。

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

    通信以何种方式失败? (暂停? NACK? 无效数据?) 您改编/采用了哪个 TI 示例? (我记得有几个。)

    如何声明"num"(在 main 中)? 是否可能发生缓冲区溢出?

    CCS811寄存器抽象有一点不常见;我想知道其中是否有某些临界情况。

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

    您好!

    应用这些函数时、似乎未进行通信。

    下图显示了逻辑分析仪输出:

    至于使用的示例、对于 UART、我只使用9600波特和1MHz 的配置、但不使用 ISR;对于 I2C、最好共享代码:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //*********************************************************************************************
    void i2cInit(void)
    {
    // set up I2C pins
    P1SEL |= BIT6 | BIT7; // Assign I2C pins to USCI_B0
    P1SEL2|= BIT6 | BIT7; // Assign I2C pins to USCI_B0
    // set up I2C module
    UCB0CTL1 |= UCSWRST; // Enable SW reset
    UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC; // I2C Master, synchronous mode
    UCB0CTL1 = UCSSEL_2 | UCSWRST; // Use SMCLK, keep SW reset
    UCB0BR0 = 10; // fSCL = SMCLK/10 = ~100kHz
    UCB0BR1 = 0;
    UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
    IE2 |= UCB0RXIE | UCB0TXIE;
    }
    //*********************************************************************************************
    void i2cWrite(unsigned char address)
    {
    IFG2 &= ~(UCB0TXIFG + UCB0RXIFG); // Clear pending interrupts
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     

    这些函数和 ISR 适用于这两个传感器、只需要切换地址。

    数组 num 声明为无符号字符;关于 缓冲区溢出、这是一个好问题。

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

    如果您在调试器中暂停、程序在哪里执行? 在第一个事务之后添加代码会导致第一个事务失败、这似乎很奇怪。

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

    您好!

    我使用 platformIO 进行开发、但我不能使用调试器、尽管按照提供的文档进行操作。

    CCS Studio 在 Linux 上不适用于我的 MCU、我在这里的一些线程中确认这是由于微控制器淘汰造成的。

    我再次执行代码以验证一次观察结果并猜测是什么? 它正在工作(无法解释)!

    但是、分隔传感器读数的3对转换和打印相加的延迟为10毫秒。 这可能会导致通信失败?

    如果没有调试器、这就很难实现。

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

    我不熟悉 platformIO,但由于它指的是一个"框架",我想知道它是否会造成一些堆栈大小的成本。 G2553中相对较小的 SRAM 可使平衡堆栈大小变得棘手。

    我在使用 CCS 12.6.0与 G2553配合使用时没有遇到问题、不过这是在 Windows 上使用的。 platformIO 还声称能够使用 Launchpad (板载调试接口)进行调试、但可能是"还不是全部使用"?

    也就是说、如果您受困于(我们过去所调用的)"printf 调试"、我会先绕过"uart_puts ("Step 1\r\m")"等调用来看看您能实现多远。 uart_puts()具有同步的优点、只需要很少的栈。 TI 编译器将常量字符串放置在闪存中、因此不会影响 SRAM。

    如何在 main 中声明"num"? 我知道它是"unsigned char num[ ];"。 的值 可能是一个线索。

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

    是的,文档说,所以,但我不知道我是否有一些错误的步骤,但遵循参考和添加解决方案的错误记录在 foruns 是不够的。

    我这样声明数组:

    Fullscreen
    1
    unsigned char num[] = {'0','0','0','0','0','\0'};
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    两个传感器都具有相关的数据、长度为16位、因此我认为一个包含5个位置的阵列就足够了。

    现在、我正在研究一些数据的奇怪而错误的输出、 执行似乎是稳定的。

    我将介绍一种使用 Windows 操作系统来使用 CCS 的方法、并研究可能的堆栈大小成本和缓冲区溢出。 您是否认为通信失败 可能是由内存问题引起的?

    顺便说一下、感谢您到目前为止的帮助。

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

    我没有您的设备、也没有您的开发工具(或您的整个源代码)、因此我只能做一些一般性的陈述:

    1) 1)如果您在 I2C 上从未看到任何活动、则第一个猜测是您的程序未在运行(正在运行)。

    2)堆栈或缓冲区溢出会产生不可预测的结果、其中一个可能未运行(在未初始化的存储器中旋转、反复非常快速地复位、卡在 LPM 中)。

    3) G2553上的 SRAM 相当有限。

    因此、我想知道程序认为它在做什么。 如果您有调试器、您可以暂停并查看。 否则,一组 UART_PUT()进度指示器会有所帮助。

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

    您好! 很抱歉耽误你的时间。

    尝试在 Windows 上下载 CCS 12.7、但仍然无法使用 MCU 的调试器。

    现在我使用 MSP430FR2433更改了目标、不知道该线程是否仍然适合、或者我必须创建另一个线程。

    我会将使用的代码迁移到新的 MCU、现在我只对 I2C 接口进行编码、以便与加速计进行通信、而且使用在 Linux 中安装的 CCS 调试器、并验证 UCBBUSY 是否在数据采集的第二次迭代中设置。

    我已经输出了10k 个电阻器并检查了引脚配置、 如此处所述

    以下是 I2C 的配置:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * Configuration of I2C module
    */
    void i2c_conf(void)
    {
    // I2C pins configuration
    P1SEL0 |= BIT2 | BIT3;
    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
    // Configure USCI_B0 for I2C mode
    UCB0CTLW0 |= UCSWRST; // Software reset enabled
    UCB0CTLW0 |= UCMODE_3 | UCMST; // I2C mode, Master mode
    UCB0CTLW0 |= UCSSEL__SMCLK | UCSYNC; // Use SMCLK as clock source, sync
    UCB0CTLW1 |= UCASTP_2; // Automatic stop generated by
    // reaching data acquisition boundary
    UCB0BRW = 0x000A; // baudrate = SMCLK / 10 = 100 kHz
    UCB0CTL1 &= ~UCSWRST; // Disable SW reset
    UCB0IE |= UCTXIE | UCRXIE | UCBCNTIE; // Enable Tx, RX, and count interruptions
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    这是 ISR;除了 UCB0TBCNT 接收 byteCtr 之外、写入和读取函数保持不变

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * UCB0 ISR
    */
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
    {
    case USCI_I2C_UCRXIFG0:
    RX_ByteCtr--;
    if(RX_ByteCtr)
    {
    RX_Data[RX_ByteCtr] = UCB0RXBUF; // Store RX'd byte
    }
    break;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

    1) 1)请记住、仅当 I2C 单元处于复位状态(UCSWRST=1)时才能更改 UCB0TBCNT。 我看不到您在 i2c_conf()中设置它。

    2) 2)(a)在最后一个字节之后停止条件被(自动)发出之前、UCBCNTIFG 被置位、(b)停止需要一段时间、(c)在一个停止等待期间、eUSCI 对发出一个启动十分敏感。

    这就是为什么您会在新操作的设置中经常看到这一点的原因:

    > while (UCB0CTLW0 & UCTXSTP)/* empty*/;  //等待之前的操作(停止)完成

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

    我删除了 UCB0TBCNT 中断使能和处理。 现在在 UCB0CTLW0 |= UCTR | UCTXSTT 后置位 UCBBUSY 和 UCSCLLOW 时、我遇到了问题。 已尝试通过8位版本(UCB0CTL1)进行访问、但遇到了同样的问题。

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

    是否围绕设置 UCB0TBCNT 复位 I2C (UCSWRST=1、然后=0)? 如果不是这样、可能是 UCB0TBCNT=0、我不是很确定 UCASTP=2对这一点做了什么(我还没有尝试过)。 请记住、复位 I2C 会设置 UCB0IE=0、因此必须将它们放回。

    是否正在等待 UCTXSTP 清除后再开始新的操作(UCTXSTT)?

    几周前、我为 FR2433编写了代码、以便与 MPU-6050通信[现在其他人拥有]、我不记得该器件有任何特别之处。 可能有助于您发布 I2C 读取/写入函数。

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

    当然、这里是:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * Write function
    */
    void i2c_wr(unsigned char addr)
    {
    UCB0CTL1 |= UCSWRST;
    UCB0I2CSA = addr; // Slave address
    UCB0TBCNT = TX_ByteCtr;
    UCB0CTL1 &= ~UCSWRST;
    UCB0IE |= UCTXIE | UCRXIE; // Enable Tx and RX interruptions
    while(UCB0CTL1 & UCTXSTP); // Ensure stop condition sent
    UCB0CTL1 |= UCTR; // Transmitter mode
    UCB0CTL1 |= UCTXSTT; // and send START condition
    __bis_SR_register(LPM0_bits|GIE); // Enter LPM0 w/ interrupt
    }
    /**
    * Read function
    */
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    UCBBUSY 和 UCSCLLOW 仍被置位。 由于在调试器中 UCTXSTT 已清除、所以发送了 START (可能吗?)。

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

    这看起来是合理的;我建议移动 UCTXSTP 检查、使其先于复位(UCSWRST)、因为复位可能会干扰(持续)停止。

    回顾 ISR、这看起来是个1次关断:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    case USCI_I2C_UCRXIFG0:
    RX_ByteCtr--;
    if(RX_ByteCtr)
    {
    RX_Data[RX_ByteCtr] = UCB0RXBUF; // Store RX'd byte
    }
    break;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    例如、如果您以 RxByteCtr=1开始、那么它根本不会读取 UCB0RXBUF。 对 RXBUF 的读取会绑定到流量控制中、因此可能会挂起总线。 您可能应该在 if ()块内移动递减。

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

    以下是更新后的函数和 ISR:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * Write function
    */
    void i2c_wr(unsigned char addr)
    {
    while(UCB0CTL1 & UCTXSTP); // Ensure stop condition sent
    UCB0CTL1 |= UCSWRST;
    UCB0I2CSA = addr; // Slave address
    UCB0TBCNT = TX_ByteCtr;
    UCB0CTL1 &= ~UCSWRST;
    UCB0IE |= UCTXIE | UCRXIE | UCBCNTIE; // Enable Tx and RX interruptions
    UCB0CTL1 |= UCTR; // Transmitter mode
    UCB0CTL1 |= UCTXSTT; // and send START condition
    __bis_SR_register(LPM0_bits|GIE); // Enter LPM0 w/ interrupt
    }
    /**
    * Read function
    */
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    从而得出:

    数据线保持高电平、但正在生成时钟。

    再试一次、得到以下结果:

    在第三次尝试中、我收到了 accel 值。

    这太奇怪了...

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

    顶部的配置看起来特别奇怪、因为没有启动/停止条件、但 SCL 看起来很合理。

    是否复位 MPU-6050 (寄存器0x6B)? 如果是、您是否在等待器件启动? 数据表要求为30ms、但我记得我给它的时间大约为100ms。  

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

    我在传感器唤醒块中添加了一个延迟。 现在,它似乎工作正常,谢谢你先生。

    现在、我将添加气体传感器寄存器和 UART。 我认为最好创建另一个线程。

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

    我很高兴您启动了该工具。 我希望下一款器件会更简单。

    CCS811唯一与众不同的地方在于、它具有多字节寄存器("邮箱")、这些寄存器不是寄存器空间中的连续字节、这意味着您不能在单个事务中读取多个寄存器(或许这不重要)。

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

    您好!

    我创建了另一个线程来处理这个主题,因为我认为它与最初的 问题不同。

    单击 此处 访问。

    再次感谢您到目前为止的帮助!