Arduino Timer

Arduino Timer 用法

菜鸟日记

场景:循迹小车经过横线 beep响300ms,如果使用delay函数,影响代码的执行效率,因此考虑使用时间中断函数。
Arduino mega 2560的PWM口和timer的对应表

首先需要明确对timer的修改会影响对应pwm端口的准确执行
由于我的项目已经使用了这些口,所以只有Timer5 可供使用

const uint8_t P_MOTOR[4][2] = {{10, 8},
                               {6, 7},
                               {12, 11},
                               {4, 5}};

试验阶段 采用button按钮 按下代表循迹传感器扫过线

Timer5.initialize(300000);//timer的执行周期
Timer5.start();//定时器开始计数
Timer5.stop();//定时器停止计数
Timer5.restart();//查了库文件的代码,这个函数里面只有start()函数
Timer5.attachInterrupt(function);
Timer5.detachInterrupt();

timer的过程是:
头文件引用了TimerFive.h的库 就定义了一个Timer5的对象,initialize函数给了一个默认值1000000 然后计数器开始计数
如果计数器数到了initialize设置的值,产生一个中断信号
如果在这之前已经执行过了attachInterrupt(function)函数,就会执行这个function 同时中断标志复位
如果在这之前没有执行attachInterrupt()函数 也没有其他手段使中断标志清零 中断标志会一直存在 直到能有一个函数清零中断标志

setup()函数
这里最后一行需要加入一个stop()的原因是,如上所述由于引用了TimerFive库 即使还没有开始做任何的调用工作,定时器已经开始工作了,超过1s时间后就会置位中断标志位,那么一旦Timer5 attach一个函数后,不会等待一段时间,而是马上执行那个attach的函数
这里stop一下,保证程序开始后还没有按下按钮的那段时间,定时器没有溢出。

void setup()
{
    Serial.begin(9600);
    pinMode(P_BEEP, OUTPUT);
    digitalWrite(P_BEEP, OFF);//beep默认不响
    // Timer5.initialize(300000);
    Timer5.stop();
}

loop()函数
按钮按下调用beepsound()

void loop()
{
    while (buttonread())
    {
        beepsound();
    }
}

beepsound()函数

void beepsound(void)
{
    digitalWrite(P_BEEP, ON);
	Timer5.setPeriod(300000);//中断函数中stop了 为什么这里不用start 最后面讲
    Timer5.attachInterrupt(beepdesound);
}

beepdesound()

void beepdsound(void)
{
    Timer5.stop();//同理setup里面 一旦退出 就停止计时器 防止中断标志被置位 影响下一次beep
    digitalWrite(P_BEEP, OFF);
    Timer5.detachInterrupt();
}

最后这是比较坑的地方

void start() __attribute__((always_inline)) {
	TCCR5B = 0;
	TCNT5 = 0;		// TODO: does this cause an undesired interrupt?
	resume();
    }

打开源代码 看了一眼 start()这里写了一句话 does this cause an undesired interrupt? 还是问好结尾
然后绝了 执行start()是真的会产生了一个额外的中断信号
为了验证我这个想法我把beepsound 改成了这样

void beepsound(void)
{
    digitalWrite(P_BEEP, ON);
    Timer5.start();
    Timer5.attachInterrupt(empty);//empty是一个空的子函数
    Serial.println(0);//这里是为了等一下 使得attach empty 成功
    Timer5.attachInterrupt(beepdsound);
}

上文提到 attachInterrupt会软件自动清零中断标志一次 然后就可以用了 一切正常

void attachInterrupt(void (*isr)()) __attribute__((always_inline)) 
{
	isrCallback = isr;
	TIMSK5 = _BV(TOIE5);//这一行应该就是清零中断标志的代码
}

为什么会产生额外中断 具体原因还没细究 要翻一下avr atmega2560 的数据手册
试出来反正start换成Timer5.initialize(300000)就可以用了

end

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页