繁体   English   中英

MSP430 I2C读取多字节通信问题

[英]MSP430 I2C read multiple bytes communication problem

我正在尝试使用 MSP430F249 的温度传感器(PCT2075)

为了获得温度,我从这个传感器获得了 2 个字节。

我从这个链接写了一个代码。

https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/589712?MSP430FR5969-Read-multiple-bytes-of-data-i2c-with-repeated-start-and-without-interrupts

我正在使用 MSP430F249。 所以我从这个链接修改了一个代码。

在此处输入图像描述 但是,我只得到了两个相同的值。 我认为它是 MSByte。

有什么方法可以从传感器获取 2 个字节。

在此处输入图像描述

我的代码在这里

void i2c_read_multi(uint8_t slv_addr, uint8_t reg_addr, uint8_t l, uint8_t *arr)
{
   uint8_t i;

   while(UCB0STAT & UCBBUSY);

   UCB0I2CSA = slv_addr;                   // set slave address

   UCB0CTL1 |= UCTR | UCTXSTT;            // transmitter mode and START condition.

   while(UCB0CTL1 & UCTXSTT);

   UCB0TXBUF = reg_addr;

   while(!(UCB0CTL1 & UCTXSTT));

   UCB0CTL1 &= ~UCTR;                     // receiver mode

   UCB0CTL1 |= UCTXSTT;                   // START condition

   while(UCB0CTL1 & UCTXSTT);             // make sure start has been cleared

   for (i = 0; i < l; i++) {

   while(!(IFG2 & UCB0RXIFG));

   if(i == l - 1){

       UCB0CTL1 |= UCTXSTP;           // STOP condition

   }

      arr[i] = UCB0RXBUF;

 }

   while(UCB0CTL1 & UCTXSTP);

}

有两个问题...

链接到代码假定端口只需要为每个 output 值读取一个字节。

但是,根据您显示的传感器文档,对于数组中的每个值output ,我们需要读取两个字节(一个用于 MSB,一个用于 LSB)。

而且,我们需要将这两个字节值合并为一个 16 位值。 请注意, arr现在是uint16_t而不是uint8_t 而且, l现在是 [16 位]样本的数量(与字节数相比)。 因此,可能需要相应地调整 this 的调用者。

此外,请注意,我们必须“忽略” lsb的低 5 位。 我们通过将 16 位值右移 5 位来做到这一点(例如val16 >>= 5 )。 我认为这是正确的方法。 或者,它可能只是val16 &= ~0x1F [不太可能]。 您可能需要进行一些实验。

这是重构的代码。

请注意,这假设数据以“大端”顺序到达[基于我的最佳猜测]。 如果它实际上是小端,则反转msb =lsb =语句。

此外,可能需要调整“STOP”条件代码的位置。 我不得不猜测它是否应该放在 LSB 读取或 MSB 读取之上。

我选择了 LSB——最后一个字节,因为它最接近链接的通用 i2c 读取的完成方式。 (ie) i2c 不知道或不关心相关设备的 MSB/LSB 多路复用。 它希望在最后一个字节之前停止 [不是16 位样本]。

void
i2c_read_multi(uint8_t slv_addr, uint8_t reg_addr, uint8_t l,
    uint16_t *arr)
{
    uint8_t i;
    uint8_t msb;
    uint8_t lsb;
    uint16_t val16;

    while (UCB0STAT & UCBBUSY);

    // set slave address
    UCB0I2CSA = slv_addr;

    // transmitter mode and START condition.
    UCB0CTL1 |= UCTR | UCTXSTT;

    while (UCB0CTL1 & UCTXSTT);

    UCB0TXBUF = reg_addr;

    while (!(UCB0CTL1 & UCTXSTT));

    // receiver mode
    UCB0CTL1 &= ~UCTR;

    // START condition
    UCB0CTL1 |= UCTXSTT;

    // make sure start has been cleared
    while (UCB0CTL1 & UCTXSTT);

    for (i = 0; i < l; i++) {
        while (!(IFG2 & UCB0RXIFG));
        msb = UCB0RXBUF;

        while (!(IFG2 & UCB0RXIFG));

        // STOP condition
        if (i == l - 1) {
            UCB0CTL1 |= UCTXSTP;
        }

        lsb = UCB0RXBUF;

        val16 = msb;
        val16 <<= 8;
        val16 |= lsb;

        // use only most 11 significant bits
        // NOTE: this _may_ not be the correct way to scale the data
        val16 >>= 5;

        arr[i] = val16;
    }

    while (UCB0CTL1 & UCTXSTP);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM