用单片机的外部中断来测频率
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
dis[0]=counter2/10000; // dis[5]=counter2000; dis[1]=dis[5]/1000; // dis[5]=dis[5]00;
获取计数值的万位 获取计数值的千位
dis[2]=dis[5]/100; // dis[5]=dis[5]0; dis[3]=dis[5]/10; // dis[4]=dis[5]; // for(i=0;i<5;i ) // {
uchar counter1;
sbit duan=P2^6; //74HC573 的 LE 端 U5 LED 的段选端
sbit wei=P2^7; //74HC573
的 LE 端 U4 LED 的位选端
unsigned int counter2,tmp;
uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //
// P0=0xff; P0=con[i]; wei=1; wei=0; P0=table[dis[i]]; duan=1; duan=0; delay(1); P0=0; duan=1; duan=0; } }
获取计数值的百位
获取计数值的十位 获取计数值的个位 依次显示万、千、百、十、个位,动态显示
5.9.2 输入捕捉功能 ATmega128 的两个 16 位定时 / 计数器( T/C1、T/C3)具有输入捕捉功能,它是
AVR定时 / 计数器的又一个显著的特点。其基本作用是当一个事件发生时,立即将 定时 / 计数器的值锁定在输入捕捉寄存器中(定时 / 计数器保持继续运行)。利用输 入捕捉功能,可以对一个事件从发生到结束的时间进行更加精确,如下面的示例中 精确测量一个脉冲的宽度。
电位器可
//
发现数字有变化 .
// 原理: 1 秒钟内计数外部脉冲个数,如计数 1000 次,则表示频率为 1000Hz
//1 秒钟定时采用 51 单片机定时器 0 实现,外部脉冲由外部中断 0 引脚接入
#include<reg51.h>
#include"51hei.h"
#define uchar unsigned char
pulse_clocks = (unsigned long)falling_edge - (unsigned long)rising_edge
(unsigned long)ov_counter * 0x10000 / 500; //
计算脉冲宽度
}
}
捕捉中断
void main(void) { TCCR1B=0x42; // TIMSK=0x24; // #asm("sei")
jishu(); } } // 定时器 0 和外部中断 0 的初始化 init()
{ EA=1; EX0=1; ET0=1; IT0=1; TMOD=0x01; TH0=0x3c; TL0=0xaf; TR0=1; }
// 延时程序 delay(uchar x) { uchar a,b; for(a=x;a>0;a--)
而使用 ATmega128的 1 个定时 / 计数器,再配合其输入捕捉功能来测量脉冲的宽 度就非常方便,下面是实现的程序示例。
#include <mega128.h>
#define ICP1 PIND.4 //
脉冲输入由 ICP1( Pind.4 )输入
unsigned char ov_counter; unsigned int rising_edge,falling_edge; unsigned long pulse_clocks;
256 15.625KHz 64us
16.384ms
1024 3906.25Hz 256us
65.536ms
最宽时宽( TCNT0=)0
从表中看出,在系统时钟为 4MHz时, 8 位的 T/C0 最高计时精度为 0.25us ,最长 的时宽可达到 65.536ms。而使用 16 位的定时 / 计数器时,不需要辅助的软件计数 器,就可以非常方便的设计一个时间长达 16.777216 秒(精度为 256us)的定时 器,这对于其它的 8 位单片机是做不到的。
jishu()
{
if(counter1==20) //
定时器定时 50ms,故 20 次中断就表示 1 秒钟到达
{
counter2=tmp;
display();
tmp=0;
counter1=0;
}
else
display();
}
/ 计数器( Timer/counter )是单片机芯片中最基本的外围接口,它的用途非常广
可以看到,使用定时 / 计数器以及配合它的捕捉功能测量脉冲宽度,不仅节省系 统的硬件资源,编写程序简单,而且精度也高,因为读到的上升沿和下降沿的时间 就是其实际发生的时间。
5.9.3 比较匹配输出和脉冲宽度调制 PWM (见已发表的主题)
泛,常用于测量时间、速度、频率、脉宽、提供定时脉冲信号等。相对于一般
8位
单片机而言, AVR不仅配备了更多的定时 / 计数器接口,而且还是增强型的,功能
非常强大。 ATmega128一共配置了 2 个 8 位和 2 个 16 位,共 4 个定时 / 计数器,本
小节重点对它的一些增强功能的应用做基本的介绍。
5.9.1 预分频器 定时 / 计数器最基本的功能就是对脉冲信号计数,当计数器计满后( 8 位为 255,
16 位为 65535),再来一个脉冲它就翻转到 0,并产生中断信号。同其他单片机类
似, AVR的定时 / 计数器的计数脉冲可以来自外部的引脚,也可以由从内部系统时 钟获得;但 AVR的定时 / 计数器在内部系统时钟和计数单元之间增加了一个预分频 器,利用预分频器,定时 / 计数器可以从内部系统时钟获得不同频率的信号。表 51 为系统时钟为 4MHz使用定时 / 计数器 0 的最高计时精度和时宽范围。
脉冲的实际宽度(毫秒格式)是根据 T/C1 的计数时钟个数来计算的。本例中 T/C1 的计数时钟是系统时钟( 4MHz)的 8 分频,即 500KHz,相应的计数脉冲宽度 为 2us。因此计算出从上升沿和下降沿之间总的计数脉冲个数,除以 500 个脉冲 (为 1ms)即得到以毫秒为单位的被测脉冲宽度了。
interrupt [TIM1_OVF] void timer1_ovf_isr(void) // T/C1
{
ov_counter ; //
记录溢出次数
}
溢出中断
interrupt [TIM1_CAPT] void timer1_capt_isr(void) // T/C1
{
if (ICP1)
{ //
上升沿中断
rising_edge = ICR1; //
记录上升沿开始时间
TCCR1B = TCCR1B & 0xBF; // 设置 T/C1 为下降沿触发捕捉
ov_counter = 0; // 清零溢出计数器
}
else
{ //
来自百度文库
下降沿中断
falling_edge = ICR1; //
记录下降沿时间
TCCR1B = TCCR1B | 0x40; // 设置 T/C1 为上升沿触发捕捉
共
阳型数码管 0—9 显示
unsigned int dis[6];
uchar con[]={0xfe,0xfd,0xfb,0xf7,0xef}; //
共阳型数码管控制端
init();
delay(uchar);
display();
jishu();
void main() {guandz(); init(); while(1) {
测量一个脉冲的宽度,就是测量脉冲上升沿到下降之间的时间。不使用输入捕捉 功能,一般情况往往需要使用两个外围部件才能完成和实现。如使用 1 个定时 / 计 数器加 1 个外部中断(或模拟比较器):定时 / 计数器用于计时;而外部中断方式 设置成电平变化触发方式,用于检测脉冲的上升和下降沿。当外部中断输入电平由 低变高,触发中断,读取时间 1;等到输入电平由高变低时,再次触发中断,读取 时间 2;两次时间差既为脉冲宽度。这种实现方式不仅多占用了一个单片机的内部 资源,而且精度也受到中断响应时间的限制。因为一旦中断发生, MCU响应中断需 要时间,在中断中可能要进行适当的中断现场保护,才能读取时间值。而此时的时 间值比中断发生的时间已经滞后了。
表 5-1 T/C0 计时精度和时宽(系统时钟 4MHz)
分频系数 计时频率 最高计时精度( TCNT0=25)5
1
4MHz 0.25us
64us
8
500KHz 2us
512us
32 125KHz 8us
2.048ms
64 62.5KHz 16us
4.096ms
128 31.25KHz 32us
8.192ms
作者 : 佚名 来源 : 本站原创 【字体:大 中 小】
点击数 : 302
更新时间: 2010 年 08 月 08 日
// 晶振 :12M
// 实验方法 : 首先要把 51hei 单片机开发板上的 ne555 的方波输出信号 J7 的第一脚
用杜邦线
//
引入 P3.2 口, 数码管即可显示 ne555 震荡电路当前的频率值 , 旋动 PR1
AVR 单片机的每一个定时 / 计数器都配备独立的、多达 10 位的预分频器,由软件 设定分频系数,与 8/16 位定时 / 计数器配合,可以提供多种档次的定时时间。使用 时可选取最接近的定时档次,即选 8/16 位定时 / 计数器与分频系数的最优组合,减 少了定时误差。所以, AVR定时 / 计数器的显著特点之一是:高精度和宽时范围, 使得用户应用起来更加灵活和方便。此外, AVR的 USAR、T SPI、I2C、WDT等都不 占用这些定时 / 计数器。
初始化 T/C1,1/8 分频,上升沿触发捕捉 允许 T/C1 溢出和捕捉中断
while (1) { ………
}; }
这段程序是在 CVAVR中实现的。在 T/C1 的捕捉中断中,先检查 ICP1 的实际状 态,以确定是出现了上升沿还是下降沿信号。如果中断是由上升沿触发的( ICP1 为高电平),程序便开始一次脉冲宽度的测量:记录下上升沿出现的时间,把 T/C1 的捕捉触发方式改为下降沿触发,并清空溢出计数器。如果中断由下降沿触 发( ICP1 为低电平),表示到达脉冲的未端,程序记录下降沿出现时间,计算出 脉冲的宽度,再将 T/C1 的捕捉触发方式改为上升沿触发,以开始下一次的测量。
for(b=20;b>0;b--); } // 外部中断 0 中断程序 void external0() interrupt 0 {
tmp ;
}
// 定时器 0 中断程序 void timer0() interrupt 1 { TH0=0x3c; TL0=0xaf; counter1 ; }
// 显示程序 display() { uchar i;
获取计数值的万位 获取计数值的千位
dis[2]=dis[5]/100; // dis[5]=dis[5]0; dis[3]=dis[5]/10; // dis[4]=dis[5]; // for(i=0;i<5;i ) // {
uchar counter1;
sbit duan=P2^6; //74HC573 的 LE 端 U5 LED 的段选端
sbit wei=P2^7; //74HC573
的 LE 端 U4 LED 的位选端
unsigned int counter2,tmp;
uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //
// P0=0xff; P0=con[i]; wei=1; wei=0; P0=table[dis[i]]; duan=1; duan=0; delay(1); P0=0; duan=1; duan=0; } }
获取计数值的百位
获取计数值的十位 获取计数值的个位 依次显示万、千、百、十、个位,动态显示
5.9.2 输入捕捉功能 ATmega128 的两个 16 位定时 / 计数器( T/C1、T/C3)具有输入捕捉功能,它是
AVR定时 / 计数器的又一个显著的特点。其基本作用是当一个事件发生时,立即将 定时 / 计数器的值锁定在输入捕捉寄存器中(定时 / 计数器保持继续运行)。利用输 入捕捉功能,可以对一个事件从发生到结束的时间进行更加精确,如下面的示例中 精确测量一个脉冲的宽度。
电位器可
//
发现数字有变化 .
// 原理: 1 秒钟内计数外部脉冲个数,如计数 1000 次,则表示频率为 1000Hz
//1 秒钟定时采用 51 单片机定时器 0 实现,外部脉冲由外部中断 0 引脚接入
#include<reg51.h>
#include"51hei.h"
#define uchar unsigned char
pulse_clocks = (unsigned long)falling_edge - (unsigned long)rising_edge
(unsigned long)ov_counter * 0x10000 / 500; //
计算脉冲宽度
}
}
捕捉中断
void main(void) { TCCR1B=0x42; // TIMSK=0x24; // #asm("sei")
jishu(); } } // 定时器 0 和外部中断 0 的初始化 init()
{ EA=1; EX0=1; ET0=1; IT0=1; TMOD=0x01; TH0=0x3c; TL0=0xaf; TR0=1; }
// 延时程序 delay(uchar x) { uchar a,b; for(a=x;a>0;a--)
而使用 ATmega128的 1 个定时 / 计数器,再配合其输入捕捉功能来测量脉冲的宽 度就非常方便,下面是实现的程序示例。
#include <mega128.h>
#define ICP1 PIND.4 //
脉冲输入由 ICP1( Pind.4 )输入
unsigned char ov_counter; unsigned int rising_edge,falling_edge; unsigned long pulse_clocks;
256 15.625KHz 64us
16.384ms
1024 3906.25Hz 256us
65.536ms
最宽时宽( TCNT0=)0
从表中看出,在系统时钟为 4MHz时, 8 位的 T/C0 最高计时精度为 0.25us ,最长 的时宽可达到 65.536ms。而使用 16 位的定时 / 计数器时,不需要辅助的软件计数 器,就可以非常方便的设计一个时间长达 16.777216 秒(精度为 256us)的定时 器,这对于其它的 8 位单片机是做不到的。
jishu()
{
if(counter1==20) //
定时器定时 50ms,故 20 次中断就表示 1 秒钟到达
{
counter2=tmp;
display();
tmp=0;
counter1=0;
}
else
display();
}
/ 计数器( Timer/counter )是单片机芯片中最基本的外围接口,它的用途非常广
可以看到,使用定时 / 计数器以及配合它的捕捉功能测量脉冲宽度,不仅节省系 统的硬件资源,编写程序简单,而且精度也高,因为读到的上升沿和下降沿的时间 就是其实际发生的时间。
5.9.3 比较匹配输出和脉冲宽度调制 PWM (见已发表的主题)
泛,常用于测量时间、速度、频率、脉宽、提供定时脉冲信号等。相对于一般
8位
单片机而言, AVR不仅配备了更多的定时 / 计数器接口,而且还是增强型的,功能
非常强大。 ATmega128一共配置了 2 个 8 位和 2 个 16 位,共 4 个定时 / 计数器,本
小节重点对它的一些增强功能的应用做基本的介绍。
5.9.1 预分频器 定时 / 计数器最基本的功能就是对脉冲信号计数,当计数器计满后( 8 位为 255,
16 位为 65535),再来一个脉冲它就翻转到 0,并产生中断信号。同其他单片机类
似, AVR的定时 / 计数器的计数脉冲可以来自外部的引脚,也可以由从内部系统时 钟获得;但 AVR的定时 / 计数器在内部系统时钟和计数单元之间增加了一个预分频 器,利用预分频器,定时 / 计数器可以从内部系统时钟获得不同频率的信号。表 51 为系统时钟为 4MHz使用定时 / 计数器 0 的最高计时精度和时宽范围。
脉冲的实际宽度(毫秒格式)是根据 T/C1 的计数时钟个数来计算的。本例中 T/C1 的计数时钟是系统时钟( 4MHz)的 8 分频,即 500KHz,相应的计数脉冲宽度 为 2us。因此计算出从上升沿和下降沿之间总的计数脉冲个数,除以 500 个脉冲 (为 1ms)即得到以毫秒为单位的被测脉冲宽度了。
interrupt [TIM1_OVF] void timer1_ovf_isr(void) // T/C1
{
ov_counter ; //
记录溢出次数
}
溢出中断
interrupt [TIM1_CAPT] void timer1_capt_isr(void) // T/C1
{
if (ICP1)
{ //
上升沿中断
rising_edge = ICR1; //
记录上升沿开始时间
TCCR1B = TCCR1B & 0xBF; // 设置 T/C1 为下降沿触发捕捉
ov_counter = 0; // 清零溢出计数器
}
else
{ //
来自百度文库
下降沿中断
falling_edge = ICR1; //
记录下降沿时间
TCCR1B = TCCR1B | 0x40; // 设置 T/C1 为上升沿触发捕捉
共
阳型数码管 0—9 显示
unsigned int dis[6];
uchar con[]={0xfe,0xfd,0xfb,0xf7,0xef}; //
共阳型数码管控制端
init();
delay(uchar);
display();
jishu();
void main() {guandz(); init(); while(1) {
测量一个脉冲的宽度,就是测量脉冲上升沿到下降之间的时间。不使用输入捕捉 功能,一般情况往往需要使用两个外围部件才能完成和实现。如使用 1 个定时 / 计 数器加 1 个外部中断(或模拟比较器):定时 / 计数器用于计时;而外部中断方式 设置成电平变化触发方式,用于检测脉冲的上升和下降沿。当外部中断输入电平由 低变高,触发中断,读取时间 1;等到输入电平由高变低时,再次触发中断,读取 时间 2;两次时间差既为脉冲宽度。这种实现方式不仅多占用了一个单片机的内部 资源,而且精度也受到中断响应时间的限制。因为一旦中断发生, MCU响应中断需 要时间,在中断中可能要进行适当的中断现场保护,才能读取时间值。而此时的时 间值比中断发生的时间已经滞后了。
表 5-1 T/C0 计时精度和时宽(系统时钟 4MHz)
分频系数 计时频率 最高计时精度( TCNT0=25)5
1
4MHz 0.25us
64us
8
500KHz 2us
512us
32 125KHz 8us
2.048ms
64 62.5KHz 16us
4.096ms
128 31.25KHz 32us
8.192ms
作者 : 佚名 来源 : 本站原创 【字体:大 中 小】
点击数 : 302
更新时间: 2010 年 08 月 08 日
// 晶振 :12M
// 实验方法 : 首先要把 51hei 单片机开发板上的 ne555 的方波输出信号 J7 的第一脚
用杜邦线
//
引入 P3.2 口, 数码管即可显示 ne555 震荡电路当前的频率值 , 旋动 PR1
AVR 单片机的每一个定时 / 计数器都配备独立的、多达 10 位的预分频器,由软件 设定分频系数,与 8/16 位定时 / 计数器配合,可以提供多种档次的定时时间。使用 时可选取最接近的定时档次,即选 8/16 位定时 / 计数器与分频系数的最优组合,减 少了定时误差。所以, AVR定时 / 计数器的显著特点之一是:高精度和宽时范围, 使得用户应用起来更加灵活和方便。此外, AVR的 USAR、T SPI、I2C、WDT等都不 占用这些定时 / 计数器。
初始化 T/C1,1/8 分频,上升沿触发捕捉 允许 T/C1 溢出和捕捉中断
while (1) { ………
}; }
这段程序是在 CVAVR中实现的。在 T/C1 的捕捉中断中,先检查 ICP1 的实际状 态,以确定是出现了上升沿还是下降沿信号。如果中断是由上升沿触发的( ICP1 为高电平),程序便开始一次脉冲宽度的测量:记录下上升沿出现的时间,把 T/C1 的捕捉触发方式改为下降沿触发,并清空溢出计数器。如果中断由下降沿触 发( ICP1 为低电平),表示到达脉冲的未端,程序记录下降沿出现时间,计算出 脉冲的宽度,再将 T/C1 的捕捉触发方式改为上升沿触发,以开始下一次的测量。
for(b=20;b>0;b--); } // 外部中断 0 中断程序 void external0() interrupt 0 {
tmp ;
}
// 定时器 0 中断程序 void timer0() interrupt 1 { TH0=0x3c; TL0=0xaf; counter1 ; }
// 显示程序 display() { uchar i;