AVR/Arduino定时/计数器、中断入门

2019-12-04来源: eefocus关键字:AVR  Arduino  定时  计数器  中断

在Arduino中,可以使用AnalogWrite来使用硬件产生490Hz/980Hz的pwm波,并可根据参数来设定占空比。不了解这个的同学可以去AnalogWrite学习下,SecretsOfArduinoPWM也是讲了Arduino在avr的定时/计数器上做的封装,我们这里并不讲Arduino相关,而是讲AVR的定时/计数器,如何产生更多PWM波和定时/计数器的中断使用。

AVR Timer/Counter(以下统称Timer)

以ATmega358p为例,其内部拥有一个16位计时器,两个8位计时器,下图则为16位计时器的大致图解:

对于没有接触过avr内部的Arduino同学来说,这张图看不出来任何意思,别急,这些都是AVR-GCC里定义的缩写,我们先来解释下图中的缩写对照:

缩写全称
TCNTTimer/Counter Register
TCCRTimer/Counter Control Register
OCROutput Compare Register
OCOutput Compare Match Output
ICRInput Capture Register
Int.ReqInterrupt Request
TOVTimer Overflow
ICFInput Capture Flag

而图中TCNT为主要工作部件,其工作模式的是依据TCCR的设定值。以该16位计时器为例,该计时器在ATmega358p中的序号为1,则其所有缩写都会与1有关,即TCNT1的工作模式由TCCR1A和TCCR1B来决定。不急着看别的,我们先来瞅瞅TCCR1A与TCCR1B是怎么来配置TCNT1的工作模式的:

TCCR1A:

图中7、6、5、4位分别应该是COM1A1、COM1A0、COM1B1、COM1B0,话说这datasheet有时候也真是会省事儿

TCCR1B:

这两个寄存器都是八位寄存器,再来一张表来对照一下图中的缩写:

缩写全称
COMnACompare Output Mode for Channel A
COMnBCompare Output Mode for Channel B
WGMWave Generation Mode
ICNCInput Capture Noise Canceler
ICESInput Capture Edge Select
CSClock Select

我们通过配置这两个寄存器来控制TCNT1的工作模式,通过配置WGM来选择波型生成模式,主要有Fast PWM/PWM Phase Correct/CTC模式,并且也拥有不同的计数TOP值,有0xFF/ICR1/OCR1A等,通过COM结合WGM对针脚的输出做配置,用CS来选择生成波型的prescaler,分别有1/8/64/256/1024,或者外部时钟。TOP值为ICR1或OCR1A时,要对使用的寄存器进行赋值。工作模式中,Fast PWM与PWM Phase Correct这两种计数模式不同的是,PWM Phase Correct可以到达top值后又递减至0,Fast PWM到达top值后则会触发上升或下降沿。

如下配置:


TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);

TCCR1B = _BV(CS12) | _BV(CS10);

//WGM配置了PWM Phase Correct,使用的TOP值为0x00FF

//COM配置了在往上计数时清零,往下计数时置位

//使用了1024的prescaler

OCR1A = 100;

OCR1B = 50;


则我们可以得到的时钟频率为Fclk/(prescaler*TOP)=16000000/(1024*255)/2=30.63Hz,且OC1A占空比为OCR1A/TOP=100/255=39%,OC1B占空比为OCR1B/TOP=50/255=19.6%。

更多配置组合请看SecretsOfArduinoPWM/PWM的秘密或直接datasheet,其中要注意的是,使用OCR1A为TOP值时,可以在一定范围内配置任意频率,但OC1A的占空比为始终为50%,OC1B的占空比为(OCR1B+1)/(OCR1A+1)。

Interrupt

中断是其它与CPU异步进行的硬件与CPU交互的一种方法。这样我们就不用在CPU中去等待其它某些任务的完成和触发状态,由其它硬件去来触发进入CPU主进程的时机。回头看第一张大图,在图中可以找到四处(Int.Req),分别是TOVn(Timer/Counter Overflow), OCnA(Output Compare A Match), OCnB(Output Compare B Match), ICF(Input Capture Flag),根据字义我们便可了解到该中断的作用,在使用中断时,我们要先于TIMSK1(Timer/Counter 1 Interrupt Mask Register)中开启相应的中断位。

下图为TIMSK1:

图中的字母应为ICIE1, OCIE1B, OCIE1A, TOIE1,这数据手册,也是太懒了。下表为对照:

缩写全称
ICIEInput Capture Interrupt Enable
OCIEOutput Compare Interrupt Enable
TOIETimer/Counter Overflow Interrupt Enable

开启该遮罩位后,便可打开中断,前提也是在全局中断打开的情况下(sei()为打开全局中断,cli()为关闭全局中断)。在当下的AVR-GCC环境中,我们使用宏命令ISR来定义中断程序,使用方法如下:


ISR(xxxx_vect)

{

    // user code here

}


而这里的xxxx_vect则是要监听的中断向量地址,可以于Atmel官网: Interrupts上找得到所有中断对应的向量名称。

如上面的四种向量,于mega328p中,则分别对应:

ICIE1TIMER1_CAPT_vect
OCIE1ATIMER1_COMPA_vect
OCIE1BTIMER1_COMPB_vect
TOIE1TIMER1_OVF_vect

而中断又分为两种,一种为事件触发型,这种中断会在上一个中断没有运行结束前队列等待,直至前面优先的任务完成后才能执行;另一种为中断条件触发,如果上一个中断还没有返回回来,那么则不会触发这个中断(如果定时器为高频时则会出现该情况)。所以在使用中断的时候,进入中断、跳转、返回都需要耗费时钟,不要对高频使用中断,甚至会使主线程一直处于堆栈状态,且中断中不要运行太多程序。


There are basically two types of interrupts: The first type is triggered by an event that sets the Interrupt Flag. The second type of interrupts will trigger as long as the interrupt condition is present


The traps when using interrupts中也是罗列了一些使用中断的坑和技巧,可以看看。附上Atmega328p的datasheet,真是有问题就看datasheet,上面的图与摘录都是从datasheet里出来的。

Have fun

关键字:AVR  Arduino  定时  计数器  中断 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic481955.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:AVR GCC对端口的操作指南
下一篇:LED 驱动控制专用电路 TM1628 AVR 测试程序源代码

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

AVR开发 Arduino方法(四) 串行通信子系统
  Arduino UNO R3主处理器ATMega328P的串行通信子系统可以用于与计算机、外设或其他微控制器进行通信,它支持3种串行通信方式:通用同步/异步收发器,串行外设接口和两线串行接口。1. 通用同步/异步收发器  在串行通信中,波特率用来衡量传输速率的快慢,同步和异步的对象是波特率的时钟信号;同步通信的设备之间需要一条额外的时钟线,也因此同步方式可以提供更高的波特率;这里将以异步为例。  下面的示例可以使通过串口发送给Arduino的数据回显到串口监视器上: 1 // SerialEcho.ino 2 char data; 3  4 void
发表于 2019-12-05
AVR开发 Arduino方法(四) 串行通信子系统
AVR开发 Arduino方法(三) 定时/计数器子系统
Arduino UNO R3的主处理器ATMega328P拥有3个定时/计数器,它们分别是Timer0,Timer1和Timer2;它们都通过对来自内部或外部的脉冲信号进行计数的方式完成基本的定时/计数功能以及一些其他的功能。Timer0和Timer2是8位定时/计时器,Timer1是16位定时/计数器;下面以Timer2为例讨论定时/计数器子系统的典型应用,这些内容同样适用于Timer0和Timer1。1. 精准延时在前面的例子中,已经使用了一些与精准延时相关的Arduino库函数:   delay(ms):延迟一段时间  ms:延迟的时长,单位是毫秒 请注意,上面的
发表于 2019-12-05
AVR开发 Arduino方法(三) 定时/计数器子系统
AVR开发 Arduino方法(二) 中断子系统
在了解中断子系统之前,首先要了解中断的概念。你正在看书,这时电话响了,你会怎么做呢?相信大多数人会这样:先标记看到的位置,接完电话回来后继续阅读。这就是一个现实生活中中断的例子,我们把“电话响了”成为中断源。Arduino UNO R3的主处理器ATMega328P拥有26个中断源,如下表所示:向量号程序地址中断源中断定义中断服务程序名称10x0000RESET外部电平复位,上电复位,掉电检测复位,看门狗复位20x0002INT0外部中断请求0INT0_vect30x0004INT1外部中断请求1INT1_vect40x0006PCINT0引脚电平变化中断请求0PCINT0_vect50x0008PCINT1
发表于 2019-12-05
AVR开发 Arduino方法(一) 端口子系统
  Arduino UNO R3的主处理器ATMega328P上有3个8位的输入/输出端口,分别是PB,PC和PD。Arduino IDE提供的Blink示例可以帮助我们了解端口的数字输出功能:  1 // Blink.ino 2 int led = 13; 3  4 void setup() { 5   pinMode(led, OUTPUT); 6 } 7  8 void loop() { 9   digitalWrite(led, HIGH);10  &nbs
发表于 2019-12-05
AVR开发 Arduino方法(一) 端口子系统
AVR开发 Arduino方法(附一) 工具链与调试技术
开“AVR Source Code”和“AVR Variables”对话框,从中可以查看程序源代码以及变量值的情况:从“AVR Source Code”对话框中找到主函数,找到setup()函数和loop()函数的调用语句,双击打上断点,运行到断点处,就可以开始调试了:(2) 使用Visual Studio进行硬件调试安装带有C++组件2012或更新版本的Visual Studio后,在http://www.visualmicro.com/page/Arduino-Visual-Studio-Downloads.aspx中下载Visual 
发表于 2019-12-05
AVR开发 Arduino方法(附一) 工具链与调试技术
AVR+FPGA实现六路闭环电流控制程序
library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity XTKZQ isport(    rst,clk        :    in        std_logic;    --时钟和复位信号,复位信号由AVR初始化手动给出    --avr 读写相关信号线    ale,rd
发表于 2019-12-05
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved