我在测试TB6600步进电机控制器时,使用了ESP8266。在Arduino上编程,测试发出脉冲信号时,程序代码如下:
// 旋转指定步数
void rotateSteps(int steps) {
for(int i = 0; i < steps; i++) {
digitalWrite(PUL_PIN, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(PUL_PIN, LOW);
delayMicroseconds(stepDelay);
}
}其中stepDelay设置为1000,实际上delayMicroseconds(stepDelay);也就是延时1mS。然后实际运行中出现了异常,

那延时处理换成delay函数,
// 旋转指定步数
void rotateSteps(int steps) {
for(int i = 0; i < steps; i++) {
digitalWrite(PUL_PIN, HIGH);
//delayMicroseconds(stepDelay);
delay(1);
digitalWrite(PUL_PIN, LOW);
//delayMicroseconds(stepDelay);
delay(1);
}
}运转就正常,

根据经验看,感觉在使用delayMicroseconds函数时,可能导致了中断嵌套、堆栈溢出,发生了异常。
于是重新温习这两个延时函数的知识。
delay和delayMicroseconds都属于是阻塞式延时处理,前者是毫秒级别,后者是微秒级别。
调用delayMicroseconds(us)时,Arduino将参数值加载到定时器寄存器中,并禁用全局中断。长时间使用delayMicroseconds可能导致程序运行效率降低,建议结合millis()函数实现非阻塞延时。
millis和micros函数是非阻塞式处理函数,前者是毫秒级被,后者是微妙级别。因此如果想要维持微秒级的延迟,可以考虑下面的处理方式:
unsigned long previousMicros = 0;
const long interval = 1000000; // 1秒
unsigned long currentMicros = micros(); // 获取当前时间
if (currentMicros - previousMicros >= interval) {
previousMicros = currentMicros; // 更新上次时间
......
}按照这个思路,改造了程序:
// 旋转指定步数
void rotateSteps(int steps) {
for(int i = 0; i < steps; i++) {
digitalWrite(PUL_PIN, HIGH);
//delayMicroseconds(stepDelay);
//delay(1);
delayMicro(stepDelay);
digitalWrite(PUL_PIN, LOW);
//delayMicroseconds(stepDelay);
//delay(1);
delayMicro(stepDelay);
}
}
void delayMicro(uint32_t us) {
unsigned long previousMicros = micros();
while (true) {
if (micros() - previousMicros >= us) {
break;
}
}
}结果,仍然是出现了异常。

这下,真就理解不了了。
如果开发板的工作主频更高,代码执行周期更短,这样的异常还会产生吗?
我要赚赏金
