一、51單片機定時器初值計算
1、方法一
void main(void)
{
s1=1;
TMOD=0x01; //使用定時器T0的模式1
TH0=(65536-46083)/256; //定時器T0的高8位設(shè)置初值
TL0=(65536-46083)%256; //定時器T0的低8位設(shè)置初值
函數(shù)功能:定時器T0的中斷服務(wù)函數(shù)
********************************************************/
void Time0(void ) interrupt 1 using 0 //定時器T0的中斷編號為1,使用第1組工作寄存器
{
count++; //每產(chǎn)生1次中斷,中斷累計次數(shù)加1
if(count==20) //如果中斷次數(shù)計滿20次
count=0; //中斷累計次數(shù)清0
s++; //秒加1
網(wǎng)絡(luò)上閱讀一段程序,定時器初值 46083 是怎么計算出來的? 一般我們?nèi)缬?AT892051的話 定時50MS 就是 TH0=(65536-50000)/256;
猜想應(yīng)該是使用的12M晶體 ,20次為1S.
2、方法二
10MS定時器初值的計算:
1)晶振12M
12MHz除12為1MHz,也就是說一秒=1000000次機器周期。10ms=10000次 機器周期。
65536-10000=55536(d8f0)
TH0=0xd8,TL0=0xf0
2)晶振11.0592M
11.0592MHz除12為921600Hz,就是一秒921600次機器周期,10ms=9216次機器周期。
65536-9216=56320(dc00)
TH0=0xdc,TL0=0x00
3、方法三
50MS定時器初值的計算:
1)晶振12M
12MHz除12為1MHz,也就是說一秒=1000000次機器周期。50ms=50000次 機器周期。
65536-50000=15536(3cb0)
TH0=0x3c,TL0=0xb0
2)晶振11.0592M
11.0592MHz除12為921600Hz,就是一秒921600次機器周期,50ms=46080次機器周期。
65536-46080=19456(4c00)
TH0=0x4c,TL0=0x00
使用說明
以12M晶振為例:每秒鐘可以執(zhí)行1000000次機器周期個機器周期。而T 每次溢出
最多65536 個機器周期。我們盡量應(yīng)該讓溢出中斷的次數(shù)最少(如50ms),這樣對主程序的干擾也就最小。
開發(fā)的時候可能會根據(jù)需要更換不同頻率的晶振(比如c51單片機,用11.0592M的晶振,很適合產(chǎn)生串口時鐘,而12M晶振很方便計算定時器的時間),使用插接式比較方便。
對12MHz 1個機器周期 1us 12/fosc = 1us
方式0 13位定時器最大時間間隔 = 2^13 = 8.192ms
方式1 16位定時器最大時間間隔 = 2^16 = 65.536ms
方式2 8位定時器最大時間間隔 = 2^8 = 0.256ms =256 us
定時5ms,計算計時器初值 M = 2^K-X*Fosc/12 12MHz
方式0: K=13,X=5ms,F(xiàn)osc=12MHz 則 M = 2^13 - 5*10^(-3)*12*10^6/12= 3192 = 0x0C78
THx = 0CH,TLx = 78H,
方式1: K=16,X=5ms,F(xiàn)osc=12MHz 則 M = 2^16 - 5*10^(-3)*12*10^6/12= 60536 = 0xEC78
THx = ECH,TLx = 78H,
50ms 12MHz THx = 3CH,TLx = B0H,
10ms THx = D8H,TLx = F0H,
方式2: 最大時間 2^8Fosc/12 = 0.256ms
十進制數(shù)是怎么來的?
6MHz 一個機器周期 12/6 = 2us
定時1ms 計數(shù)初值x
?。?^16-x)*2us = 1000us
x = 2^16 - 500 ,TH,TL 可置 -500
12MHz 一個機器周期 12/12 = 1us
12MHz 一個機器周期 12/12 = 1us
定時50ms 計數(shù)初值x
?。?^16-x)*1us = 50000us
x = 2^16 - 50000 ,TH,TL 可置 -500
定時器 計內(nèi)部晶振頻率
計數(shù)器 計外部輸入CPU腳上的脈沖個數(shù) P3.4(T0) P3.5(T1) 負(fù)跳變加一
當(dāng)晶振為6MHz時,最高計數(shù)頻率500KHz
二、AVR單片機定時器初值計算
1、方法一
使用芯片 AT Mega16 外部晶振 4.00MHz
定時器1 (16位定時器)寄存器 TCCR1B = 0x04 設(shè)定 256預(yù)分頻
要利用定時器定時1秒
1,4000000 / 256 = 15625 說明定時器每當(dāng) 1/15625 秒 就會觸發(fā)一次中斷
2,65535 - 15625 = 49910 計算出要累加多少次才能在1秒后出發(fā)定時器1的溢出中斷
3,49910 《==》 C2 F6 將計算后的值換算成16進制
4, TCNT1H = 0xC2 ; 對寄存器賦值
TCNT1L = 0xF6 ;
2、方法二
例如用16位定時器TIMER1,4MHZ晶振,256分頻,100ms定時,如何求得初值賦給TCNT1?
65536-(4M/256)*0.1=63973.5
其中,4M是晶體頻率,0.1是定時時長單位秒。
對于8位的定時器
T=(2^8-計數(shù)初值)*晶振周期*分頻數(shù)=(2^8-計數(shù)初值)/晶振頻率*分頻數(shù)計數(shù)初值=2^8-T/晶振周期/分頻數(shù)=2^8-T*晶振頻率/分頻數(shù)
因為AVR一指令 一周期
IAR For AVR 精確延時
C語言中,想使用精確的延時程序并不容易。IAR 中有這樣的一個函數(shù) __delay_cycles(),該函數(shù)在頭文件intrinsics.h中定義,函數(shù)的作用就是延時N個指令周期。根據(jù)這個函數(shù)就可以實現(xiàn)精確的延時函數(shù)了(但不能做到100%精確度)。
實現(xiàn)的方法:
建立一個delay.h的頭文件:
#ifndef __IAR_DELAY_H
#define __IAR_DELAY_H
#include 《intrinsics.h》
#define XTAL 8 //可定義為你所用的晶振頻率(單位Mhz)
#define delay_us(x) __delay_cycles ( (unsigned long)(x * XTAL) )
#define delay_ms(x) __delay_cycles ( (unsigned long)(x * XTAL*1000) )
#define delay_s(x) __delay_cycles ( (unsigned long)(x * XTAL*1000000) )
#endif
注意: __delay_cycles(x),x必須是常量或則是常量表達式,如果是變量則編譯報錯!
關(guān)于溢出中斷不管是哪個單片機都是不斷累加,使其寄存器溢出觸發(fā)中斷,然后跳轉(zhuǎn)到中斷函數(shù)處執(zhí)行中斷服務(wù)程序。對于定時器初值的設(shè)定可以加深對定時器的工作原理的理解。
ATMega16 里面有8位和16位兩種定時器,他們何時會溢出這個是固定的,也就是到達他們的計數(shù)范圍的最大值就會產(chǎn)生中斷,8位的定時器的最大計數(shù)范圍是0~256(2的8次方),就是累加到256后他就會產(chǎn)生中斷,16位的定時器最大計數(shù)范圍是0~65536(2的16次方),累加到65536時他就會產(chǎn)生中斷。
而我們所謂的計數(shù)初值是就是要設(shè)定定時器在什么地方開始計數(shù),以8位定時器為例比如:初值為100,所以定時器從100開始累加,累加了156次,加到256后產(chǎn)生中斷,這就是中間消耗的時間和指令周期就是我們要去設(shè)定的時間;再比如:初值是200,所以定時器從200開始累加,累加了56次,加到256后產(chǎn)生中斷,可以看到第一定時要累加156次才會中斷而第二次只要累加56次就會產(chǎn)生中斷,顯然第一次設(shè)定的時間要比第二次的長。
定時器不僅可以定時,而且我們用到定時器的時候往往是需要精確定時的時候。我們可以計算出我們設(shè)定的初值會在多長時間后進入中斷。
3、方法三
實驗平臺:ATMega16
晶振: 11.0592 MHz
對初值的計算:
1,11059200 / 1024 = 10800 設(shè)定為1024倍分頻 ,得到每1秒需要進行多少次累加
2,10800 / 100 = 108 得到10ms 的定時需要進行多少次累加 。
3,256 - 108 = 148 計算范圍最大值減去要累加的時間,得到初值,即從哪里開始累加才能在溢出時為10ms的時間。
4,148 《==》 0x94 得到十六進制值,賦值給TCNT0
代碼: 定時10ms
#include 《iom16.h》
unsigned char flag = 0;
void timer_init(void)
{
TCCR0 = 0x05; //進行1024分頻
TCNT0 = 0x94; //賦計數(shù)初值
TIMSK_TOIE0 = 1; //開使能
SREG_I = 1; //開總中斷
}
#pragma vector = TIMER0_OVF_vect
__interrupt void time0_normal(void)
{
TCNT0 = 0x94; //重新賦初值
flag++;
}
void main(void)
{
timer_init();
DDRB_Bit0 = 1;
while(1)
{
if(flag == 100) //10ms 重復(fù)100次,即為1秒
{
PORTB_Bit0 = ~PORTB_Bit0; //讓LED閃爍
flag = 0;
}
}
}
4、方法四
實驗平臺:ATMega16
晶振:11.0592
16位定時器初值設(shè)定:
1,11059200 / 256 = 43200 設(shè)定256倍分頻,得到每1秒需要進行多少次累加
2,65536 - 43200 = 22336 計算范圍最大值減去要累加的時間,得到初值,即從哪里開始累加才能在溢出時為1s的時間。
3,22336 《==》 0x57 0x40 得到十六進制值,賦值給TCNT1H , TCNT1L
: 定時1s
#include 《iom16.h》
unsigned char flag = 0;
void timer_init(void)
{
TCCR1B = 0x04;
TCNT1H = 0x57;
TCNT1L = 0x40;
TIMSK_TOIE1 = 1;
SREG_I = 1;
}
#pragma vector = TIMER1_OVF_vect
__interrupt void time1_normal(void)
{
TCNT1H = 0x57;
TCNT1L = 0x40;
flag++;
}
void main(void)
{
timer_init();
DDRB_Bit0 = 1;
while(1)
{
if(flag == 1)
}
}
評論