Arduino定时器和定时器中断

目录

一、定时器中断库函数方式说明

1、定时器中断编号和引脚说明

2、库文件安装

3、MsTimer2库文件使用

4、TimerOne库文件使用

5、注意事项

二、定时器的寄存器配置说明

1、定时器寄存器列表说明

2、Timer0寄存器说明

3、预分频系数与比较匹配器

4、定时器模式        


Arduino种关于定时器中断和PWM讲解的一些博客教程

https://blog.csdn.net/xq151750111/article/details/114885341

https://blog.csdn.net/weixin_51055384/article/details/124114222

https://blog.csdn.net/linZinan_/article/details/127832771

Arduino 定时器中断_arduino定时器中断-CSDN博客

一、定时器中断库函数方式说明

1、定时器中断编号和引脚说明

Arduino不同开发板对应的定时器编号和对应引脚

Arduino定时器和定时器中断_第1张图片

2、库文件安装

项目-加载库-库管理器,搜索和安装MsTimer2库文件

Arduino定时器和定时器中断_第2张图片

3、MsTimer2库文件使用

使用MsTimer2库文件,实现定时器中断实现Led输出500毫秒闪烁

代码

#include 

#define Led   22

//自定义中断响应函数
void MyTimerFlash() 
{
  static boolean output = HIGH;
  digitalWrite(Led, output);
  output = !output;
}

void setup() 
{
  pinMode(Led, OUTPUT);
  MsTimer2::set(500, MyTimerFlash);    // 500ms period
  MsTimer2::start();            // enables the interrupt.
  // MsTimer2::stop();          // disables the interrupt.
}

void loop() 
{
  
}

4、TimerOne库文件使用

使用TimerOne库文件, timer1 产生自定义载波频率下不同 pwm 占空比输出 和定时器中断。

实现功能:使用TimerOne库文件,实现定时器中断实现Led输出500毫秒闪烁

库文件安装

Arduino定时器和定时器中断_第3张图片

代码

#include 

#define Led   22

void callback()
{
    static boolean output = HIGH;
    digitalWrite(Led, output);      // 状态翻转
    output = !output;
}

void setup()
{
    pinMode(Led, OUTPUT);
    Timer1.initialize(500000);              // initialize timer1, and set a 1/2 second period
    //Timer1.pwm(9, 512);                     // setup pwm on pin 9, 50% duty cycle----UNO开发板定时器1引脚9、10
    Timer1.pwm(11, 512);                     // setup pwm on pin 9, 50% duty cycle----MEGA开发板定时器1引脚11、12
    Timer1.attachInterrupt(callback);       // attaches callback() as a timer overflow interrupt
}

void loop()
{
    
}

5、注意事项

(1)如果你使用了 MsTimer2 库, 则 pin11 和 pin3 就不能再用做 PWM 输出了! 因为该 pin3 和 pin11 的 PWM 是靠 timer2 帮忙的! (tone()也是)

(2)注意 Servo.h 库与 TimerOne 都是使用内部定时器 timer1 会影响pin 9, pin 10 的 PWM

(3)tone() 使用 timer2 定时器; 若使用 Tone 库的 Tone 对象(Tone 变量)也是优先使用 timer2 定时器,若用两个 Tone 变量则 timer1 也会被用掉, 用三个 Tone 则连控制 millis( )的 timer0 也会被用掉。

(4)别忘了, timer0 负责帮忙控制 pin 5 和 pin 6 的 PWM 输出。只要不去改变 timer 的 Prescaler 就不会影响其控制的 PWM pin, 但MsTimer2 库与 tone( )都会改变 Prescale

二、定时器的寄存器配置说明

      定时器对于单片机来说就类似我们现实生活中的时钟,记录很多和时间相关的事件。在我们平时经常使用的 delay() millis() ,micros() ,delayMicroseconds() ,PWM 波生成的 analogWrite() 和 tone() 函数都是通过定时器实现的,不过这些都被 Arduino 的封装库隐藏起来了,为了让使用者更快更便捷地开发项目。        

       我们平常使用的 Arduino 单片机为 UNO,NANO和MEGA 2560。UNO 和 NANO 都使用的是 ATmega328 芯片,这款芯片有3个定时器,Timer0,Timer1,Timer2,其中Timer0和Timer2都是8位寄存器(256),Timer1是16位寄存器(65536),意味着更高的分辨率。mege2560 使用的是 ATmege2560 芯片,这款芯片有 6 个定时器,在328 的基础上,增加了 Timer3,Timer4,Timer5。这三个定时器都是16位的寄存器。

1、定时器寄存器列表说明

 寄存器列表如下,x代表0,1,2,3,4,5这6种定时器。

Arduino定时器和定时器中断_第4张图片

2、Timer0寄存器说明

Timer0 的寄存器。其它的寄存器参见:https://download.csdn.net/download/xq151750111/15867135

Arduino定时器和定时器中断_第5张图片

3、预分频系数与比较匹配器

      Arduino UNO 时钟以16MHz运行。计数器的一个刻度值表示 1 / 16,000,000秒(~63ns),跑完1s需要计数值16,000,000。

(1)Timer0 和 Timer2 是8位定时器,可以存储最大计数器值255。

(2)Timer1 是一个16位定时器,可以存储最大计数器值65535。

一旦计数器达到其最大值,它将回到零(这称为溢出)。因此,需要对时钟频率进行分频处理,即预分频器。通过预分频器控制定时计数器的增量速度。预分频器与定时器的计数速度如下:

定时器速度(HZ) = Arduino UNO时钟速度(16MHz) / 预分频器系数

因此,1预分频器将以16MHz递增计数器,8预分频器将在2MHz递增,64预分频器= 250kHz,依此类推。

定时器 Timer0 的预分频系数配置如表:

Arduino定时器和定时器中断_第6张图片

Arduino定时器和定时器中断_第7张图片

4、定时器模式        

定时器可以配置为不同的模式。

(1)PWM模式。 纸浆宽度调制模式。 OCxy输出用于生成PWM信号

(2)CTC模式。 比较匹配时清除计时器。 当定时器计数器到达比较匹配寄存器时,定时器将被清除。        

定时器 Timer0 的模式选择配置如表:

Arduino定时器和定时器中断_第8张图片

5、 不同型号的开发定时器的配置

int toggle0,toggle1,toggle2;
  void setup(){

  cli();关闭全局中断

  //设置定时器0为10kHz(100us)
  TCCR0A = 0;//将整个TCCR0A寄存器设置为0
  TCCR0B = 0;//将整个TCCR0B寄存器设置为0
  TCNT0  = 0;//将计数器值初始化为0
  //设置计数器为10kHZ,即100us
  OCR0A = 24;//比较匹配寄存器= [16,000,000Hz /(预分频器*所需中断频率)] - 1
             //比较匹配寄存器=24,中断间隔=100us即中断频率10khz
  TCCR0A |= (1 << WGM01);//打开CTC模式
  TCCR0B |= (1 << CS01) | (1 << CS00); //设置CS01位为1,CS00位为1(64倍预分频)   
  TIMSK0 |= (1 << OCIE0A);//启用定时器比较中断
  

  //设置定时器1为1kHz
  TCCR1A = 0;//将整个TCCR1A寄存器设置为0
  TCCR1B = 0;//将整个TCCR1B寄存器设置为0
  TCNT1  = 0;//将计数器值初始化为0
  //设置计数器为1kHZ,即1ms
  OCR1A = 1999;// = (16*10^6)/(1000*8) - 1 (must be <65536)
  TCCR1B |= (1 << WGM12);//打开CTC模式
  TCCR1B |= (1 << CS11);//设置CS11位为1(8倍预分频)
  TIMSK1 |= (1 << OCIE1A);

  //设置定时器2为8kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for 8khz increments
  OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);//打开CTC模式
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS21);   
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);

  sei();//打开全局中断

}

//中断0服务函数
ISR(TIMER0_COMPA_vect){// timer0中断2Hz切换引脚13(LED)
//产生频率为10kHz / 2 = 5kHz的脉冲波
  if(toggle0){
    digitalWrite(8,HIGH);
    toggle0 = 0;
  }
  else{
    digitalWrite(8,LOW);
    toggle0 = 1;
  }
}

ISR(TIMER1_COMPA_vect){// timer1中断2Hz切换引脚13(LED)
//产生频率为2Hz / 2 = 1Hz的脉冲波
  if(toggle1>=500)
    digitalWrite(13,HIGH);
  if(toggle1<=500)
    digitalWrite(13,LOW);
  toggle1 += 1;
  if(toggle1 >= 1000)
    toggle1 = 0;
}
  
ISR(TIMER2_COMPA_vect){// timer2中断8kHz切换引脚9
//产生频率为8kHz / 2 = 4kHz的脉冲波
  if(toggle2){
    digitalWrite(9,HIGH);
    toggle2 = 0;
  }
  else{
    digitalWrite(9,LOW);
    toggle2 = 1;
  }
}
//loop function
void loop(){
  
}

你可能感兴趣的:(单片机,嵌入式硬件,Arduino)