ESP8266 - 异步达拉斯温度 - 异常 (28)
ESP8266 - Async DallasTemperature - Exception (28)
我正在定时器中断中开始温度测量 (sensors.requestTemperatures),我需要一种方法来了解它是否准备就绪。我尝试使用 sensors.isConversionAvailable 方法,但它抛出异常。我查看了isConversionAvailable方法的源码,尝试自己调用readScratchPad方法,那里抛出异常
完整代码:
#include <DallasTemperature.h>
#include <OneWire.h>
#define TIMER_SECONDS 1
#define SENSOR_PIN 5
OneWire sensorWire(SENSOR_PIN);
DallasTemperature sensors(&sensorWire);
void setup() {
Serial.begin(115200);
Serial.println("Initializing...");
sensors.begin();
sensors.setResolution(10);
sensors.setWaitForConversion(false);
timer1_isr_init();
timer1_attachInterrupt([] {
sensors.requestTemperatures();
});
timer1_enable(TIM_DIV265, TIM_EDGE, TIM_LOOP);
timer1_write(F_CPU / 256 * TIMER_SECONDS);
Serial.println("Initialization complete");
}
void loop() {
Serial.println("Started the loop method");
//When this block is uncommented, the second exception is thrown
/*uint8_t number;
sensors.readScratchPad(0, &number);
Serial.print("Scratch pad number: ");
Serial.println(number);*/
if (sensors.isConversionAvailable(0)) {
Serial.print("Temperature: ");
Serial.println(sensors.getTempCByIndex(0));
} else {
Serial.println("The conversion is unavailable");
}
Serial.println("Finished the loop method");
}
异常(isConversionAvailable):
Initializing...
Initialization complete
Started the loop method
Exception (28):
epc1=0x402025af epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef230 end: 3ffef460 offset: 01a0
>>>stack>>>
3ffef3d0: 00000000 3ffee354 00000000 402025ad
3ffef3e0: 3ffef420 00000000 3ffee338 40201e57
3ffef3f0: 00000000 00000017 3ffef4a0 40202bcd
3ffef400: 3ffe8588 00000000 3ffef4a0 3ffee42c
3ffef410: 3fffdad0 3ffee338 3ffef4a0 40202144
3ffef420: 40201052 88011627 3ffef4a0 40202c1c
3ffef430: 3fffdad0 00000000 3ffef4a0 40201d0e
3ffef440: feefeffe 00000000 3ffee424 40202888
3ffef450: feefeffe feefeffe 3ffee440 40100114
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(1,6)
异常(readScratchPad):
Initializing...
Initialization complete
Started the loop method
Exception (28):
epc1=0x402025cf epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef250 end: 3ffef470 offset: 01a0
>>>stack>>>
3ffef3f0: 00000000 3ffee364 00000000 402025cd
3ffef400: 3ffef440 00000000 3ffee348 40201e77
3ffef410: 00000000 3ffee348 3ffef4b0 40202c18
3ffef420: 3ffe8438 00000000 3ffef4b0 3ffee43c
3ffef430: 3fffdad0 3ffee348 3ffef4b0 40201d14
3ffef440: 3fffdad0 3ffee348 3ffef4b0 40201cd0
3ffef450: feefeffe 00000000 3ffee434 402028a8
3ffef460: feefeffe feefeffe 3ffee450 40100114
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(1,6)
查看函数代码(省略一些注释):
bool DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad){
// send the reset command and fail fast
int b = _wire->reset();
if (b == 0) return false;
_wire->select(deviceAddress);
_wire->write(READSCRATCH);
for(uint8_t i = 0; i < 9; i++){
scratchPad[i] = _wire->read();
}
b = _wire->reset();
return (b == 1);
}
你用
调用函数
sensors.readScratchPad(0, &number);
然后deviceAddress = NULL
。于是就有了调用_wire->select(deviceAddress)
。 _wire
对象的类型为 OneWire*
。 select
函数实现如下:
void OneWire::select(const uint8_t rom[8])
{
uint8_t i;
write(0x55); // Choose ROM
for (i = 0; i < 8; i++) write(rom[i]);
}
并且在 rom[i]
中,您对最初提供的 NULL
指针进行了取消引用。即:崩溃。
查看库中的另一个函数显示了如何获取有效的 deviceAddress
指针。
float DallasTemperature::getTempCByIndex(uint8_t deviceIndex){
DeviceAddress deviceAddress;
if (!getAddress(deviceAddress, deviceIndex)){
return DEVICE_DISCONNECTED_C;
}
return getTempC((uint8_t*)deviceAddress);
}
因此,如果您想要第一个传感器的地址,可以通过以下方式获取:
DeviceAddress deviceAddress;
if (!sensors.getAddress(deviceAddress, 0)){
Serial.println("No device address found for index 0!!!");
return;
}
//use deviceAddr in the next call
ScratchPad readScratchPad; //this is a typedef to uint8_t[9]
sensors.readScratchPad( (uint8_t*)deviceAddress, readScratchPad);
//do whatever you like with the values in the readScratchPad array..
如需进一步参考,请查看 https://github.com/milesburton/Arduino-Temperature-Control-Library and https://github.com/PaulStoffregen/OneWire 中的库文件。
我正在定时器中断中开始温度测量 (sensors.requestTemperatures),我需要一种方法来了解它是否准备就绪。我尝试使用 sensors.isConversionAvailable 方法,但它抛出异常。我查看了isConversionAvailable方法的源码,尝试自己调用readScratchPad方法,那里抛出异常
完整代码:
#include <DallasTemperature.h>
#include <OneWire.h>
#define TIMER_SECONDS 1
#define SENSOR_PIN 5
OneWire sensorWire(SENSOR_PIN);
DallasTemperature sensors(&sensorWire);
void setup() {
Serial.begin(115200);
Serial.println("Initializing...");
sensors.begin();
sensors.setResolution(10);
sensors.setWaitForConversion(false);
timer1_isr_init();
timer1_attachInterrupt([] {
sensors.requestTemperatures();
});
timer1_enable(TIM_DIV265, TIM_EDGE, TIM_LOOP);
timer1_write(F_CPU / 256 * TIMER_SECONDS);
Serial.println("Initialization complete");
}
void loop() {
Serial.println("Started the loop method");
//When this block is uncommented, the second exception is thrown
/*uint8_t number;
sensors.readScratchPad(0, &number);
Serial.print("Scratch pad number: ");
Serial.println(number);*/
if (sensors.isConversionAvailable(0)) {
Serial.print("Temperature: ");
Serial.println(sensors.getTempCByIndex(0));
} else {
Serial.println("The conversion is unavailable");
}
Serial.println("Finished the loop method");
}
异常(isConversionAvailable):
Initializing...
Initialization complete
Started the loop method
Exception (28):
epc1=0x402025af epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef230 end: 3ffef460 offset: 01a0
>>>stack>>>
3ffef3d0: 00000000 3ffee354 00000000 402025ad
3ffef3e0: 3ffef420 00000000 3ffee338 40201e57
3ffef3f0: 00000000 00000017 3ffef4a0 40202bcd
3ffef400: 3ffe8588 00000000 3ffef4a0 3ffee42c
3ffef410: 3fffdad0 3ffee338 3ffef4a0 40202144
3ffef420: 40201052 88011627 3ffef4a0 40202c1c
3ffef430: 3fffdad0 00000000 3ffef4a0 40201d0e
3ffef440: feefeffe 00000000 3ffee424 40202888
3ffef450: feefeffe feefeffe 3ffee440 40100114
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(1,6)
异常(readScratchPad):
Initializing...
Initialization complete
Started the loop method
Exception (28):
epc1=0x402025cf epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3ffef250 end: 3ffef470 offset: 01a0
>>>stack>>>
3ffef3f0: 00000000 3ffee364 00000000 402025cd
3ffef400: 3ffef440 00000000 3ffee348 40201e77
3ffef410: 00000000 3ffee348 3ffef4b0 40202c18
3ffef420: 3ffe8438 00000000 3ffef4b0 3ffee43c
3ffef430: 3fffdad0 3ffee348 3ffef4b0 40201d14
3ffef440: 3fffdad0 3ffee348 3ffef4b0 40201cd0
3ffef450: feefeffe 00000000 3ffee434 402028a8
3ffef460: feefeffe feefeffe 3ffee450 40100114
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(1,6)
查看函数代码(省略一些注释):
bool DallasTemperature::readScratchPad(const uint8_t* deviceAddress, uint8_t* scratchPad){
// send the reset command and fail fast
int b = _wire->reset();
if (b == 0) return false;
_wire->select(deviceAddress);
_wire->write(READSCRATCH);
for(uint8_t i = 0; i < 9; i++){
scratchPad[i] = _wire->read();
}
b = _wire->reset();
return (b == 1);
}
你用
调用函数sensors.readScratchPad(0, &number);
然后deviceAddress = NULL
。于是就有了调用_wire->select(deviceAddress)
。 _wire
对象的类型为 OneWire*
。 select
函数实现如下:
void OneWire::select(const uint8_t rom[8])
{
uint8_t i;
write(0x55); // Choose ROM
for (i = 0; i < 8; i++) write(rom[i]);
}
并且在 rom[i]
中,您对最初提供的 NULL
指针进行了取消引用。即:崩溃。
查看库中的另一个函数显示了如何获取有效的 deviceAddress
指针。
float DallasTemperature::getTempCByIndex(uint8_t deviceIndex){
DeviceAddress deviceAddress;
if (!getAddress(deviceAddress, deviceIndex)){
return DEVICE_DISCONNECTED_C;
}
return getTempC((uint8_t*)deviceAddress);
}
因此,如果您想要第一个传感器的地址,可以通过以下方式获取:
DeviceAddress deviceAddress;
if (!sensors.getAddress(deviceAddress, 0)){
Serial.println("No device address found for index 0!!!");
return;
}
//use deviceAddr in the next call
ScratchPad readScratchPad; //this is a typedef to uint8_t[9]
sensors.readScratchPad( (uint8_t*)deviceAddress, readScratchPad);
//do whatever you like with the values in the readScratchPad array..
如需进一步参考,请查看 https://github.com/milesburton/Arduino-Temperature-Control-Library and https://github.com/PaulStoffregen/OneWire 中的库文件。