查看: 18658|回复: 6

arduinoTimer1定时中断

[复制链接]
  • TA的每日心情
    开心
    2016-5-17 14:55
  • 签到天数: 9 天

    [LV.3]偶尔看看II

    发表于 2016-5-30 17:21 | 显示全部楼层 |阅读模式
    本帖最后由 goxushunchao2 于 2016-5-30 17:21 编辑

    arduino定时器包含定时器/计数器0,定时器/计数器1,定时器/计数器2三个。定时器/计数器0和定时器/计数器2是一个8位的计数器,定时器/计数器1是一个16位长的计数器。timer1最大值为65535,在使用之前我们需要进行一些设置,从而使得timer1可以运行起来。进行这些设置,我们需要用内置的寄存器来存储这些设置。每一个定时器都有很多寄存器,本篇文章主要侧重timer1 的介绍和使用。存储这些初始值的寄存器的两个寄存器TCCRXA,TCCRXB(其中X代表序号定时器的编号0,1,2).其中TCCR是英文Timer/Counter Control Register简写,下面是TCCR1A和TCCR1B的具体情况。每个寄存器共8位,每位都存储了一些值来进行定时器的设置。表引用自:http://www.atmel.com/dyn/product ... 60&part_id=4198

    开始使用timer1的话,CS12, CS11和CS10的设置是很重要的。这三个值得设置可以让定时器工作在不同的频率。不同的设置的频率如下表所示:


    默认的,这些值都是为0的,我们用一个例子来说明问题。下边这个例子是设置定时器1溢出中断,在溢出的时候我们让2号引脚连接的LED灯亮灭转换。首先我们来进行初始化timer1。
    //包含avr-lib库
    #include <avr/io.h>
    #include <avr/interrupt.h>

    #define LEDPIN 2

    void setup()
    {
        pinMode(LEDPIN, OUTPUT);

        // 初始化timer1
        cli();             //禁止全局中断
        TCCR1A = 0;        //设置TCCR1A全为0
        TCCR1B = 0;

        // 设置允许timer溢出中断
        TIMSK1 = (1 << TOIE1);
        //设置CS10位为1从而使定时器以时钟的速度运行。
        TCCR1B |= (1 << CS10);
        /允许全局中断
        sei();
    }

    在上边这段代码中TIMSK1代表的是Timer/Counter1 Interrupt Mask Register.这个寄存器控制着timer允许怎样的中断。其中TOIE1表示的溢出中断。其他的后边会继续介绍。
    由于我们上班设置了CS10,定时器1就会开始工作。当定时器1溢出时就会执行中断服务程序中断服务程序如下:
    ISR(TIMER1_OVF_vect)
    {
        digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    }
    这样,我们就可以让loop不做任何事情了,加入我们要停止中断只用设置TCCR1B为0就可以了。
    上班每次的中断时间大概为((1/16)*e-6)*65535=0.0041us,时间比较短,假若我们想要更长的时间,我们可以设置CS11,CS12,组合来进行设置。这样我们的时间就可以变化了。
    比如下边的例子:
    void setup()
    {
        pinMode(LEDPIN, OUTPUT);

        // 初始化timer1
        cli();             //禁止全局中断
        TCCR1A = 0;        //设置TCCR1A全为0
        TCCR1B = 0;

        // 设置允许timer溢出中断
        TIMSK1 = (1 << TOIE1);
        //设置CS10位为1从而使定时器以时钟的速度运行。
          TCCR1B |= (1 << CS10);
          TCCR1B |= (1 << CS12);



        sei();
    }
    [size=1em]这样我们的时间就(1/16000000)*1024*65536=4.1s,





    再者,加入我们想要确定的时间而不是定时器溢出来做中断,怎么做呢,
    在定时器中断有另外一个模式叫做CTC(Clear Timer on Compare Match),在这个模式下,timer1不在是溢出中断了,而是在寄存器中设定好的值进行比较,若大于则进入中断,这种模式的设置例子如下:
    void setup()
    {
        pinMode(LEDPIN, OUTPUT);

        // 初始化timer1
        cli();          // 进制全局中断
        TCCR1A = 0;     //设置TCCR1A全为0
        TCCR1B = 0;     // [size=1em]设置TCCR1B全为0


        //设置比较的值得大小
        OCR1A = 15624;
        // 开启CTC模式
        TCCR1B |= (1 << WGM12);
        // 设置 CS10和CS12位
        TCCR1B |= (1 << CS10);
        TCCR1B |= (1 << CS12);
        // 允许比较中断
        TIMSK1 |= (1 << OCIE1A);
        sei();          // 允许全局中断
    }
    ISR(TIMER1_COMPA_vect)
    {
        digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    }


    在这里:
    目标时间=时间周期*(时钟次数+1)
    时钟次数+1=目标时间/时钟周期,
    比如说我们要获取一秒的时间,则定时器1 的数值改变次数为1000/((1/16000000)*1024)
    如果想要获取更长的时间;比如说10秒,又要防止溢出,可以这样写
    ISR(TIMER1_COMPA_vect)
    {
        seconds++;
        if (seconds == 10)
        {
            seconds = 0;
            readMySensor();
        }
    }




  • TA的每日心情
    开心
    2016-5-17 14:55
  • 签到天数: 9 天

    [LV.3]偶尔看看II

     楼主| 发表于 2016-5-30 17:22 | 显示全部楼层
  • TA的每日心情
    开心
    2016-12-24 14:31
  • 签到天数: 108 天

    [LV.6]常住居民II

    发表于 2016-5-30 18:53 | 显示全部楼层
    ddddddddddddddddddd
  • TA的每日心情
    无聊
    2018-11-26 09:49
  • 签到天数: 254 天

    [LV.8]以坛为家I

    发表于 2016-6-10 20:50 | 显示全部楼层
    avr/io.h和avr/interrupt.h这两个文件,哪里有啊。能给一个吗?谢谢!
    打赏作者鼓励一下!
  • TA的每日心情
    无聊
    2018-11-26 09:49
  • 签到天数: 254 天

    [LV.8]以坛为家I

    发表于 2016-6-11 16:47 | 显示全部楼层
    这个函数:”readMySensor()“无法通过编译,是缺某个库文件吗?
    打赏作者鼓励一下!
  • TA的每日心情
    奋斗
    2017-5-15 10:55
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2017-5-10 11:39 | 显示全部楼层
    avr/io.h和avr/interrupt.h这两个文件,哪里有啊
  • TA的每日心情
    奋斗
    2019-1-25 22:57
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2019-1-25 22:10 | 显示全部楼层
    djzwxx 发表于 2016-6-11 16:47
    这个函数:”readMySensor()“无法通过编译,是缺某个库文件吗?

    这个函数应该是作者自己的应用函数,你自己编一个就行,名字随便取。因为已经进入中断了,你总要干点什么吧。
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    KittenBot杯第六届开源硬件开发大赛启动啦
    KittenBot杯第六届开源硬
    大赛简介: 第六届开源硬件开发大赛由Arduino中文社区发起 由KittenBot冠名赞助
    Blinker 模拟传感器+数字传感器例程(DHT11 温湿度+气体传感)
    Blinker 模拟传感器+数字
    才接触1星期,发现Blinker自带了很多例程,已经成功试验了DHT的例程序,并完善了体
    一文教你选择Arduino开发板,小白进
    一文教你选择Arduino开发
    笔者在2016年接触了Arduino,跳了万条坑,行了千里弯,到今天也算是Arduino的一
    [发布帖]RPG游戏 无人世界
    [发布帖]RPG游戏 无人世界
    视频攻略:https://www.bilibili.com/video/av43790997/ (b站正在审核) 剧情:主角是
    【人脸识别】ESP-EYE 最新的板子到货了
    【人脸识别】ESP-EYE 最新
    1.我不会编程,最多抄几个一步一步的网络教程。 2.不知道为啥就是超级喜欢电子元件。
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表