Microchip PIC系列8位单片机入门教程(5):定时器

01第一节 知识点
我们通过定时器0的讲解来实现多个定时器的定时功能。
(1)timer0 模块具有以下特征:
• 可通过软件选择,作为8 位或16 位定时器/ 计数器
• 可读写的寄存器
• 专用的8 位软件可编程预分频器
• 可选的时钟源(内部或外部)
• 外部时钟的边沿选择
• 溢出中断
(2)timer0工作原理
timer0 既可用作定时器亦可用作计数器;具体的模式由tocs 位(t0con)选择。在定时器模式下(t0cs = 0),除非选择了不同的预分频值,否则,默认情况下在每个时钟周期该模块的计时都会递增(见第11.3 节“预分频器”)。如果写入tmr0 寄存器,那么在随后的两个指令周期内,计时将不再递增。用户可通过将校正后的值写入tmr0 寄存器来解决上述问题。通过将t0cs 位置1 选择计数器模式。在计数器模式下, timer0 可在ra4/t0cki 引脚信号的每个上升沿或下降沿递增。触发递增的边沿由timer0 时钟源边沿选择位t0se (t0con)决定。清零此位选择上升沿递增。下面讨论外部时钟输入的限制条件。可以使用外部时钟源来驱动timer0。但是必须确保外部时钟与内部时(tosc)相位同步。在同步之后,定时器/ 计数器仍需要一定的延时才会引发递增操作。
(3) 中断
当tmr0 寄存器发生溢出时(8 位模式下,从ffh 到00h ;或16 位模式下,从ffffh 到0000h),将产生tmr0 中断。这种溢出会将标志位tmr0if 置1。可以通过清零tmr0ie 位(intcon)来屏蔽此中断。在重新允许该中断前,必须在中断服务程序中用软件清
零tmr0if 位。由于timer0 在休眠模式下是关闭的,所以tmr0 中断无法将处理器从休眠状态唤醒。
(4) 定时器的时钟选择内部fosc/4;
定时器的初值为0的话,8位模式, 一次中断的时间为(1/(fosc/4)256; 如果定时1s 中断的计数值为n=1/((1/(fosc/4)256);
eg: fosc=40mhz 1s定时n=39063
02第二节 软件设计
我们新建一个关于定时器的头文件和一个源文件
(1) timer_config.h
/** file: timer_config.h* author: greg* comments: 定时器的配置和初始化程序* revision history: version 1.1*/// this is a guard condition so that contents of this file are not included// more than once. #ifndef _timer_config_h_#define _timer_config_h_#include // include processor files - each processor file is guarded. extern unsigned int timer0num=0;extern unsigned int timer1num=0;extern unsigned int timer2num=0;void timer0_config_init(void);void tiner1_config_init(void);void timer2_config_init(void);void timer3_config_init(void);#endif /* _timer_config_h_ */(2)timer_config.c
#include timer_config.hvoid timer0_config_init(void){ //没有预分频,可以预分频 tmr0on=1; // enable timer0 t08bit=1; // 8bit model t0cs=0; //clock is selected by internal clko psa=1; // 未经分频器 // 中断timer0 使能 tmr0ie=0; // timer0 允许中断 tmr0if=0; // 中断标志位清零 tmr0l=0; // 初值为0}void tiner1_config_init(void){ //没有预分频,可以预分频 t1conbits.rd16=1;// 16位操作 t1run=0;// 时钟由时钟源产生 t1oscen=0; tmr1cs=0;// 内部时钟 fosc/4 tmr1on=1;// timer1 使能 tmr1ie=0;// timer1 允许中断 tmr1if=0; tmr1=0; //timer1 初值}void timer2_config_init(void){ t2conbits.tmr2on=1;// timer2使能 t2conbits.t2ckps=0b00; //预分频值为1 t2conbits.t2outps=0b0000; //timer2输出后分频为1 tmr2=0; //timer2 初值w为0; pr2=0xff;// tiner2 周期寄存器的值设置为256;tmr2的值和pr2的值相等时是tmr2if为1; tmr2ie=0;// timer2允许中断 tmr2if=0;}void timer3_config_init(void){ t3conbits.rd16=1;// 16位操作 t3conbits.t3ckps=0b00;// 预分频 t3conbits.t3sync=1;// 不与外部时钟同步 t3conbits.tmr3cs=0;// 内部时钟 t3conbits.tmr3on=1;// timer3使能 tmr3=0; //timer3 初值 tmr3ie=1;// timer3允许中断 tmr3if=0;}再新建两个关于中断的头文件和源文件
(3)inrt_config.h
// this is a guard condition so that contents of this file are not included// more than once. #ifndef _inrt_config_h_#define _inrt_config_h_#include // include processor files - each processor file is guarded.#include usart_dr.hvoid interrupt_config_init(void);// 高级优先级中断服务子程序 声明void interrupt high_priority inrt_isr_high(void);//低级中断服务子程序 声明void interrupt low_priority inrt_isr_low(void);#endif /* _inrt_config_h_ */(4)inrt_config.c
#includetimer_config.h#include inrt_config.hvoid interrupt_config_init(void){ intconbits.gie=1;//允许全局中断 intconbits.peie=1;// 允许外设中断 rconbits.ipen=1; // 中断优先级使能位 rcie=1; //usart中断使能 rcip=1; // usart中断优先级高 rcif=0; tmr0ip=1;// timer0 设置为高级优先中断 tmr1ip=1; //timer1 设置为高级优先级中断 tmr2ip=1; //timer2 设置为高级优先级中断 tmr3ip=1; //timer3 设置为高级优先级中断}// 高级优先级中断服务子程序void interrupt high_priority inrt_isr_high(void){ //usart 服务 if(rcif&&rcie) { rcif=0; // 必须先清楚rc中断标志位 usart_send_byte(rcreg); } //timer 0 服务 if(tmr0ie&&tmr0if) { tmr0if=0; timer0num++; if(timer0num==39063) { usart_send_string(timer0 is count for 1s!rtn); timer0num=0; } } //timer 1 服务 if(tmr1ie&&tmr1if) { // 在这里定时器的初值在初始化设置为0,因此不需要再赋初值 tmr1if=0; timer1num++; if(timer1num==305) //16bits { usart_send_string(timer1 is count for 2s!rtn); timer1num=0; } } if(tmr2ie&&tmr2if) { // 在这里定时器的初值在初始化设置为0,因此不需要再赋初值 tmr2if=0; timer2num++; if(timer2num==39063) { usart_send_string(timer2 is count for 1s!rtn); timer2num=0; } } //timer3 服务 if(tmr3ie&&tmr3if) { // 在这里定时器的初值在初始化设置为0,因此不需要再赋初值 tmr3if=0; timer1num++; if(timer1num==458)//3s 16bits { usart_send_string(timer3 is count for 3s!rtn); timer1num=0; } }}// 低级中断服务程序由此处书写void interrupt low_priority inrt_isr_low(void){ ;}现在具体的定时器和中断的配置已经完成了,我们在主函数中使用:
注意:我们配置字没有修改,默认前期教程的。
#include usart_dr.h#include inrt_config.h#include timer_config.h//#includeplib/adc.h//#include delays.hint main(void){ usart_port_dir_init(); usart_config_init(); interrupt_config_init(); timer0_config_init(); tiner1_config_init(); timer2_config_init(); timer3_config_init(); usart_send_string(i love you!); while(1) { } return 0;}下载到开发板中测试吧,我已经测试过没有问题。

ARM/StrongARM
智慧视通蜂鸟实时布控系统高效管控疫情的蔓延
“国产化率报告”都有哪些内容与指标?一文读懂
改善生产工艺流程提升多功能电力仪表的寿命
TD-SCDMA海面覆盖策略浅析
Microchip PIC系列8位单片机入门教程(5):定时器
轴承非正常发热及保持架损坏的原因
未来三年上海工业互联网发展的路线是怎么样的?
Anritsu MT8852B蓝牙测试仪技术支持
R8d固件库——GPIO固件库函数说明
利用非完全补偿技术实现超高增益带宽,并降低输入电压噪声
基于飞凌OK113i-S开发板适配10寸LCD显示
运营商加速数字化转型 如何构建和融入新的数字生态圈
KRC内部安全如何控制
中小型芯片代理商生存危机迫在眉睫,路在何方?
干货分享|基于HPM6750 CAN2.0 及 CAN- FD 操作指南
新品速递丨精度为 ±0.5% 的电压监控器
变色灯的电路图
智慧路灯供电及安全设计要求有哪些?
洲明智慧综合杆及智能交通专项工程荣获最佳工程奖