Arduino ESP32&x2B;深度睡眠+;I2C-中断问题
我在ISR(中断模式)下执行深度睡眠和i2c通信时遇到问题 我使用这个库在Arduino IDE中对其进行编码: 当我在void loop()函数中运行i2c时,它可以正常工作(比如打开LED),但当我将其移植到中断时,它就不工作了 与deepsleep相同,我不能在中断模式下执行它。我绕过它的方法是在中断模式下设置一个标志,表明我想要深度睡眠,然后在void loop()函数中执行它 有没有人有办法解决这个问题?(代码仅适用于i2c和esp32)Arduino ESP32&x2B;深度睡眠+;I2C-中断问题,arduino,microcontroller,esp32,Arduino,Microcontroller,Esp32,我在ISR(中断模式)下执行深度睡眠和i2c通信时遇到问题 我使用这个库在Arduino IDE中对其进行编码: 当我在void loop()函数中运行i2c时,它可以正常工作(比如打开LED),但当我将其移植到中断时,它就不工作了 与deepsleep相同,我不能在中断模式下执行它。我绕过它的方法是在中断模式下设置一个标志,表明我想要深度睡眠,然后在void loop()函数中执行它 有没有人有办法解决这个问题?(代码仅适用于i2c和esp32) #包括 #如有定义(ARDUINO_ARC
#包括
#如有定义(ARDUINO_ARCH_SAMD)
//对于零,在USB串行控制台上输出,如果使用编程端口编程零,请删除下面的行!
#定义串行USB
#恩迪夫
//中断设置-定时器
hw_timer_t*timer=NULL//配置计时器,需要指向hw_timer_t变量类型的指针
portMUX\u TYPE timerMux=portMUX\u初始值设定项\u未锁定;//用于同步主环路和ISR
RTC_DATA_ATTR bool应_sleep=false;
//设置ADC属性-电池
int电压_放大器=0;
电池电量百分比=0;
//设置i2c地址-I/O扩展器
常量int地址=0x20;
uint16_t led_status=字(B11111111,B11111111);
//中断模式-在portENTER和portEXIT之间插入
void IRAM_ATTR onTimer(){
portENTER\u CRITICAL\u ISR(&timerMux);
//led_电池();如果在此处使用,led不会更新
portEXIT_CRITICAL_ISR(&timerMux);
}
无效led_电池(){
电压\放大器=模拟读数(34);
串行打印LN(电压放大器);
整数位_max=4096;
int电池百分比=电压放大器*100/位最大值;
//如果电池电量低于20%
如果从中断处理程序调用led\u battery()
时(电池百分比),则表示您在那里做了太多的工作
中断可以中断任何没有被锁定的中断
假设您的代码正在使用串行输出某些内容,并且计时器中断发生。现在您的代码正在串行中的某个位置运行代码,您再次调用串行…而软件和硬件可能处于不一致的状态
从中断处理程序进行的每个子程序和硬件访问都是这样。防止这种情况发生的唯一方法是在代码访问硬件或修改数据结构时禁用中断
不幸的是,禁用中断很容易出错-如果你忘记了这样做,你会有神秘的崩溃。如果你忘记重新启用它们,你会遇到大麻烦-你的网络、计时器和串行都会停止工作。这也会给你的代码增加很多开销。它会降低你的整体系统性能-它会延迟或导致你重新启动iss网络和计时器事件。您可以从串行端口删除字符。您可以确定Arduino内核中没有任何代码为您执行此操作
所以,长话短说,锁定中断以便在中断处理程序中做很多事情是不实际的
您还希望尽量减少在中断处理程序中花费的时间,因为这会抢占网络堆栈、计时器、串行和其他硬件处理,并可能阻塞其他硬件处理
您在最初的帖子中指出了我们处理这个问题的方法:设置一个标志(确保它是易变的
)在中断处理程序中,并在任务中处理。除非您真的、真的知道自己在做什么以及系统中所有软件的工作方式,否则这是唯一可行的处理方法。如果您试图完成大量工作并调用中断处理程序调用的内容,您的程序将出现故障和崩溃。请与我们分享一个最小的、可行的、完整的代码示例,演示了您的问题。@JohnRomkey在这里,希望它是清楚的。抱歉,如果有任何令人讨厌的格式,我是stackoverflow的新手。是的,刚刚发现您不能使用中断来一致地跟踪某件事情,除非它非常紧急,并且您需要在该统计上花费最少的时间e、 谢谢你的意见@JohnRomkey@RiccoYudha,如果你认为我的答案是准确的,那么请接受它作为解决方案。
#include <Wire.h>
#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endif
// Interrupt Setup - TIMER
hw_timer_t * timer = NULL; //configure the timer, need pointer to a variable type of hw_timer_t
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // used to sync main loop and ISR
RTC_DATA_ATTR bool should_sleep = false;
// Setting ADC Properties - BATTERY
int voltage_amplifier = 0;
int battery_percentage = 0;
// Set i2c Address - I/O EXPANDER
const int address = 0x20;
uint16_t led_status = word(B11111111,B11111111);
// INTERRUPT MODE - INSERT INBETWEEN portENTER and portEXIT
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
// led_battery(); led doesn't update if used here
portEXIT_CRITICAL_ISR(&timerMux);
}
void led_battery(){
voltage_amplifier = analogRead(34);
Serial.println(voltage_amplifier);
int bit_max = 4096;
int battery_percentage = voltage_amplifier*100/bit_max;
// If battery is below 20%
if (battery_percentage <= 20){
led_status &= word(B00111111,B11111111); // clearing the bits that we want to change whilst preserving the other unchanged bits
led_status |= ~word(B11000000,B00000000); // setting up the bits that we want to change
pf575_write(led_status);
}
else if (battery_percentage <= 40){
led_status &= word(B00011111,B11111111); // clearing the bits that we want to change whilst preserving the other unchanged bits
led_status |= ~word(B11100000,B00000000); // setting up the bits that we want to change
pf575_write(led_status);
}
else if (battery_percentage <= 60){
led_status &= word(B00001111,B11111111); // clearing the bits that we want to change whilst preserving the other unchanged bits
led_status |= ~word(B11110000,B00000000); // setting up the bits that we want to change
pf575_write(led_status);
}
else if (battery_percentage <= 80){
led_status &= word(B00000111,B11111111); // clearing the bits that we want to change whilst preserving the other unchanged bits
led_status |= ~word(B11111000,B00000000); // setting up the bits that we want to change
pf575_write(led_status);
}
else if (battery_percentage <= 100){
led_status &= word(B00000011,B11111111); // clearing the bits that we want to change whilst preserving the other unchanged bits
led_status |= ~word(B11111100,B00000000); // setting up the bits that we want to change
pf575_write(led_status);
}
}
void ioexpander_setup(){
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\n Blinker Ready");
Wire.begin();
}
void pf575_write(uint16_t data) {
Wire.beginTransmission(address);
Wire.write(lowByte(data));
Wire.write(highByte(data));
Wire.endTransmission();
}
void timer_setup(){
// Base Clock Frequency = 80MHz ; Timer Frequency = 1MHz | Clock Cycle = 1us [in this case]
timer = timerBegin(0,80,true); // return a pointer to a structure of type hw_timer_t
// Timer binded to a handling function
timerAttachInterrupt(timer, &onTimer, true); // Parameter : (timer_initialization, address_interrupt,flag_to_activate - true(edge)/false(level))
// Specify the counter value in which the timer interrupt will be generated (set every 10 ms)
timerAlarmWrite(timer, 10000, true); // Parameter : (timer_initialization, when_to_interrupt (us), flag_to_reload)
// Enable the timer
timerAlarmEnable(timer);
}
void setup() {
Serial.begin(115200);
// IO Expander
ioexpander_setup();
// Timer
timer_setup();
}
void loop() {
led_battery(); //led update if used here
}