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.

TM4C123GH6PM 的I2C读取芯片寄存器值读出来的值是乱的

Other Parts Discussed in Thread: TM4C123GH6PM, TMP75

使用TM4C123GH6PM 的I2C读取TMP75温度寄存器的值,使用一个例程读取到的值是对的,但是它的函数操作顺序与123gh6pm的数据手册不同,我自己参照123gh6pm数据手册写了一个读寄存器函数,但发现读出来的值是乱的, 下面第一个函数是例程,第二个函数是我自己写的. 希望大家能帮忙看一下哪里出了问题,ps(其它配置计算等皆无问题,)

/********************************************
* 例程里的读寄存器函数,能正确读取温度值
* TMP_READ_DELAY是600
* *****************************************/
uint16_t
TMP75DataRead(void)
{
uint8_t i2cWriteBuffer;
uint32_t i2cReadBuffer[2];

uint16_t temp_value;

uint16_t i2c_read_delay;

i2cWriteBuffer = TMP_TEMP_REG;
i2cWriteBuffer &= 0x03;

// frame 1:
I2CMasterSlaveAddrSet(I2C1_BASE, TMP_I2C_ADDR, false);

// frame 2:
I2CMasterDataPut(I2C1_BASE, i2cWriteBuffer);
I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_SEND);

i2c_read_delay = TMP_READ_DELAY;
while (i2c_read_delay--);

// frame 3:
I2CMasterSlaveAddrSet(I2C1_BASE, TMP_I2C_ADDR, true);

I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);

// frame 4:
i2cReadBuffer[0] = I2CMasterDataGet(I2C1_BASE);

i2c_read_delay = TMP_READ_DELAY;
while (i2c_read_delay--)
;

I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);

// frame 5:
i2cReadBuffer[1] = I2CMasterDataGet(I2C1_BASE);

I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

temp_value = (i2cReadBuffer[0] << 8) | i2cReadBuffer[1];

return temp_value;
}

/*

*   这是我自己写的读寄存器函数 ,读出的值不对
* 入口参数: ui32I2CBase -- i2c基址, ui8SlaveAddr -- 从机地址,
* ui8RegAddr -- 寄存器地址
* 返 回 值: ui16RegData -- 读到的寄存器值 
*/
uint16_t I2CReadRegTwoByte(uint32_t ui32I2CBase, uint8_t ui8SlaAddr,
uint8_t ui8RegAddr)
{
uint8_t ui8WriteBuffer = 0; /* 写缓冲器 */
uint32_t ui32ReadBuffer = 0; /* 读缓冲器 */
uint16_t ui16RegData = 0;

// 查询BUSY位
while(I2CMasterBusy(ui32I2CBase))
{
;
}

// frame 1: 向从机地址I2CMSA寄存器写从机地址
ui8WriteBuffer = ui8SlaAddr;
I2CMasterSlaveAddrSet(ui32I2CBase, ui8WriteBuffer, false);

// frame 2: 向数据寄存器I2CMDR写数据
ui8WriteBuffer = ui8RegAddr;
I2CMasterDataPut(ui32I2CBase, ui8WriteBuffer);

// // 查询BUSBUSY位 (多主机模式) (单主机模式下或被忽略)
// while(I2CMasterBusBusy(ui32I2CBase))
// ;

// frame 3: 向控制/状态寄存器I2CMCS 写 "---0-011" 产生start 不产生stop
I2CMasterControl(ui32I2CBase, I2C_MASTER_CMD_BURST_SEND_START);

// 查询BUSY位
while(I2CMasterBusy(ui32I2CBase))
;

// 查询ERROR位
while(I2CMasterErr(ui32I2CBase) != I2C_MASTER_ERR_NONE)
{
// 若有错误 死在这里或进入中断处理程序
;
}

/******************传输后以重复开始序列进行的接收***************/

// frame 4: 向从机地址I2CMSA寄存器写从机地址
I2CMasterSlaveAddrSet(ui32I2CBase, ui8SlaAddr, true);

// // 查询BUSBUSY位 (多主机模式) (单主机模式下或被忽略)
// while(I2CMasterBusBusy(ui32I2CBase))
// ;

// frame 5: 向控制/状态寄存器I2CMCS 写 "---01011" 产生重复开始
I2CMasterControl(ui32I2CBase, I2C_MASTER_CMD_BURST_RECEIVE_START);

// 查询BUSY位
while(I2CMasterBusy(ui32I2CBase))
;

// 查询ERROR位
while(I2CMasterErr(ui32I2CBase) != I2C_MASTER_ERR_NONE)
{
// 若有错误 死在这里或进入中断处理程序
;
}

// frame 6: 从主机数据寄存器I2CMDR读第一个数据, 默认高8bit(MSB)
ui32ReadBuffer = I2CMasterDataGet(ui32I2CBase);
ui16RegData = ui32ReadBuffer << 8;

// frame 7: 向控制/状态寄存器I2CMCS 写 "---00101" 产生stop
I2CMasterControl(ui32I2CBase, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);

// 查询BUSY位
while(I2CMasterBusy(ui32I2CBase))
;

// 查询ERROR位
while(I2CMasterErr(ui32I2CBase) != I2C_MASTER_ERR_NONE)
{
// 若有错误 死在这里或进入中断处理程序
;
}

// frame 8: 从主机数据寄存器I2CMDR读第二个数据, 默认低8bit(LSB)
ui32ReadBuffer = I2CMasterDataGet(ui32I2CBase);

ui16RegData |= ui32ReadBuffer;

return ui16RegData;
}

这是芯片读时序图

  • 这是数据手册上的流程图

  • 仔细对比了下,发现基本操作都是一样的。你出现寄存器的值乱是什么意思呢?直接看输出读到的值是否和实际一致?怀疑你数据处理的时候出错了。

  • 这是读取寄存器之后处理数据的函数,其他的都不变,只把里面的读寄存器的函数换了一下读出来的值就不对了,用第一个TMP75DataRead()的话读出的温度就是对的,

    换成我写的I2CReadRegTwoByte(I2C1_BASE, TMP_I2C_ADDR,TMP_TEMP_REG&0x03)温度就不对了,

    float
    temp_read(void)
    {
    volatile float temp_degree;
    uint16_t temp_value = 0;

    temp_value = TMP75DataRead();

    //temp_value = I2CReadRegTwoByte(I2C1_BASE, TMP_I2C_ADDR,TMP_TEMP_REG&0x03);

    temp_degree = (uint8_t)temp_value +
    ((float) ( ( temp_value ) >> 12 ) ) * 0.0625 ;//*0.0625

    return temp_degree;
    }

    这是串口打印出来的我的函数读出的错误的温度值

  • 这是读取寄存器之后处理数据的函数,其他的都不变,只把里面的读寄存器的函数换了一下读出来的值就不对了,用第一个TMP75DataRead()的话读出的温度就是对的,

    换成我写的I2CReadRegTwoByte(I2C1_BASE, TMP_I2C_ADDR,TMP_TEMP_REG&0x03)温度就不对了,

    float
    temp_read(void)
    {
    volatile float temp_degree;
    uint16_t temp_value = 0;

    temp_value = TMP75DataRead();

    //temp_value = I2CReadRegTwoByte(I2C1_BASE, TMP_I2C_ADDR,TMP_TEMP_REG&0x03);

    temp_degree = (uint8_t)temp_value +
    ((float) ( ( temp_value ) >> 12 ) ) * 0.0625 ;//*0.0625

    return temp_degree;
    }

    这是串口打印出来的我的函数读出的错误的温度值

  • 问题暂时解决了,我把我自己写的函数里面的高低位组合互换了一下,发现结果正确了,但是问题来了,这样的话理论上说例程里的高地位组合和我的高地位就完全反了,但是同样的数据处理得到的结果却是一样的,所以我分析觉得例程里读取寄存器值应该是读取了三个字节,第一次空读了BYTE1,第二次读了一个字节BYTE2给了data[0],第三次又读了一个字节,此时芯片给的数据是再次重复,也就是说第三次读的还是BYTE1给了data[1],因此得到的结果与我读到的结果是高地位相反的,同样的数据处理得到的值就是错的.不知道分析的对不对,大家觉得应该问题应该出在什么方面?

  • 数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位