用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

点击进入授权页面

只需一步,快速开始

  • QQ空间
  • 回复
  • 收藏
  • TA的每日心情
    开心
    2017-7-3 15:02
  • 签到天数: 56 天

    [LV.5]常住居民I

    本帖最后由 甲基红橙黄绿蓝 于 2017-5-1 22:28 编辑

    概述:

    CurieTimerOne是Arduino101的定时器库。可用于定时中断和PWM。实际上ARC核心有两个定时器:Timer0是系统定时器,Timer1在CureTimerOne中为用户所使用。本帖将Timer0作为另一个定时器,编写库CurieTimerZero,实现和Timer1相同的功能。





    目的:        编写一个Arduino 101可用的额外的定时器库CurieTimerZero,并提供下载和使用说明。





    可行性分析:


    我阅读了相关库的代码,发现Timer0用于以下这几个函数:
    • delay                               延时若干毫秒
    • delayMicroseconds        延时若干微秒
    • delayTicks                       延迟若干个Tick,每个Tick是1/32微秒
    • millis                               获取101已经运行的时间,单位为毫秒
    • micros                                 获取101已经运行的时间,单位为微秒

    如果把Timer0为用户使用,这些函数就不能用了。其中delay的替代方案是软件实现(运行空循环),下面的delaySoft可以替代delay函数。而millis和micros函数是没有替代方案的。无法与CurieTimerZero共用。

    [C++] 纯文本查看 复制代码
    void delaySoft(volatile uint32_t us){
      for(;us>0;us--)
        for(volatile uint32_t i=0;i<2456;i++);
    }
    








    CurieTimerZero 实现过程:


    经过对各种库、寄存器的一番研究,终于折腾出了CurieTimerZero库,与CurieTimerOne完全一样,也能进行定时中断和PWM输出。
    我编写的文件包括CurieTimerZero.h和CurieTimerZero.cpp。我不建议大家把它封装成库放在Arduino IDE的library下,因为它与Arduino的那几个内置函数是矛盾的,这有悖于Arduino的“通用硬件平台”的精神。我的建议是,只在需要使用更多定时器的场合,把这两个文件加入你的项目即可。





    CurieTimerZero 使用方法:
    首先,你需要下载本帖末尾的.zip包。下载库和示例代码请看本帖最后面的附件!该附件包括两个库文件CurieTimerZero.cpp和CurieTimerZero.h以及一个测试文件TimerZeroTest.ino。
    当你的一个Arduino 101程序需要用到额外的定时器时,把里面的CurieTimerZero.h和CurieTimerZero.cpp复制进你的项目目录,如下图:
    timerzero_show.png
    比方说你的项目主文件为TimerZeroTest.ino,则在TimerZeroTest.ino中#include "CurieTimerZero.h"  就可以。用法和CurieTimerOne库相同,具体例程请参考下文。






    两个例程:

    此处给出定时中断和PWM两个例程,其中需要的CurieTimerZero.h库请前往本帖最后下载
    1、定时中断:
    以下程序用两个定时器配合,实现了一个“呼吸闪灯”的效果。Timer0每50ms反转一次LED的电平、Timer0每51ms反转一次LED的电平。每经过一个周期,二者错开1ms,最后效果是:LED第一次亮持续1ms,第二次亮持续2ms,以此类推……  产生了“呼吸闪灯的效果”。
    [C++] 纯文本查看 复制代码
    #include "CurieTimerOne.h"
    #include "CurieTimerZero.h"
    
    // 该函数把板载LED灯反转
    void timeInterrupt(){
      static uint8_t toggle = 0;
      digitalWrite(13, toggle);
      toggle = !toggle;
    }
    
    void setup() {
      pinMode(13,OUTPUT);
      // 启动Timer0作为定时中断器,每50毫秒执行一次timerInterrupt函数
      CurieTimerZero.start(50000, &timeInterrupt);
      // 启动Timer1作为定时中断器,每51毫秒执行一次timerInterrupt函数
      CurieTimerOne.start (51000, &timeInterrupt);
    }
    
    void loop() {
    }
    
    



    2、PWM
    以下程序使用两个定时器同时地,不互相干扰地分别在12号和13号引脚输出PWM。你可以把一个LED灯插在12号引脚上,观察到它与板载LED的闪烁节奏完全不合,这仅用一个定时器是无法实现的。
    [C++] 纯文本查看 复制代码
    #include "CurieTimerOne.h"
    #include "CurieTimerZero.h"
    
    void setup() {
      // Timer0在 13 号引脚输出周期0.5秒,占空比20%的PWM信号
      CurieTimerZero.pwmStart(13, 20.0, 500000);    // Timer1在 12 号引脚输出周期0.8秒,占空比70%的PWM信号
      CurieTimerOne.pwmStart (12, 70.0, 800000);
    }
    
    void loop() {
    }
    








    问题报告:


    根据题主进行的测试,目前为止只有delay、delayMicroseconds、delayTicks、millis、micros函数无法和该库共用。而串口、GPIO、PWM、IMU、BLE都未受到CurieTimerZero库的影响。若有人出现其他库不能用的情况,可以在回帖里告知我。
    (注:此处的PWM是指3、5、6、9号引脚上的不可调频率的PWM,即analogWrite函数,它与CurieTimerOne和CurieTimerZero是互不干扰的)





    下载:
    游客,如果您要查看本帖隐藏内容请回复












    打赏作者鼓励一下!

    1人打赏


    有什么问题吗?
    打赏作者鼓励一下!
    3Q for sharing.
    感谢楼主的分享,学习到不少的东西。
    不错,赞赞赞赞赞赞赞
    123下一页
    发新帖
    发表评论
    高级模式  
    您需要登录后才可以回帖 登录 | 立即注册  
    关闭

    推荐主题 上一条 /2 下一条