目录
0.arduino uno的定时器:
timer0:一个被Arduino的delay(), millis()和micros()使用的8位定时器
timer1:一个被Arduino的Servo()库使用的16位定时器
timer2:一个被Arduino的Tone()库使用的8位定时器
"Arduino Mega"板有另外三个可使用的timer(3,4,5)
1.TimerOne 说明
Timer1是一个16位定时器
如果你使用了 Timer1 库 (TimerOne 库), pin 9 和 pin 10 就不能再用做 PWM 输出了!
timer1 的PWM通道是pin 9 和 pin 10
注意 Servo.h 库使用定时器 timer1,所以, 用了 TimerOne 也不能再用 Servo.h 库了
技术文档: TimerOne & Timer三个Arduino库
经测试,TimerOne 的精度可以达到10us.下面给出一个demo方便大家理解.
2.10us中断,定时1s的demo.
10us触发一次中断 累加100000次 也就是1s将标志位置1,实现1s执行一次命令.
其中里面的ms_tick本来想设置int型,arduino中的int型是2字节的 范围是-32768~32767.
累加100000次超量程了,这里采用long类型.
关于volatile的运用,道友们可以去单独了解一下.
Timer1.initialize(10); //设置定时器的周期 ,这里是10us
Timer1.attachInterrupt(Interrupt_callback); // 定时器的中断回调函数
Timer1.setPeriod(microseconds);//设置定时器的周期
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
pinMode(13, OUTPUT);
Timer1.initialize(10);//精确度10us
Timer1.attachInterrupt(Interrupt_callback); // 定时器的中断回调函数
Serial.begin(115200);
}
void Interrupt_callback(void)
{
if(ms_tick_flag==0)
{
ms_tick++;
if(ms_tick>100000)//这里10*100000 也就是1s标志位置1.
{
ms_tick=0;
ms_tick_flag=1;
}
}
}
void loop(void)
{
if(ms_tick_flag==1)
{
static boolean output = HIGH;
digitalWrite(13,output);
output =!output;
Serial.println("test");
ms_tick_flag=0;
}
}
3.TimerOne的PWM的使用
Timer1.pwm(pin,duty,Frequency); //PWM初始化,第二个变量是 “duty” 是从 0 到 1023 ,通过改变它来改变占空比,第三个频率,可以不填. Timer1.initialize(10);//这个是设置周期,也相当于设置频率
Timer1.setPwmDuty(pin,duty) ; //设置PWM的占空比,不需要再重新初始化引脚,相较于Timer1.pwm速度快
Timer1.disablePwm(pin); //关闭PWM
TimerOne的PWM有什么优势和区别呢?
简单的操作方法.一行代码就可设定PWM频率
arduino的analogWrite();也能实现PWM的功能,主要原因是arduino自带的analogWrite()函数的PWM的默认频率:
timer0 控制 pin 5, pin 6, PWM 频率 976.5625Hz, duty cycle可以 2/256 ~ 255/256 (对应 1 到254);
timer1 控制 pin 9, pin 10, PWM 频率 490.196Hz, duty cycle 可以 1/255 ~ 254/255(对应 1 到254);
timer2 控制 pin 11, pin 3, PWM 频率 与 duty cycle 跟 timer1 控制的相同 !
Timer1.pwm(pin,duty,Frequency);可以设定PWM的频率,对某些设备如步进电机对脉冲信号有要求.
实现呼吸灯的demo(加上定时器)
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
Timer1.initialize(10);//精确度10us
Timer1.pwm(9,0);
Timer1.attachInterrupt(Interrupt_callback); // 定时器的中断回调函数
Serial.begin(115200);
}
void Interrupt_callback(void)
{
if(ms_tick_flag==0)
{
ms_tick++;
if(ms_tick>100)//这里1ms触发一次 1秒内实现一个上升期 2s完成亮灭.
{
ms_tick=0;
ms_tick_flag=1;
}
}
}
void loop(void)
{
if(ms_tick_flag==1)
{
static int i=0,flag=0;
if(i<=0)
flag=0;
if(i>=1023)
flag=1;
if(flag==0)
i++;
else
i--;
Timer1.setPwmDuty(9, i); // setup pwm on pin 9, 50% duty cycle
ms_tick_flag=0;
}
}
极其简单的呼吸灯demo,更易理解TimerOne的PWM
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
Timer1.initialize(10);//精确度10us
Timer1.pwm(9,0);
Serial.begin(115200);
}
void loop(void)
{
static int i=0,flag=0;
//这两个if语句主要是为了实现亮灭亮交替
if(i<=0)
flag=0;
if(i>=1023)
flag=1;
if(flag==0)
i++;
else
i--;
delay(1);
Timer1.setPwmDuty(9, i); // setup pwm on pin 9, 50% duty cycle
}
4.0PWM核心代码
#include <TimerOne.h>
volatile long ms_tick=0,ms_tick_flag=0;
void setup(void)
{
Timer1.initialize(10);//精确度10us
Timer1.pwm(9,0);//0-1023 控制占空比
Serial.begin(115200);
}
void loop(void)
{
}