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.

[参考译文] EK-TM4C123GXL:尝试使用 I2C 读取 BME280。

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/795530/ek-tm4c123gxl-trying-to-read-bme280-using-i2c

器件型号:EK-TM4C123GXL
主题中讨论的其他器件:TM4C123BOOSTXL-SENSORS

我最近购买了一个带有 BOOSTXL-SENSORS 传感器 Booster Pack 的 TM4C123 LaunchPad。 我正在尝试使用 Bosch API 的板载 BME280传感器。到目前为止、I2C 读取器件仅用于读取器件 ID、I2C 写入器件完全不起作用。 请帮帮我。

#include 
#include 
#include 
#include 
include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/secstt.mdio"







#include "dive_datase_trature.mdio"#include "dive.h_trategr_trature.mdio"#include "dio.mde2me.h"#include "dio.mdio.mdio_module"#include "dio.mde2me.h"#include "dio_transl_transl_date"#include "t_transl.mdeft voide"#include "t_transl.mdefinature.mdio.mde2me.h"#include "inategor.md.md.md.md.md.md.md


SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHz);
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
InitConsole();
UARTprintf ("UART OK \n");
InitI2C1();
UARTprintf ("I2C OK \n");
struct bme280_dev;
INT8_t rslt = BME280_OK;
dev.dev_id = 0x77;
dev.intf = BME280_I2C_INTF;
dev.read = user_i2c_read;
dev.write = user_i2c_write;
dev.delay_ms = USER_DELAY_ms;
rslt = bme280_init (&dev);
stream_sensor_data_normal_mode (&dev);
}

int8_t stream_sensor_data_normal_mode (struct bme280_dev *dev)
{
int8_t rslt;
uint8_t settings_SEL;
struct bme280_data comp_data;

/*建议的操作模式:室内导航*/
dev->settings.osr_h = BME280_oversings_1X;
dev->settings.osr_p = BME280_oversinging_16X;
dev->settings.osr_t = BME280_oversinging_2X;
dev->settings.filter = BME280_FILTER_COEFF_16;
dev->settings.STANDBY_TIME = BME280_STANDBY_TIME_62_5_MS;

SETTINGS_SEL = BME280_OSR_PRESS;
SETTINGS_SEL |= BME280_OSR_TEMP_SEL;
SETTINGS_SEL |= BME280_OSR_hum_SEL;
SETTINGS_SEL |= BME280_STANDBY_SEL;
SETTINGS_SEL |= BME280_FILTER_SEL;
rslt = bme280_set_sensor_settings (settings_SEL、dev);
rslt = bme280_set_sensor_mode (BME280_normal_mode、dev);

UARTprintf ("温度、压力、湿度"\r\n);
while (1){
传感器完成测量时的/*延迟*/
dev->delay_ms(1000);
rslt = bme280_get_sensor_data (BME280_all、&comp_data、dev);
print_sensor_data (&comp_data);
}

返回 rslt;
}

void print_sensor_data (struct bme280_data * comp_data)
{
#ifdef BME280_float_enable
UARTprintf ("%0.2f、%0.2f、%0.2f\r\n"、comp_data->temperature、comp_data->pressure、comp_data->humidity");
其他
UARTprintf ("%l、%l、%l\r\n"、comp_data->temperature、comp_data->pressure、comp_data->yumthure);
#endif
}



void InitConsole (void)
{
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
GPIOPinConfigure (GPIO_PA0_U0RX);
GPIOPinConfigure (GPIO_PA1_U0TX);
SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
UARTClockSourceSet (UART0_BASE、UART_CLOCK_SYSTEM);
GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioConfig (0、115200、SysCtlClockGet ());
}

void InitI2C1 (void)
{
SysCtlPeripheralEnable (SYSCTL_Periph_I2C1);
GPIOPinTypeI2C (GPIO_Porta_base、GPIO_PIN_6 | GPIO_PIN_7);
GPIOPinTypeI2CSCL (GPIO_Porta_base、GPIO_PIN_6);
GPIOPinConfigure (GPIO_PA6_I2C1SCL);
GPIOPinConfigure (GPIO_PA7_I2C1SDA);
I2CMasterInitExpClk (I2C1_base、SysCtlClockGet ()、false);
}

void I2CSend (uint8_t slave_addr、uint8_t num_of _args、...)
{int i;
//告诉主模块何时将在总线上放置什么地址
//与从设备通信。
I2CMasterSlaveAddrSet (I2C1_base、slave_addr、false);

//存储变量数量的参数列表
va_list vargs;

//将 va_list 指定为"open"和最后一个固定参数
//so vargs 知道从何处开始查找
va_start (vargs、num_of _args);

//将要发送的数据放入 FIFO 中
I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));

//如果只有一个参数,我们只需要使用
//单发送 I2C 函数
如果(num_of _args == 1)
{
//从 MCU 发起数据发送
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_SINGLE_SEND);

//等待 MCU 完成传输。
while (I2CMasterBusy (I2C1_base))
;

//"close"变量参数列表
va_end (vargs);
}

//否则,我们开始在上传输多个字节
//I2C 总线
其他
{
//从 MCU 发起数据发送
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_START);

//等待 MCU 完成传输。
while (I2CMasterBusy (I2C1_base))
;

//send num_of _args-2数据片段、使用
///burse_send_contt 命令的 I2C 模块
对于(i = 1;i <(num_of _args - 1);i++)
{
//将下一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));
//发送刚刚放置到 FIFO 中的下一个数据
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_CONT);

//等待 MCU 完成传输。
while (I2CMasterBusy (I2C1_base))
;
}

//将最后一段数据放入 I2C FIFO 中
I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));
//发送刚刚放置到 FIFO 中的下一个数据
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_FINISH);
//等待 MCU 完成传输。
while (I2CMasterBusy (I2C1_base))
;

//"Close"变量 args 列表
va_end (vargs);
}
}

空 USER_DELAY_ms (uint32_t 周期)
{
SysCtlDelay ((SysCtlClockGet ()/ 1000)*(uint32_t)周期);
}

int8_t USER_i2c_read (uint8_t DEV_id、uint8_t REG_addr、uint8_t * REG_DATA、
uint16_t len)
{
int8_t rslt = 0;//返回0表示成功,非0表示失败*/
/*
*参数 dev_id 可用作变量以存储器件的 I2C 地址
*

/*
*总线上的数据应该是这样的
*|-------- --------------- |
*| I2C 操作|数据 |
*|-------- --------------- |
*|开始 |- |
*|写入 |(reg_addr) |
*|停止 |- |
*|开始 |- |
*|阅读 |(REG_DATA[0]) |
*|阅读 |(...) |
*|阅读 |(reg_data[len - 1])|
*|停止 |- |
*|-------- --------------- |
*
I2CMasterSlaveAddrSet (I2C1_base、(uint8_t) dev_id、false);
I2CMasterDataPut (I2C1_base、(uint8_t) reg_addr);
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_START);
while (I2CMasterBusy (I2C1_base))
;
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_FINISH);
I2CMasterSlaveAddrSet (I2C1_base、dev_id、true);
while (len-)
{
I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_Receive_start);
while (I2CMasterBusy (I2C1_base))
;
*REG_DATA = I2CMasterDataGet (I2C1_base);
REG_DATA++;
}
返回 rslt;
}

int8_t USER_i2c_write (uint8_t dev_id、uint8_t reg_addr、uint8_t * reg_data、
uint16_t len)
{
int8_t rslt = 0;//返回0表示成功,非0表示失败*/

/*
*参数 dev_id 可用作变量以存储器件的 I2C 地址
*

/*
*总线上的数据应该是这样的
*|-------- --------------- |
*| I2C 操作|数据 |
*|-------- --------------- |
*|开始 |- |
*|写入 |(reg_addr) |
*|写入 |(REG_DATA[0]) |
*|写入 |(...) |
*|写入 |(reg_data[len - 1])|
*|停止 |- |
*|-------- --------------- |
*
I2CSend (dev_id、1、reg_addr);
while (len-)
{
I2CSend (dev_id、1、* reg_data);
REG_DATA++;

}

} 

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

    大家好、V.Singh、

    BoosterPack 看起来更适合 MSP432器件、我不记得我们在 TM4C 上本地对该 BoosterPack 有任何支持。

    如果您由于需要在 MSP432上使用 TM4C 而尝试进行移植、我们可以尝试提供帮助、但老实说、您可能更容易尝试将其与 MSP-EXP432P401R 套件配合使用。 您的呼叫。

    不管怎样、就 TM4C 而言、我需要看到 I2C 示波器捕获以获得更好的帮助、但我有一条建议是先做、那就是应用此帖子中显示的权变措施: https://e2e.ti.com/support/microcontrollers/other/f/908/p/741685/2738504#2738504

    具体而言、替换此行的所有内容:

    while (I2CMasterBusy (I2C1_base))
    ; 

    其中:

    while (!I2CMasterBusy (I2C1_base)) 
    while (I2CMasterBusy (I2C1_base))
    ; 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我只是尝试使用 bme280、一般而言、就像在分线板上一样。 我添加了建议的修改并连接了我的示波器、SDA 和 SCL 在"0"时没有活动。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    #ifndef Functions_H_
    #define Functions_H_
    
    void InitConsole (void)
    {
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    GPIOPinConfigure (GPIO_PA0_U0RX);
    GPIOPinConfigure (GPIO_PA1_U0TX);
    SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    UARTClockSourceSet (UART0_BASE、UART_CLOCK_SYSTEM);
    GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
    UARTStdioConfig (0、115200、SysCtlClockGet ());
    }
    
    void InitI2C1 (void)
    {
    SysCtlPeripheralEnable (SYSCTL_Periph_I2C1);
    GPIOPinTypeI2C (GPIO_Porta_base、GPIO_PIN_6 | GPIO_PIN_7);
    GPIOPinTypeI2CSCL (GPIO_Porta_base、GPIO_PIN_6);
    GPIOPinConfigure (GPIO_PA6_I2C1SCL);
    GPIOPinConfigure (GPIO_PA7_I2C1SDA);
    I2CMasterInitExpClk (I2C1_base、SysCtlClockGet ()、false);
    }
    
    void I2CSend (uint8_t slave_addr、uint8_t num_of _args、...)
    {int i;
    //告诉主模块何时将在总线上放置什么地址
    //与从设备通信。
    I2CMasterSlaveAddrSet (I2C1_base、slave_addr、false);
    
    //存储变量数量的参数列表
    va_list vargs;
    
    //将 va_list 指定为"open"和最后一个固定参数
    //so vargs 知道从何处开始查找
    va_start (vargs、num_of _args);
    
    //将要发送的数据放入 FIFO 中
    I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));
    
    //如果只有一个参数,我们只需要使用
    //单发送 I2C 函数
    如果(num_of _args == 1)
    {
    //从 MCU 发起数据发送
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_SINGLE_SEND);
    
    //等待 MCU 完成传输。
    while (!I2CMasterBusy (I2C1_base))
    ;
    while (I2CMasterBusy (I2C1_base))
    ;
    
    //"close"变量参数列表
    va_end (vargs);
    }
    
    //否则,我们开始在上传输多个字节
    //I2C 总线
    其他
    {
    //从 MCU 发起数据发送
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_START);
    
    //等待 MCU 完成传输。
    while (I2CMasterBusy (I2C1_base))
    ;
    
    //send num_of _args-2数据片段、使用
    ///burse_send_contt 命令的 I2C 模块
    对于(i = 1;i <(num_of _args - 1);i++)
    {
    //将下一段数据放入 I2C FIFO 中
    I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));
    //发送刚刚放置到 FIFO 中的下一个数据
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_CONT);
    
    //等待 MCU 完成传输。
    while (!I2CMasterBusy (I2C1_base))
    ;
    while (I2CMasterBusy (I2C1_base))
    ;
    }
    
    //将最后一段数据放入 I2C FIFO 中
    I2CMasterDataPut (I2C1_base、va_arg (vargs、uint32_t));
    //发送刚刚放置到 FIFO 中的下一个数据
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_FINISH);
    //等待 MCU 完成传输。
    while (!I2CMasterBusy (I2C1_base))
    ;
    while (I2CMasterBusy (I2C1_base))
    ;
    
    //"Close"变量 args 列表
    va_end (vargs);
    }
    }
    
    空 USER_DELAY_ms (uint32_t 周期)
    {
    SysCtlDelay ((SysCtlClockGet ()/ 1000)*(uint32_t)周期);
    }
    
    int8_t USER_i2c_read (uint8_t DEV_id、uint8_t REG_addr、uint8_t * REG_DATA、
    uint16_t len)
    {
    int8_t rslt = 0;//返回0表示成功,非0表示失败*/
    /*
    *参数 dev_id 可用作变量以存储器件的 I2C 地址
    *
    
    /*
    *总线上的数据应该是这样的
    *|-------- --------------- |
    *| I2C 操作|数据 |
    *|-------- --------------- |
    *|开始 |- |
    *|写入 |(reg_addr) |
    *|停止 |- |
    *|开始 |- |
    *|阅读 |(REG_DATA[0]) |
    *|阅读 |(...) |
    *|阅读 |(reg_data[len - 1])|
    *|停止 |- |
    *|-------- --------------- |
    *
    I2CMasterSlaveAddrSet (I2C1_base、(uint8_t) dev_id、false);
    I2CMasterDataPut (I2C1_base、(uint8_t) reg_addr);
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_START);
    while (!I2CMasterBusy (I2C1_base))
    ;
    while (I2CMasterBusy (I2C1_base))
    ;
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_SEND_FINISH);
    I2CMasterSlaveAddrSet (I2C1_base、dev_id、true);
    while (len-)
    {
    I2CMasterControl (I2C1_base、I2C_MASTER_CMD_BURST_Receive_start);
    while (!I2CMasterBusy (I2C1_base))
    ;
    while (I2CMasterBusy (I2C1_base))
    ;
    *REG_DATA = I2CMasterDataGet (I2C1_base);
    REG_DATA++;
    }
    返回 rslt;
    }
    
    int8_t USER_i2c_write (uint8_t dev_id、uint8_t reg_addr、uint8_t * reg_data、
    uint16_t len)
    {
    int8_t rslt = 0;//返回0表示成功,非0表示失败*/
    
    /*
    *参数 dev_id 可用作变量以存储器件的 I2C 地址
    *
    
    /*
    *总线上的数据应该是这样的
    *|-------- --------------- |
    *| I2C 操作|数据 |
    *|-------- --------------- |
    *|开始 |- |
    *|写入 |(reg_addr) |
    *|写入 |(REG_DATA[0]) |
    *|写入 |(...) |
    *|写入 |(reg_data[len - 1])|
    *|停止 |- |
    *|-------- --------------- |
    *
    I2CSend (dev_id、1、reg_addr);
    while (len-)
    {
    I2CSend (dev_id、1、* reg_data);
    REG_DATA++;
    
    }
    
    }
    #endif /* functions_H_*/
    
    

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

    但是、当您尝试从器件读取器件 ID 时、您会看到活动吗? 那么、您是否能够成功地为器件 ID 发送从器件地址和读取命令、并接收该数据? 但是、当您尝试写入过程时、您看不到任何数据被发送、甚至是从器件地址?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、我可以发送从器件地址并从器件寄存器中读取数据、但在我尝试写入时没有任何活动(不发送从器件地址或发送数据)。 此外、我刚刚试用了 Arduino 传感器、该传感器工作正常。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、V.Singh、

    如果未发送从器件地址、您能否再次检查从器件是否未将 SCL 或 SDA 线保持在低电平? 我非常怀疑这是发生的情况、但这会排除硬件问题。

    只要这些线路可用、我就会希望软件问题引起。 您是否曾尝试过断点以查看是否已到达要写入的函数?

    我没有怀疑传感器有任何问题、但感谢您的检查。

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

    读取和写入函数现在可以工作。 虽然只发生了一个 I2C 事务、如所附的图像所示。我怀疑 API 集成有一些问题。 就硬件而言、它似乎可以正常工作。 就代码而言、我只更改了

    UARTprintf ("%d、%d、%d\r\n"、comp_data->温度、comp_data->压力、comp_data->湿度);
    
    来自
    UARTprintf ("%l、%l、%l\r\n"、comp_data->temperature、comp_data->pressure、comp_data->yumthure); 

    控制台持续读取 0、8138076、102400、但总线上没有活动!

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

    该时钟看起来真的很糟糕。 您使用的上拉电阻器是什么? 您可能需要参考此应用手册: www.ti.com/.../slva689.pdf

    如果上拉电阻器设置不正确、您可能会看到信号、但无法从我看到的数据中获取正确的数据、这似乎是您现在可能遇到的情况、因为您至少有 API 尝试通信。