Thread 中讨论的其他器件:CC2652RB、 SysConfig、 Z-stack、 SYSBIOS
我想使用示例项目 zr_temperaturesenser_LP_CC2652Rb_tirtos_ccs 并实现我自己的温度测量传感器、尝试使用 zigbee2mqtt 连接电路板、并评估可能的新项目。 我使用了带 I2C 的 BME680温度传感器、我之前为其编写了一个驱动程序、它在另一个项目中工作正常、我可以在该项目上从传感器读取和写入数据。 我可以确认通信在协议合规性方面是正确的、正如我使用示波器检查过的。 但是,这在将驱动程序引入示例项目时根本不起作用,因为 i2c 通信似乎会在 MID 传输时失败(这仅在使用示例 ztack 项目时发生)。 我将尝试并详细说明我在下面执行的步骤:
在 main 中、在创建新任务之前、我初始化 i2c 外设和传感器。
#define SPI_BUFFER_SIZE 64
#define I2C_BUS_ADDR 0x00
static struct bme680_dev gBME680Struct = { };
bool gResult = true;
uint16_t gMeasPeriod = 0;
static I2C_Handle gI2C = { 0 };
static I2C_Params gI2CParams = { 0 };
static I2C_Transaction gI2CTransaction = { 0 };
static bool gI2CInitDone = false;
static uint8_t txBuf[SPI_BUFFER_SIZE];
static uint8_t rxBuf[SPI_BUFFER_SIZE];
int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
void userDelay(uint32_t period);
int8_t sensorBME680Init()
{
if (!gI2CInitDone){
return __LINE__;
}
int8_t rslt = BME680_OK;
gBME680Struct.dev_id = BME680_I2C_ADDR_PRIMARY;
gBME680Struct.intf = BME680_I2C_INTF;
gBME680Struct.read = userRead;
gBME680Struct.write = userWrite;
gBME680Struct.delay_ms = userDelay;
gBME680Struct.amb_temp = 25;
rslt = bme680_init(&gBME680Struct);
if (0 != rslt)
{
return __LINE__;
}
uint16_t setRequiredSettings;
/* Set the temperature, pressure and humidity settings */
gBME680Struct.tph_sett.os_hum = BME680_OS_2X;
gBME680Struct.tph_sett.os_pres = BME680_OS_4X;
gBME680Struct.tph_sett.os_temp = BME680_OS_8X;
gBME680Struct.tph_sett.filter = BME680_FILTER_SIZE_3;
/* Set the remaining gas sensor settings and link the heating profile */
gBME680Struct.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
/* Create a ramp heat waveform in 3 steps */
gBME680Struct.gas_sett.heatr_temp = 320; /* degree Celsius */
gBME680Struct.gas_sett.heatr_dur = 150; /* milliseconds */
/* Select the power mode */
gBME680Struct.power_mode = BME680_FORCED_MODE;
/* Must be set before writing the sensor configuration */
/* Set the required sensor settings needed */
setRequiredSettings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL
| BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
/* Set the desired sensor configuration */
rslt = bme680_set_sensor_settings(setRequiredSettings, &gBME680Struct);
/* Set the power mode */
rslt = bme680_set_sensor_mode(&gBME680Struct);
bme680_get_profile_dur(&gMeasPeriod, &gBME680Struct);
gBME680Struct.delay_ms(gMeasPeriod); /* Delay till the measurement is ready */
memset(txBuf, 0, SPI_BUFFER_SIZE);
memset(rxBuf, 0, SPI_BUFFER_SIZE);
return rslt;
}
int8_t sensorBME680I2CInit()
{
I2C_init();
I2C_Params_init(&gI2CParams);
gI2C = I2C_open(I2C_BUS_ADDR, &gI2CParams);
if (NULL == gI2C)
{
return __LINE__;
}
gI2CInitDone = true;
return 0;
}
int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if (!gI2CInitDone)
{
return __LINE__;
}
if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
{
return __LINE__;
}
memset(txBuf, 0, SPI_BUFFER_SIZE);
txBuf[0] = reg_addr;
gI2CTransaction.slaveAddress = dev_id /*<< 1*/;
gI2CTransaction.readCount = len;
gI2CTransaction.readBuf = data;
gI2CTransaction.writeCount = 1;
gI2CTransaction.writeBuf = txBuf;
gResult = I2C_transfer(gI2C, &gI2CTransaction);
if (!gResult)
{
return -1;
}
return 0;
}
int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if (!gI2CInitDone)
{
return -1;
}
if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
{
return -1;
}
memset(txBuf, 0, SPI_BUFFER_SIZE);
txBuf[0] = reg_addr;
memcpy(&txBuf[1], data, len);
gI2CTransaction.slaveAddress = dev_id;
gI2CTransaction.writeCount = len + 1;
gI2CTransaction.writeBuf = txBuf;
gI2CTransaction.readCount = 0;
gResult = I2C_transfer(gI2C, &gI2CTransaction);
if (!gResult)
{
return 1;
}
return 0;
}
void userDelay(uint32_t period)
{
usleep(1000 * period);
}
int8_t getSensorData(struct bme680_field_data *pData)
{
if (!gI2CInitDone)
{
return -2;
}
if (NULL == pData)
{
return -1;
}
static int8_t rslt = 0;
rslt = bme680_get_sensor_data(pData, &gBME680Struct);
if (gBME680Struct.power_mode == BME680_FORCED_MODE)
{
rslt = bme680_set_sensor_mode(&gBME680Struct);
}
return rslt;
}
void sensorBME680CommInit()
{
int8_t rslt = sensorBME680I2CInit();
if (0 != rslt)
{
return;
}
rslt &= sensorBME680Init();
if (0 == rslt)
{
gInitDone = true;
}
}
然后、我创建一个新任务来轮询传感器并报告温度变化:
void pollTask()
{
static int16_t temp = 0;
static zstack_bdbRepChangedAttrValueReq_t zReq;
while (1)
{
if (gInitDone)
{
GPIO_toggle(CONFIG_GPIO_RLED);
getSensorData(&gZSensorData);
temp = gZSensorData.temperature;
if (temp < zclSampleTemperatureSensor_MaxMeasuredValue
&& temp > zclSampleTemperatureSensor_MinMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue = temp;
}
else if (temp >= zclSampleTemperatureSensor_MaxMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue =
zclSampleTemperatureSensor_MaxMeasuredValue;
}
else if (temp <= zclSampleTemperatureSensor_MinMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue =
zclSampleTemperatureSensor_MinMeasuredValue;
}
#ifdef BDB_REPORTING
zReq.attrID = ATTRID_TEMPERATURE_MEASUREMENT_MEASURED_VALUE;
zReq.cluster = ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT;
zReq.endpoint = SAMPLETEMPERATURESENSOR_ENDPOINT;
Zstackapi_bdbRepChangedAttrValueReq(appServiceTaskId, &zReq);
#endif
Task_sleep(100 * (1000 / Clock_tickPeriod));
}
}
}
我在 main 中初始化它并启动任务:
#define SENSOR_TASK_STACK_SIZE 1000
Task_Struct gPollTask;
Char pollTaskStack[SENSOR_TASK_STACK_SIZE];
Void sensorPollTask(UArg a0, UArg a1)
{
extern void pollTask();
pollTask();
}
// in main
{
sensorBME680CommInit();
Task_Params sensorTaskParams;
Task_Params_init(&sensorTaskParams);
sensorTaskParams.stack = pollTaskStack;
sensorTaskParams.priority = 2;
sensorTaskParams.stackSize = SENSOR_TASK_STACK_SIZE;
Task_construct(&gPollTask, sensorPollTask, &sensorTaskParams, NULL);
BIOS_start();
}
我无法将调试器用于调试目的、因为调试器会跳转至整个位置、我无法按照每条指令执行操作、即使在 示波器中的某一行上暂停、也无法看到大多数变量的值。 我以前从未在任何 IDE 中发生过这种情况。 不管怎样、我可以使用示波器、看到代码的某些部分没有执行、但程序似乎没有失败。 更清楚的是、初始化传感器的第一步是通过 i2c 执行软复位命令(设置了写入位的发送地址、发送寄存器地址和发送寄存器值)。 外设只发送从机地址和寄存器地址(从 机已成功确认)、然后突然中断、不发送寄存器值、也不使用停止位结束 i2c 传输。 将附加照片:

我假设传输不会以失败结束、但正如我说过的、一旦调试器到达 I2C_Transfer 线路、它就会自行自由运行、不会让我跳过来查看传输结果。 sensorBME680CommInit()之后的代码; 在 main 中,当主 ZigBee 任务正在运行并且电路板看起来没有复位时,似乎执行了。
摘要如下:在 main 中、我调用 rslt = BME680_init (&gBME680Struct); 该函数又调用 rslt &= sensorBME680Init();调用 rslt = BMEM680_init (&gBMEM680Struct);该函数应向传感器发送软复位命令。 命令的前两个帧被发送并应答、但传输 突然结束、而代码的其余部分似乎被执行。 在我的整个生命周期中、我无法获得 用于初始化传感器的电路板、也无法检查我编写的其余内容是否正常工作。 传感器轮询任务启动、但传感器未初始化、因此我无法验证它应该发送的数据。