我有一个ESP32,使用MCP23017集成电路,使用旋转编码器,完美地处理中断和任务。然后,我添加到一个连接到L293D的MCP23017上,运行良好。
当步进电机工作时,当我与旋转编码器交互时,问题就会发生。ESP32重新启动,我确信原因是这两个任务都希望同时访问MCP23017硬件。
因为MCP23017使用的是Sempahore:
SemaphoreHandle_t rotaryISRSemaphore = nullptr;
// MCP23017
Adafruit_MCP23017 mcp;
....
void setup(){
....
rotaryISRSemaphore = xSemaphoreCreateBinary();
mcp.begin(1); // use default address 0
xTaskCreatePinnedToCore(&rotaryReaderTask, "rotary reader", 2048, NULL, 20, NULL, 1);
attachInterrupt(esp32IntPin, intCallBack, FALLING);
xTaskCreate(stepperMotor,"Stepper Motor",2048, NULL, 1, NULL);
}
// The int handler will just signal that the int has happened
// we will do the work from a task.
void IRAM_ATTR intCallBack() {
//Serial.println("intCallback");
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(rotaryISRSemaphore, &xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR ();
}
}
void rotaryReaderTask(void* pArgs) {
(void)pArgs;
Serial.println("Started rotary reader task.");
while(true) {
if(xSemaphoreTake(rotaryISRSemaphore, portMAX_DELAY) == pdPASS) {
handleInterrupt();
}
void handleInterrupt(){
//Read the entire state when the interrupt occurred
....
// Here some work to do with the MCP23017
}
void loop() {
}
int stepperValues[4][4] = {{HIGH,LOW,HIGH,LOW},{LOW,HIGH,HIGH,LOW},{LOW,HIGH,LOW,HIGH}, {HIGH,LOW,LOW,HIGH}};
void stepperMotor(void * params){
(void) params;
for(;;){
if(!stopStepper){
for ( int i = 0; i < 4; ++i ) {
// loop through columns of current row
mcp.digitalWrite(10, stepperValues[i][0]);
mcp.digitalWrite(11, stepperValues[i][1]);
mcp.digitalWrite(12, stepperValues[i][2]);
mcp.digitalWrite(13, stepperValues[i][3]);
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
有关于如何避免ESP32重新启动问题的线索吗?
发布于 2022-02-16 07:13:25
当您拥有需要由多个任务访问的共享资源时,需要使用互斥保护资源。
如果完全控制代码,最好的选择是向I2C总线添加互斥,因为I2C总线上可能有需要从多个任务访问的其他设备。
如果您不能修改I2C代码,并且MCP23017是总线上唯一的设备,那么您可以编写一些包装函数/类,在访问MCP23017之前锁定互斥对象,然后再解锁它。
请注意,您不能在ISR中使用互斥,因此您的代码可能需要进一步重构,以便只从任务上下文访问设备。
https://stackoverflow.com/questions/71137216
复制相似问题