当前位置:首页 > 单片机 > 单片机
[导读]这篇文章是谈谈关于1937的定时器的,刚开始被晶振频率、时钟频率、振荡周期、振荡频率、指令周期、指令频率等等的名词绕晕了。先来解决这个问题。晶振频率是代表振荡器的频率,说的是晶振这个器件的频率,因为一个单

这篇文章是谈谈关于1937的定时器的,刚开始被晶振频率、时钟频率、振荡周期、振荡频率、指令周期、指令频率等等的名词绕晕了。先来解决这个问题。


晶振频率是代表振荡器的频率,说的是晶振这个器件的频率,因为一个单片机有内部外部晶振,比如你选择了内部晶振,那么这个晶振的频率就是你单片机的时钟频率,


振荡频率和晶振频率说的是一回事。振荡周期是1/(晶振频率),T = 1/f 嘛。指令周期这个根据单片机的不同会不同,8位的PIC单片机(PIC10/12/16/18系列)是4个时钟周期为一个指令周期。16位的PIC24单片机和dsPIC数字处理芯片和32位PIC32处理器是2个时钟周期为一个指令周期。(以上关于指令周期的内容是百度到的,内容较可靠http://zhidao.baidu.com/link?url=uEnsn0C-bb-xdDNG_qEI0HmhIpoDNVc4d2lheztGKsQMpflMcpbnlWAGdXyeMz05fJAhXardxSrQDLHEdDrCx_)


理清上面的内容,就开始我们的正题。


TIMER0


/*

* TIMER0是一个8位定时器/计数器,有8位预分频器(1:2-1:256),是所有定时器中预分频最大的(可以这么说吧。。)

* 可编程的内外部时钟源,可编程的外部时钟边沿选择。

* 溢出时中断

* TMR0可用于门控Timer1(还没试过。。)

* 休眠模式中无法工作

* 此时选择内部晶振8mhz,预分频1:16,每2.04s灯状态改变一次。TMR0从0计数到255

* 所以是255*16*1000/(Fosc(晶振频率)/4) = 2.04

*/


这些是我写在单片机程序开头的内容,大致描述了TIMER0模块,接下来告诉你们怎么使用它吧。(只写关于初始化TIMER0的,CPU的初始化之类的略过)


1.先初始化时钟源,在OSSCON寄存器中设置SCS位来选择内部振荡模块,IRCF设置内部频率


2.现在初始化TIMER0,还是一样,先选择时钟源,TMR0CS = 0;表示内部指令周期(注意是指令周期,fosc/4)


3.选择预分频,PSA位来选择需不需要预分频,PS<2:0>来设置预分频


4.时钟都和中断有关,所以这里要允许有效中断,GIE = 1;


5.然后允许TIM0IE中断,TIM0IE = 1;


6.最后是溢出中断标志位,TMR0IF = 0;表示未溢出,当定时器开启的时候TMRO就会开始计数,一个指令周期加一,从0-255.当加到255后再加一使TMR0IF = 1;计数会跳到0继续。


7.TMR0可以不用使能,自动计数,但因为执行时会延迟2个指令周期,所以TMR0的初值需要设置,来抵消这个延迟。


还是上代码吧


1 void InitTime();

2 void Init_fosc(); //设置内部振荡器,不过好像没用。。

3

4 unsigned int count = 0;

5

6 int main(int argc, char** argv)

7 {

8 InitCPU();

9 Init_fosc();

10 InitTime();

11 TRISC = 0x00;

12 // LATC = 0x00;

13 while(1);

14 return (EXIT_SUCCESS);

15 }

16

17 void InitTime()

18 {

19 // INTEDG = 0; //bit6 中断边沿选择位,1 = 上升沿,0 = 下降沿

20 TMR0CS = 0; //bit5 Timer0时钟源选择位,0 = 内部指令周期时钟(Fosc/4)

21 TMR0SE = 0; //bit4 Timer0时钟源边沿选择位,1 = 在T0CKI引脚电平下降沿时递增,0 = 上升沿时递增

22 PSA = 0; //bit3 预分频器分配位,1 = 不分给Timer0,0 = 预分频器分给Timer0

23 PS0 = 1;

24 PS1 = 1;

25 PS2 = 0; //1:16

26 //PS<2:0>,预分频器分频比选择位

27 GIE = 1; //允许所有有效中断

28 PEIE = 0; //禁止所有外设中断,有待考虑

29 TMR0IE = 1; //允许TMR0中断

30 TMR0IF = 0; //溢出中断标志位,未溢出

31 TMR0 = 1;

32 }

33

34 void Init_fosc()

35 {

36 // OSCCON = 0x6a; 下面的设置为设置内部振荡器频率的

37 SCS0 = 1;

38 SCS1 = 0; //1x内部振荡器模块

39 IRCF0 = 0;

40 IRCF1 = 1;

41 IRCF2 = 1;

42 IRCF3 = 0; //1101 = 250kHz

43

44 }

45

46 void interrupt ISR()

47 {

48 TMR0 = 1;

49 count++;

50 if(count ==10)

51 {

52 LATC = ~LATC;

53 count = 0;

54 }

55 TMR0IF = 0;

56 }


TMR0是不用使能的,其他的时候也许不用管他,就算它在计数,没有允许它中断(TMR0IE位),也是没啥用的啊,残念ね。。


接下来是TIMER1模块,TIMER1模块的特殊的地方是带门控,是16位的定时计数器,有专用32kHz的振荡器电路。


这次先上代码吧,感觉会更有条理些


1 void InitTime();

2 void Init_fosc(); //设置内部振荡器,不过好像没用。。

3

4 unsigned int count = 0;

5

6 int main(int argc, char** argv)

7 {

8 InitCPU();

9 Init_fosc();

10 InitTime();

11 TRISC = 0x00;

12 // LATC = 0x00;

13 while(1);

14 return (EXIT_SUCCESS);

15 }

16

17 void InitTime()

18 {

19 // INTEDG = 0; //bit6 中断边沿选择位,1 = 上升沿,0 = 下降沿

20 TMR0CS = 0; //bit5 Timer0时钟源选择位,0 = 内部指令周期时钟(Fosc/4)

21 TMR0SE = 0; //bit4 Timer0时钟源边沿选择位,1 = 在T0CKI引脚电平下降沿时递增,0 = 上升沿时递增

22 PSA = 0; //bit3 预分频器分配位,1 = 不分给Timer0,0 = 预分频器分给Timer0

23 PS0 = 1;

24 PS1 = 1;

25 PS2 = 0; //1:16

26 //PS<2:0>,预分频器分频比选择位

27 GIE = 1; //允许所有有效中断

28 PEIE = 0; //禁止所有外设中断,有待考虑

29 TMR0IE = 1; //允许TMR0中断

30 TMR0IF = 0; //溢出中断标志位,未溢出

31 TMR0 = 1;

32 }

33

34 void Init_fosc()

35 {

36 // OSCCON = 0x6a; 下面的设置为设置内部振荡器频率的

37 SCS0 = 1;

38 SCS1 = 0; //1x内部振荡器模块

39 IRCF0 = 0;

40 IRCF1 = 1;

41 IRCF2 = 1;

42 IRCF3 = 0; //1101 = 250kHz

43

44 }

45

46 void interrupt ISR()

47 {

48 TMR0 = 1;

49 count++;

50 if(count ==10)

51 {

52 LATC = ~LATC;

53 count = 0;

54 }

55 TMR0IF = 0;

56 }



再来写下总结的步骤


1.初始时钟源


2.在Timer1的初始中先选择时钟源


3.设置预分频


4.允许中断和溢出位清零


5.使能Timer1


虽然看起来简单,但是Timer1的功能比Timer0多,好些自己也没有用到过,有一个注意的地方,TMR1H和TMR1L的初值设定最好刚刚把延时拿回来就行了。使能也应该放最后,刚好需要起振时间



最后最后,1937里面最多的定时器,数量超过我的想象,竟然多达,,竟然拥有3个!!何等的数量啊。。。。。好了,不装怪了,他是TIMER2/4/6葫芦三兄弟。


/*1937共含有3个相同的Timer2模块,分别为Timer2、Timer4、Timer6

* 8位定时器和周期寄存器(TMRx和PRx)

* 可读写、预分频(1:1:4:16:64)后分频(1:1至1:16)

* TMRx与相应的PRx分别匹配时中断、可选择作为MSSP模块的移位时钟(仅Timer2)

*/


看到了吗,这里是TMRx与相应的PRx分别匹配时中断,不像前面两个あほ(TIMER0与TIMER1)是溢出中断


还是先上代码吧,,,这里直接上初始化Timer2/4/6的程序了,



1 void Init_Timer2() //时钟是系统指令时钟 Fosc/4,沿边沿递增计数。

2 {

3 T2CON = 0x0d; //设置后分频,使能Timer2,设置预分频

4 TMR2 = 0;

5 PR2 = 100; //TMR2与PR2的值越相近,进入中断越快

6 GIE = 1; //允许所有有效中断,!!!!实验无此语句能否运作

7 PEIE = 1;

8 TMR2IE = 1; //允许Timer2中断

9 TMR2IF = 0; //溢出标志位,未溢出

10 }


TIMER2/4/6是无法自己选择内外部时钟的,系统选什么他就得选什么,作为对比,TIMER0和TIMER1是可以自己选的,素晴らしい!



所有的时钟设置总结来说,必须考虑的要素有以下几条


1.设置时钟,系统时钟和定时器要用的时钟(TIMER0和TIMER1是可以选的)

2.预分频及后分频,所有时钟里TIMER0的预分频最大(1:2-1:256),TIMER2/4/6既有预分频又有后分频

3.TMRxIE、PEIE、GIE(允许TIMERx中断、允许外设中断、允许所有有效中断),这三个的赋值。除PEIE在TIMER0中没有也可以运作外,其他两个在每个定时器中必须有

4.TMRxIF,溢出的标志位,一般会在中断程序里面清零,所以在初始化里面可有可无。

5.计数的设置TIMER0中的TMRO(0-255),TIMER1中的TMR1H和TMR1L,TIMER2/4/6中的TMRx(0-PRx),PRx(0-255)


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

单片机定时器通过晶振频率来产生精准的计数脉冲,从而实现微秒级别的时间控制。 单片机定时器依托于一个稳定的计数器,该计数器与单片机上的晶振部件相连。晶振经过12分频后,为单片机提供稳定且精准的1MHZ脉冲。由于晶振的频率极...

关键字: 单片机 定时器

编码器‌是一种传感器,主要用于测量旋转运动的角度、角速度和位移等参数。常见的编码器类型包括增量式编码器和绝对值编码器,前者通过检测脉冲的增加或减少来测量旋转方向和距离,后者则直接输出当前的绝对位置信息‌。

关键字: 编码器‌ 定时器

一款语音控制的番茄时间定时器,内置Seeed Studio XIAO ESP32S3感测和圆形显示。用免提时间管理保持高效!

关键字: 定时器 ESP32S3 语音控制

【2025年3月20日, 德国慕尼黑讯】全球功率系统和物联网领域的半导体领导者英飞凌科技股份公司(FSE代码:IFX / OTCQX代码: IFNNY)近日宣布,其旗下ModusToolboxTM开发平台中的AIROC™...

关键字: MCU 物联网 定时器

众所周知,说到延时,很多人都会想到用软件件来实现,比如定时器之类的。今天就来说说用硬件来实现定时的方式,虽说没有那么准,但是有些场合还是用得到的。

关键字: CD4060 定时器

如果定时器的重装值和分频设置不正确,会导致PWM输出的频率和占空比不准确,从而产生误差‌1。

关键字: 定时器 分频

SysTick定时器的工作原理主要基于一个递减计数器的机制。以下是对SysTick定时器工作原理的详细解释:

关键字: SysTick 定时器

单片机定时器是一种用于计时和定时操作的功能模块。它通常用于生成延时、计数事件以及产生精确的时间间隔信号。

关键字: 定时器 时钟源

在现代嵌入式系统设计中,51单片机作为一种经典的微控制器,凭借其丰富的功能和广泛的应用领域,仍然受到工程师们的青睐。定时器中断是51单片机中一个非常实用的功能,它可以在特定的时间间隔内自动触发中断,执行预设的操作,从而提...

关键字: 51单片机 定时器

Holtek新推出BS67F2432具备触控按键、高精准度HIRC与LCD驱动器Flash MCU。主要特色为内建高精准度4MHz HIRC振荡电路、8路触控按键及最大支持4COM×15SEG LCD驱动器。适用于触控接...

关键字: MCU LCD驱动器 定时器
关闭