我有一个 esp32,我想用它来驱动 HC-SR04 声纳模块。我使用中断从传感器获取信息,然后使用队列将数据传递给 freertos 任务以输出它。一开始,它工作并输出正确的数据,但几秒钟后,它报告错误并重新启动。
这是错误:
古鲁冥想错误:核心 1 恐慌(加载禁止)。异常未处理。
核心 1 寄存器转储:
PC:0x40084c90 PS:0x00050631 A0:0x800d31c4 A1:0x3ffbf53c
A2:0x00000040 A3:0x00018040 A4:0x000637ff A5:0x3ffbf50c
A6:0x00000008 A7:0x00000000 A8:0x00000001 A9:0x4008bf6e
A10:0x00060b23 A11:0x3ffc4a14 A12:0x3ff44000 A13:0xffffff00
A14:0x00000000 A15:0x00000020 SAR:0x0000001d 借口:0x0000001c
EXCVADDR:0x800d31d0 LBEG:0x400899a4 借出:0x400899ba LCOUNT:0xffffffff
回溯:0x40084c8d:0x3ffbf53c |<-CORRUPTED
然后我发现,如果我删除用于将数据推送到队列的代码,它就可以正常工作。所以我猜这就是问题所在,但我不知道如何解决它。
主要内容如下:
radar radar0(25,35);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.setDebugOutput(true);
radar0.start();
}
以下是雷达类别的定义:
class radar
{
private:
uint8_t txPin,rxPin;
Ticker loopTrigger; //ticker that use to trigger loop
Ticker singalEnder; //ticker that use to generate a 1ms pulse
QueueHandle_t dstQueue; //queue that use to pass dst to coroutine
float previousDst;
bool enable;
unsigned long echoStartTime; //The time the echo start received
void loop();
void echoStartHandler(); //callback when the echo start
void echoEndHandler(); //callback when the echo end
void queueListener();
public:
radar(uint8_t txPin,uint8_t rxPin);
void start();
};
radar::radar(uint8_t txPin,uint8_t rxPin){
this->txPin=txPin;
this->rxPin=rxPin;
this->enable=true;
this->dstQueue = xQueueCreate(4,sizeof(float));
}
void radar::start(){
//set pin mode
pinMode(this->txPin,OUTPUT);
pinMode(this->rxPin,INPUT);
//low down the txPin
digitalWrite(this->txPin,LOW);
//Create a coroutine for listening to the dstQueue
auto fn = [](void *arg){static_cast<radar*>(arg)->queueListener();};
xTaskCreate(fn,"dstListener",1024,this,0,NULL);
//enable the radar
this->enable=true;
this->loop();
}
void radar::queueListener(){
float dst;
while (this->enable)
{
if (xQueueReceive(this->dstQueue,&dst,0)==pdFALSE){
//sleep 10ms if the queue is empty
vTaskDelay(10/portTICK_PERIOD_MS);
continue;
}
if (abs(dst-this->previousDst)>5){
Serial.println(dst);
this->previousDst=dst;
}
}
vTaskDelete(NULL);
}
void radar::echoStartHandler(){
this->echoStartTime = micros();
//Set rxPin pull-down interrupt
attachInterruptArg(rxPin,[](void* r){static_cast<radar*>(r)->echoEndHandler();},this,FALLING);
}
void radar::echoEndHandler(){
detachInterrupt(this->rxPin);
unsigned long echoEndTime = micros();
float pluseTime;
if (echoEndTime > this->echoStartTime){ //If the variable does not overflow
pluseTime = echoEndTime - this->echoStartTime;
}else{
pluseTime = echoEndTime + (LONG_MAX - this->echoStartTime);
}
float dst = pluseTime * 0.0173;
//push the dst to queue
BaseType_t xHigherPriorityTaskWoken;
xQueueSendFromISR(this->dstQueue,&dst,&xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken==pdTRUE){
portYIELD_FROM_ISR();
}
}
void radar::loop(){
if (!this->enable){
return;
}
//Set loop() to be triggered after 100ms
this->loopTrigger.once_ms<radar*>(100,[](radar* r){r->loop();},this);
//Generate a 1ms pulse at txPin
digitalWrite(this->txPin,HIGH);
this->singalEnder.once_ms<uint8_t>(1,[](uint8_t pin){digitalWrite(pin,LOW);},this->txPin);
//Set rxPin pull-up callback
attachInterruptArg(rxPin,[](void* r){static_cast<radar*>(r)->echoStartHandler();},this,RISING);
}
感谢您的帮助!
ps: 请原谅我糟糕的英语。我不是母语人士。
经过几个小时的研究,我在帖子中发现了一些东西。看来在esp32中我们不能在中断中使用float,因为它将使用FPU,而FPU不允许在中断处理程序中使用。
在我的中断处理程序中删除浮动后,代码终于可以工作了。