【单片机】【PIC16F1937】之定时器

这篇文章是谈谈关于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)

 

转载于:https://www.cnblogs.com/iteou/p/5686440.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值