AVR定时(计数)器工作原理

发布者:谁与争锋1最新更新时间:2016-10-20 来源: eefocus关键字:AVR  定时器  工作原理 手机看文章 扫描二维码
随时随地手机看文章
定时器是独立运行的,它不占用CPU的时间,不需要指令,只有调用对应的寄存器的时候才需要参与。
以AVR mega16为例,它有三个寄存器,timer0,timer1和timer2,T0和T2是8位定时器,T1是16位寄存器,T2为异步定时器,三个定时器都可以用于产生PWM。
以定时器T0来简单介绍定时器的操作方法,T0有三个寄存器可以被CPU访问,TCCR0,TCNT0,OCR0,下面看一段ICC生成的定时器初始化程序。
CODE:
//TIMER0 initialize - prescale:8
// WGM: Normal
// desired value: 1KHz
// actual value: 1.000KHz (0.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
OCR0 = 0x7D; //set compare
TCCR0 = 0x02; //start timer
}
[Copy to clipboard][/url]
TCCR0为控制寄存器,用于控制定时器的工作模式细节;
TCNT0为T/C 寄存器,它的值在定时器的每个工作周期里加一或减一,实现定时操作,CPU可以随时读写TCNT0;
OCR0:输出比较寄存器,它包含一个8 位的数据,不间断地与计数器数值TCNT0 进行比较。匹配事件可以用来产生输出比较中断,或者用来在OC0 引脚上产生波形。
这里说最简单的模式,TCNT一直加一,到达最大值0xFF然后清零,进入下一次计数,在上面的程序中。
TCCR0=0x00;关闭T0的时钟源,定时器停止工作。
TCNT0=0x83;设置T/C寄存器的初始值,及让定时器从TCNT0从0x83开始定时或计数。
OCR0 = 0x7D;设定比较匹配寄存器的值,这个程序里没有使用。
TCCR0 = 0x02;选择时钟源,来自时钟8分频,设置后定时器就开始工作。
初始化后定时器开始工作,TCNT0在每一个定时器时钟加一,当TCNT0等于OCR0的值时,T/C 中断标志寄存器- TIFR中的OCF0 置位,如果这时候TIMSK中OCIE0为1(即允许T0比较匹配中断),并且全局中断允许,比较匹配中断即运行。中断程序中可以对TCNT0和0CR0进行操作,对定时器进行调整。
TCNT0继续加一,当达到0xFF时,T/C 中断标志寄存器- TIFR中的TOV0置位,如果这时候TIMSK中TOIE0为1(即允许T0溢出中断),并且全局中断允许,溢出中断即运行。中断程序中可以对TCNT0和0CR0进行操作,对定时器进行调整。
和定时器相关的寄存器还有SREG和TIMSK,前者位1控制全局中段允许,后者位1(OCIE0)和位0(TOIE0)分别控制比较匹配中断和溢出比较匹配中断允许。
实际的过程中,定时器相关寄存器的操作非常灵活,可以在溢出中断中修改TCNT0的值,也可以在中断中修改OCR0的值,后面的实验中会讲到用定时器1修改OCR1A的方法实现1S精确定时。
师傅领进门,修行靠个人,定时器的基本原理说到这里,要更深入的了解定时器,请看数据手册。
定时公式:Time=PRE*(MAX-TCNT0+1) /F_cpu单位S ,其中,PRE为与分频数,本例中为8,MAX即为最大值255,TCNT0为初始化时的值,本例中为0x83(十进制的131),T_cpu,系统时钟频率,本例中为1000000。
本例程序中定时时间为:Time=8*(255-131+1)/1000000=0.001 S ,即为1ms,1Khz。可以看出,如果晶振选为8M,则定时时间变为0.000125S,也就是说晶振越大,定时时间越短,预分频越大,定时越长。
在设置时如果你选择1ms,会得到如下结果,和上面的1Khz相同。
CODE:
//TIMER0 initialize - prescale:8
// WGM: Normal
// desired value: 1mSec
// actual value: 1.000mSec (0.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
OCR0 = 0x7D; //set compare
TCCR0 = 0x02; //start timer
}

//ICC-AVR application builder : 2007-6-9 0:33:58
// Target : M16
// Crystal: 1.0000Mhz
// 用途:演示定时器的工作原理
// 作者:古欣
// AVR与虚拟仪器 http://www.avrvi.com
#include
#include

void port_init(void)
{
PORTA = 0x00;
DDRA = 0x03; //PA0 PA1 输出
PORTB = 0x00;
DDRB = 0xFF; //PB 输出
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}

//TIMER0 initialize - prescale:8
// WGM: Normal
// desired value: 1KHz
// actual value: 1.000KHz (0.0%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x83; //set count
OCR0 = 0x7D; //set compare
TCCR0 = 0x02; //start timer
}

//比较匹配中断
#pragma interrupt_handler timer0_comp_isr:20
void timer0_comp_isr(void)
{
//compare occured TCNT0=OCR0
if(OCR0==0x7D) //调整0x7D
{
OCR0=0x7F;
}
else
{
OCR0=0x7D;
}
PORTA ^= 0x01; //PA0取反
}

//溢出中断中断
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x83; //reload counter value
PORTA ^= 0x01; //PA0取反
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();

MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x03; //timer interrupt sources 允许定时器零匹配和溢出中断
SEI(); //re-enable interrupts
//all peripherals are now initialized
}

void main(void)
{
init_devices();
PORTA=0x00;
while(1)
{
PORTB = TCNT0; //任何时候都可以读TCNT0
}
}
 
 
在门禁软件中:
void timer0_init(void)
{
TCCR0 = 0x00; //stop      P94 T/C控制寄存器
ASSR = 0x00; //set async mode    异步状态寄存器
TCNT0 = 0xD9; //set count     T/C寄存器(0b11011001)
OCR0 = 0x27; //中断时TCNT0的值,输出比较中断    输出比较寄存器(0b00100111)
TCCR0 = 0x07; //start timer   1024分频,来自预分频 P94
}
 
故   中断定时时间为T=预分频*(MAX—TCNT0+1)/F_CPU
 
即 分频    1024
    MAX     0XFF
    TCNT0   0XD9
    F_CPU   8M=800000
 
故T=1024*(255-233+1)/800000=3ms
 
 
 
 
 
 
 
 
 
mega16的定时器有外部时钟源接口,用于外部计数。

Timer0对应T0(PB0),Timer1对应T1(PB1),可以允许上升沿触发和下降延触发,通过TCCRn设定。

外部计数的原理,定时器选择外部时钟,初始化之后,TCNT0在每次检测到信号变化的时候加一,知道与TCCR0相同的时候,产生比较匹配中断。

本例子程序中,用按键来产生外部的信号的变化,下降延计数。

在实际的应用中,可以用来检测外部电路产生的高低电平数量,需要注意,在电路设计时,需要考虑加入电容防抖,(在本范例程序中,有时候按下键再抬起,会产生2个计数)。
 
 
CODE:

// ICC-AVR application builder : 2007-5-29 15:21:23
// Target : M16
// Crystal: 7.3728Mhz
// 用途:演示定时器的计数功能
// 作者:古欣 AVR 与虚拟仪器 [url]www.avrvi.com[/url]
// 连接:接好电源和晶振的跳线
// 7断数码管的ABCD接VCC,a~dp接PA0~PA7
// PB0接一个独立按键

#include
#include

const unsigned char seg7_data[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//0~F and "shut"


void port_init(void)
{
PORTA = 0xFF;
DDRA = 0xFF;
PORTB = 0x01; //PB0,是TIMER0的外部时钟输入脚(T0),需要设为输入,并且使能内部上拉
DDRB = 0x00;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}

//TIMER0 initialize - prescale:Falling edge
// WGM: Normal
// desired value: 1KHz
// actual value: Out of range
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x00; //set count
OCR0 = 0x0A; //set compare十进制的十,十次按键后匹配,进入这里
TCCR0 = 0x06; //start timer 时钟由T0 引脚输入,下降沿触发
}

#pragma interrupt_handler timer0_comp_isr:20
void timer0_comp_isr(void)
{
//compare occured TCNT0=OCR0
//按下键OCR0次后,会进入本中断
TCNT0 = 0x00;
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer0_init();

MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x02; //timer interrupt sources 允许定时器0,比较中断
SEI(); //re-enable interrupts
//all peripherals are now initialized
}

void main(void)
{
init_devices();
while(1)
{
PORTA = seg7_data[TCNT0]; //一直显示TCNT0的值
}
}
 


实验效果:启动时,数码管显示0,按下按键,数码管上的值加1,从0到A显示,A之后回到0。
偶尔有按一次键,数码管变两次的现象,这是由于键盘抖动着造成的,不用在意,实际应用中在外部电路加滤波电容解决这个问题。
 
 
一点说明: 使用ICC生成的代码如下,TCNT0 和OCR0 都是不可预料的值,需要自己进行修改,这个不是ICC的bug,因为外部的时钟变化不可预料,程序无法计算初值和比较匹配的值。

CODE:


//TIMER0 initialize - prescale:Rising edge
// WGM: Normal
// desired value: 1KHz
// actual value: Out of range
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x00 /*INVALID SETTING*/; //set count
OCR0 = 0x00 /*INVALID SETTING*/; //set compare
TCCR0 = 0x06; //start timer
}


关键字:AVR  定时器  工作原理 引用地址:AVR定时(计数)器工作原理

上一篇:ATmega16L 的中断源及在GCC中的中断名
下一篇:AVR 内部EEPROM读写范例

推荐阅读最新更新时间:2024-03-16 15:16

基于AVR单片机Megal6的电子时钟设计
1 引言   数字钟能长期、连续、可靠、稳定地工作;同时还具有体积小,功耗低等特点,便于携带,使用方便。数字钟是采用数字电路实现对“时、分、秒”数字显示的计时装置,广泛应用于个人家庭、车站、码头、办公室等公共场所,已成为人们日常生活中不可缺少的必需品。由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。传统MCS51系列单片机的所有数据处理都基于一个累加器,因此累加器与程序存储器、数据存储器之间的数据转换就成了单片机的瓶颈;在AVR单片机中,寄存器由32个通用工作寄存器组成,并且任何一个寄存器都能充当累加器,从
[单片机]
基于<font color='red'>AVR</font>单片机Megal6的电子时钟设计
基于TTS技术的矿用声光报警器工作原理
随着科学技术的不断进步,矿用声光语音报警设备,已广泛应用在煤矿作业和安全领域,是矿用产品中必不可少的设备之一。 目前市场上供应的传统矿用声光报警设备均使用的是模拟技术。由于技术本身的限制,模拟语音报警设备存在语音质量差、抗干扰能力弱、可接入节点少、生产效率低、安装施工复杂、可维护性差等弱点,而且这些弱点很难通过本身技术的改进或采用优质元器件以及控制生产质量等方式来改进。 相比传统矿用声光报警设备,采用TTS技术,内置语音合成模块的声光报警器,可以合成任意的中文文本,并且清晰、甜美的声音播报出来,尤其是在嘈杂的环境中,听的更清楚、更明白。 数字语音报警设备采用了高性能嵌入式压缩算法,将文本信息转换为语音信号,极
[安防电子]
电源系统中的单元电路的工原理
电源系统中的单元电路的工原理  1、整流与滤波电路(AC/DC)整流电路的作用就是将极性双向变化的交流电或者双向脉冲电,转变成为单向脉冲电,单向脉冲电再经过滤波电路的积分作用就成为直流电。因此整流和滤波电路的共同作用,才能完成了交流电到直流电的转化。 普通二极管的单向导电性,是构成基本整流电路的基础。以下是三种二极管整流电路原理图,它们分别是:半波整流、全波整流、桥式整流。   二极管的参数(型号)依工作电压和最大输出功率确定,如果所整流的对象是非50HZ交流电或者是非正弦波脉冲,还需要考虑二极管的频率特性(开关特性)。   下图是一种可以同时输出两种电压的特殊整流电路,此电路常常使用在需要适
[电源管理]
电源系统中的单元电路的工原理
STM32系统定时器SysTick
1. SysTick系统定时器概述 学习完STM32的中断,下来就要学习STM32的定时器。就像电话最基本的功能是与人通话一样,定时器最基本的功能就是定时(STM32有些定时器的功能强大得超乎想象,当然不是今天要学的SysTick),定时器的使用步骤无非就是设置定时时间,然后等待超时,超时会触发中断或者设置某个标志位:若是触发中断自然要去执行中断处理函数,处理函数和中断源的绑定工作在启动文件的中断向量表已经明确,我们负责实现与之对应的中断处理函数即可;若是查询标志位则轮询访问该标志位,发生改变后再执行其他处理操作。 定时器涉及到中断,那就跟前面学习的EXTI、NVIC以及中断优先级等概念扯上关系了。系统定时器SysTick
[单片机]
STM32系统<font color='red'>定时器</font>SysTick
NO.15 MSP432定时器使用实例——流水灯
  上一篇文章我们讲了定时器Timer的基本概念和如何调用定时器。这次我们来尝试在MSP432中使用定时器完成流水灯这个小实验。   流水灯是我们从真正意义上进行对单片机进行时间控制。   这个实验主要是控制我们开发板上的LED进行1s亮,1s灭,循环进行。   首先,我们打开CCS中ResourceExplorer的TiDrivers下的案例——timerled。   我们将其导入到我们的工作区中,我们再打开timerled.syscfg这个文件,查看本工程的相关配置。      我们要增加其他Timer也非常简单,只要点击ADD这个按钮就可以配置相关内容。   我们其次打开timerled.c这个主文件,
[单片机]
NO.15 MSP432<font color='red'>定时器</font>使用实例——流水灯
多线电缆测试仪的工作原理
通常,电缆测试仪是我们可以检查电缆是否损坏或以正确方式连接的设备。电缆测试仪是在安装电缆或电线时单独确定电缆的物理质量或连接性的非常有用的方法。它检测电缆是否正确连接以及电缆两端之间的通信强度。一些先进的电缆测试仪测试信号传输特性,如电阻、噪声、干扰等。市场上可用的一些电缆测试仪是 LAN、5 类、6 类、7 类。 在此电路中,我们展示了多线电缆测试仪,通过它可以检查电线或电缆是否有缺陷。 所需材料 555 定时器 IC 4017 集成电路 电阻器 (10k-1, 2.2 k-2,500 k-4,) 电容器 (10uf-1,10nf-1) 红色指示灯 9V 电源 跳线 面包板 电路图 4017 十年计数器 IC
[测试测量]
多线电缆测试仪的<font color='red'>工作原理</font>
AVR单片机端口设置
DDRA=OXFF; PORTA=OXFF; 与 PORTA=OXFF; DDRA=OXFF; 是有区别的,这两种顺序对应IO口的电平变化是不一样的。这个区别是在产品性能上面的,从表面上看不出明显区别,没有一定电路功底的可能不太好理解。DDRA、PORTA、在上电时默认都为0x00;如果你设方向DDRA后设PORTA的话,设定为输出方向的全部输出低电平、再设定电平,这个时候输出高电平,那么在输出高电平的这个IO口上面,就会有一个从低电平到高电平的瞬间变化,因为在变化期间IO口方向已经为输出,所以这个信号是有一定能量的,会产生一定的干扰。如果先设电平再设方向的话:上面说的瞬间变化就不会发生了。 ATMEGA8单片机I
[单片机]
机器视觉设备的工作原理是什么
现代社会,工业自动化设备使用率越来越高,越来越多的企业、商家、客户会选择采用机械设备,不仅可以抬高产能,而且减轻人们负担,可以长时间不间断的进行工作,今天要来了解的就机器视觉设备,那你知道视觉设备工作原理是什么吗? 机器视觉系统就是利用机器代替人眼来作各种测量和判断。它是计算科的一个重要分支,它综合了光学、机械、电子、计算机软硬件等方面的技术,涉及到计算机、图像处理、模式识别、人工智能、信号处理、光机电一体化等多个领域。图像处理和模式识别等技术的快速发展,也大大地推动了机器视觉的发展。 采用机器视觉设备就是用机器替代人眼完成检测,具体实现的过程是用工业相机采集被检测器件的图像,而这个采集的过程可以说是机器视觉最为重要的一个
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved