分享

【CurieTimerZero】一个额外的定时器

 容斋承筐 2017-09-13
本帖最后由 甲基红橙黄绿蓝 于 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++] 纯文本查看 复制代码
代码
001
002
003
004
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复制进你的项目目录,如下图:

比方说你的项目主文件为TimerZeroTest.ino,则在TimerZeroTest.ino中#include "CurieTimerZero.h"  就可以。用法和CurieTimerOne库相同,具体例程请参考下文。






两个例程:

此处给出定时中断和PWM两个例程,其中需要的CurieTimerZero.h库请前往本帖最后下载
1、定时中断:
以下程序用两个定时器配合,实现了一个“呼吸闪灯”的效果。Timer0每50ms反转一次LED的电平、Timer0每51ms反转一次LED的电平。每经过一个周期,二者错开1ms,最后效果是:LED第一次亮持续1ms,第二次亮持续2ms,以此类推……  产生了“呼吸闪灯的效果”。
[C++] 纯文本查看 复制代码
代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
#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++] 纯文本查看 复制代码
代码
001
002
003
004
005
006
007
008
009
010
011
#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是互不干扰的)





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












    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多