简体   繁体   English

MSP430 I2C读取多字节通信问题

[英]MSP430 I2C read multiple bytes communication problem

I'm trying to use a temperature sensor(PCT2075) by MSP430F249我正在尝试使用 MSP430F249 的温度传感器(PCT2075)

To get a temperature, I get a 2bytes from this sensor.为了获得温度,我从这个传感器获得了 2 个字节。

I wrote a code from this link.我从这个链接写了一个代码。

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

I'm using MSP430F249.我正在使用 MSP430F249。 so I modified a code from this link.所以我从这个链接修改了一个代码。

在此处输入图像描述 Howerver, I got just two same value.但是,我只得到了两个相同的值。 I think that it is MSByte.我认为它是 MSByte。

Is there any way to get 2bytes from sensor.有什么方法可以从传感器获取 2 个字节。

在此处输入图像描述

my code here我的代码在这里

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);

}

There are two issues...有两个问题...

The linked to code assumes that the port only needs to read one byte for each output value.链接到代码假定端口只需要为每个 output 值读取一个字节。

But, based on the sensor documentation you've shown, for each value output to the array, we need to read two bytes (one for MSB and one for LSB).但是,根据您显示的传感器文档,对于数组中的每个值output ,我们需要读取两个字节(一个用于 MSB,一个用于 LSB)。

And, we need to merge those two byte values into one 16 bit value.而且,我们需要将这两个字节值合并为一个 16 位值。 Note that arr is now uint16_t instead of uint8_t .请注意, arr现在是uint16_t而不是uint8_t And, l is now the number of [16 bit] samples (vs. number of bytes ).而且, l现在是 [16 位]样本的数量(与字节数相比)。 So, the caller of this may need to be adjusted accordingly.因此,可能需要相应地调整 this 的调用者。

Further, note that we have to "ignore" the lower 5 bits of lsb .此外,请注意,我们必须“忽略” lsb的低 5 位。 We do that by shifting the 16 bit value right by 5 bits (eg val16 >>= 5 ).我们通过将 16 位值右移 5 位来做到这一点(例如val16 >>= 5 )。 I assume that's the correct way to do it.我认为这是正确的方法。 Or, it could be just val16 &= ~0x1F [less likely].或者,它可能只是val16 &= ~0x1F [不太可能]。 You may have to experiment a bit.您可能需要进行一些实验。

Here's the refactored code.这是重构的代码。

Note that this assumes the data arrives in "big endian" order [based on my best guess].请注意,这假设数据以“大端”顺序到达[基于我的最佳猜测]。 If it's actually little endian, reverse the msb = and lsb = statements.如果它实际上是小端,则反转msb =lsb =语句。

Also, the placement of the "STOP" condition code may need to be adjusted.此外,可能需要调整“STOP”条件代码的位置。 I had to guess as to whether it should be placed above the LSB read or MSB read.我不得不猜测它是否应该放在 LSB 读取或 MSB 读取之上。

I chose LSB--the last byte because that's closest to how the linked general i2c read is done.我选择了 LSB——最后一个字节,因为它最接近链接的通用 i2c 读取的完成方式。 (ie) i2c doesn't know about or care about the MSB/LSB multiplexing of the device in question. (ie) i2c 不知道或不关心相关设备的 MSB/LSB 多路复用。 It wants the STOP just before the last byte [ not the 16 bit sample ].它希望在最后一个字节之前停止 [不是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