【问题标题】:ESP8266 - Async DallasTemperature - Exception (28)ESP8266 - 异步 DallasTemperature - 异常 (28)
【发布时间】:2017-08-25 10:02:10
【问题描述】:

我正在定时器中断中开始温度测量 (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)

【问题讨论】:

  • 您应该只在中断处理程序中设置一个标志并将sensors.requestTemperatures() 放在您的主循环中。您的重置原因 28 可能是由指向未初始化对象的指针引起的。您确定温度 IC 准备好了吗?
  • @BMelis 我创建了一个 volatile bool 变量,现在我只在中断处理程序中设置它。为什么这是正确/首选的方式?是因为中断应该尽快完成并且设置布尔值比调用该方法更快吗?在配置传感器变量之后,我在设置方法中延迟了 10 秒,并且我还(成功地)在设置方法中打印了那里的温度(同步请求)。调用 isConversionAvailable 方法时仍然抛出异常。

标签: arduino esp8266 arduino-esp8266


【解决方案1】:

看函数的代码(省略了几个cmets):

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-&gt;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-Libraryhttps://github.com/PaulStoffregen/OneWire 的库文件。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-21
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多