Arduino Mega替代Uno运行电容式传感器代码的定时器中断适配问题
代码适配Arduino Mega的修改方案
核心问题原因
你代码的问题核心是直接操作了Arduino核心占用的Timer0相关变量和寄存器,ATmega2560(Mega的主控)和ATmega328P(Uno的主控)的Timer0相关变量暴露规则、寄存器操作逻辑有差异,具体修改点如下:
修改点1:替换废弃的timer0_overflow_count调用
旧版Uno核心对外暴露了timer0_overflow_count变量,但Mega所用的AVR核心已经将该变量改为内部私有静态变量,你写的extern声明无法获取正确值,直接废弃手动计时逻辑,改用Arduino官方提供的micros()函数实现计时,兼容性更强。
修改点2:移除对系统Timer0的直接修改
直接重置TCNT0和计时器溢出计数会打乱Mega系统自带的millis()、delay()等函数的正常运行,改用官方计时函数后完全规避该问题。
修改点3:保留原端口操作逻辑
原代码中对PORTH、PINH的操作对应Mega的数字引脚8,只要你硬件接线正确无需额外修改。
修改后完整可运行代码
#define resolution 8 #define mains 60 // 60: 北美、日本; 50: 其他大部分地区 #define refresh 2 * 1000000 / mains void setup() { Serial.begin(9600); // unused引脚拉低减少干扰 for(int i = 2; i < 14; i++) { pinMode(i, OUTPUT); digitalWrite(i, LOW); } for(int i =22; i < 53; i++){ pinMode(i, OUTPUT); digitalWrite(i, LOW); } pinMode(8, INPUT); } void loop() { Serial.println(time(8, B00100000), DEC); } long time(int pin, byte mask) { unsigned long count = 0, total = 0; unsigned long start = micros(); while(micros() - start < refresh) { pinMode(pin, OUTPUT); PORTH = 0; pinMode(pin, INPUT); while((PINH & mask) == 0) count++; total++; } return (count << resolution) / total; }
如果你坚持要使用寄存器操作计时器,可以改用Mega上未被系统默认占用的Timer1/Timer3/Timer4/Timer5,修改时注意16位定时器的寄存器操作规则即可。
内容的提问来源于stack exchange,提问作者Renan Almeida
相关产品推荐
相关产品推荐

