定时器相关函数:定时器初始化函数与定时器中断函数。
定时器初始化函数主要是用于对定时器T0/T1/T2/T3/T4进行相关寄存器的配置,如指定是定时功能还是计数功能,12T/1T时钟模式,定时器TH0,TL0的初始值等。
16位很好理解,就是2的16次方,即65536,假设TH0和TL0最大存储组合为0xFFFF,即65535,当TH0和TL0等于65535时表示定时器要溢出了,如果是8位定时器,就只用到TL0,最大只能到255。
所以大家要知道这个16位和8位指的是什么,就是定时器TH0和TL0的最大值。
在定时器寄存器配置这里,我琢磨出几个点,因为TMOD是T0和T1共用寄存器嘛,冲哥视频里用了与运算,和或运算。
如:
AUXR |= 0x80; //定时器时钟1T模式,这里用或运算是为了保证T0x12 = 1不变,7F=1000,0000.
TMOD &= 0xF0; //设置定时器模式为16位自动重装载,F0=1111,0000,T0_GATE= 0,T0_C/T=0,T0_M1=0,T0_M0=0,
这里大家琢磨下,如果我想保持T0为1T模式不变,我就必须用或的方式,因为这位为1,如果在前面的程序中有写入AUXR = 0x08,是不是可以保证第1位仍为0不变,不会受到后面的干扰。
那如果想保持某位为0不变,就适用与门,因为与门是全1得1,只要有1个0,那这位就是始终为0了。请看TMOD &= 0xF0,保证低4位为0,即T0的工作模式不被打扰。
与门适合那种保持某位为0状态,因为更新后无论是1或0,这位始终为0。
或门适合保持某位为1状态,因为这位只要是1就不受影响。
这个在后面都可以用到。
为什么这里要讲下与,或,非门呢,因为在视频中有介绍到手册“定时器0模式”,用1张图说明了定时器的工作原理,就必须掌握与或非门才能更好的理解定时器工作流程,因为寄存器的某1位在这里面充当的开关的作用,在为0或置1时会导致定时器走向不同的路线。
具体大家看下我上传的图片,里面都要说明。这里也更好理解为什么T0_GATE = 1 & INT0 = 1 &TR0 =1时才能打开定时器0/计数器0了。大家看着我的注释一起把流程走一遍,就会有一种豁然开朗的感觉。在这个图里也能知道到底要配置哪些寄存器与参数了。
放上一个程序,供大家参考下。同时EXCEL文档内有定时周期计算公式,方便大家学习,当然STC-ISP工具也有定时器计算器,给我们省了很大的事,但是我们还是要弄懂这个原理。
- /***********************************************************************
- 第11集 定时器
- ___
- 主程序 /
- | __/
- | __ 定时器计时到了,先执行定时器中断程序,
- | \ 执行完后再返回主程序继续执行。
- 主程序 \___
-
- 1.定时器/计数器的核心部件是一个加法计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:
- 如果计数脉冲来自系统时钟,则为定时方式 ,此时定时器/计数器每12个时钟或者每1个时钟得到一个
- 计数脉冲,计数值加1;如果计数脉冲来自于单片机外部引脚,则为计数方式,每来1个脉冲加1。
- 2.STC32G支持24位定时器,8位预分频+16位自动重装载。
- 3.定时器/计数器寄存器说明:
-
- 符号 描述 地址 B7 B6 B5 B4 B3 B2 B1 B0 复位值
- TCON 定时器控制寄存器 88H TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 0000,0000
- TMOD 定时器模式寄存器 89H T1_GATE T1_C/T T1_M1 T1_M0 T0_GATE T0_C/T T0_M1 T0_M0 0000,0000
- AUXR 辅助寄存器1 8EH T0x12 T1x12 UART_M0x6 T2R T2_C/T T2x12 EXTRAM S1BRT 0000,0001
- T4T3M 定时器4/3控制寄存器 DDH T4R T4_C/T T4x12 T4CLKO T3R T3_C/T T3x12 T3CLKO 0000,0000
-
- TH0,定时器0高8位寄存器,TL0,定时器0低8位寄存器,最大值65535。
- TH1,定时器1高8位寄存器,TL1,定时器1低8位寄存器,最大值65535。
- T2H,定时器2高8位寄存器,T2L,定时器2低8位寄存器,最大值65535。
- T3H,定时器3高8位寄存器,T2L,定时器3低8位寄存器,最大值65535。
- T4H,定时器4高8位寄存器,T4L,定时器4低8位寄存器,最大值65535。
-
- TM0PS, 8位定时器0时钟预分频寄存器,最大值255。
- TM1PS, 8位定时器0时钟预分频寄存器,最大值255。
- TM2PS, 8位定时器0时钟预分频寄存器,最大值255。
- TM3PS, 8位定时器0时钟预分频寄存器,最大值255。
- TM4PS, 8位定时器0时钟预分频寄存器,最大值255。
-
- T1_M1,T1_M0 = 00B,两位二进制用来配置寄存器工作模式。
- 00 —— 16位自动重装载
- 01 —— 16位不自动重装载
- 10 —— 8位自动重装载
- 11 —— 不可屏蔽中断的16位自动重装载
- 定时器T0,T1,T2,T3,T4并不是全部支持4种模式,请看下表:
- 定时器 模式0 模式1 模式2 模式3
- 00B 01B 10B 11B
- T0 √ √ √ √
- T1 √ √ √ ×
- T2 √ × × ×
- T3 √ × × ×
- T4 √ × × ×
-
- T0,T1 16位自动重装载模式,定时周期计算公式:SYSclk为系统时针,TM0PS默认值为0,最大值为255
- 1T模式: 定时器周期 = [65536-[TH0,TL0]] / [SYSclk/(TM0PS+1)]
- 12T模式:定时器周期 = {[65536-[TH0,TL0]]/ [SYSclk/(TM0PS+1)]}*12
-
- 如何配置定时器,采用寄存器写入方式:
- 1.选择想要使用的定时器,如选择T0,自定义T0函数void Timer0_Init(void),把2~5寄存器写入内容放到函数内;
- 2.选择定时器时钟模式1T/12T,12T模式——AUXR &= 0x7F; 即AUXR &= 0111 1111,T0x12 =0为12T,置1则为1T,用与运行是保证T0x12为0不变。
- 1T模式——AUXR |= 0x80;即AUXR |= 1000 0000,T0x12 =1为1T,用或运行是保证T0x12为1不变。
- 3.配置TMOD寄存器T0工作模式,TMOD &= 0xF0; 即TMOD &= 1111 0000,低4位是T0,用与运行是保证T0低4位为0000不变。
- 4.设定8位预分频,最大值为0xFF,即255,假设定时周期为0.1s,根据定时周期计算公式反算得出TM0PS和[TH0,TL0],编写好TH0和TL0的值。
- 5.TF0 = 0; //清除TF0标志,TF0是T0的中断请示位,定时器0溢出中断标志。中断服务程序中,硬件自动清零。
- TR0 = 1; //定时器0开始计时,只有T0_GATE = 0,TR0 = 1时,T0才开始计时
- ET0 = 1; //使能定时器0中断,是IE中断允许寄存器的B1位,ET0是T0的中断允许位,详见《STC32G芯片手册》第12.4.1节
- 6.新建void Timer0_Isr(void) interrupt 1 { //放中断执行程序 }中断函数,注意“interrupt 1”需要在手册5.9.2节中查询对应的中断号,
- 这里T0的中断号是“1”。
-
- 以上,定时器T0的中断模式参数配置完成。
-
- ***本程序执行过程:主程序是P2.7上的LED亮5s,再熄灭5s。定时器是0.5s进1次中断,P2.0上的LED每隔0.5s取1次反,
- 所以看到程序的运行效果是,P2.7和P2.0有同时点亮的情况,类似主程序与中断程序分别执行互不干扰。***
-
- ***********************************************************************/
-
- #include <STC32G.H>
- #include "comm/stc32_stc8_usb.h"
-
- #define MAIN_Fosc 24000000UL // 定义一个主时钟24MHz
-
- char *USER_DEVICEDESC = NULL;
- char *USER_PRODUCTDESC = NULL;
- char *USER_STCISPCMD = "@STCISP#";
- void sys_init();
-
- void delay_ms(u16 ms)
- {
- u16 i;
- do
- {
- i= MAIN_Fosc/6000;
- while(--i);
- } while(--ms);
- }
-
- void Timer0_Init(void); // 寄存器配置函数
-
- // 流水灯相关说明,P2.0~P2.7为共阳极连接,P4.5接三极管基极,为低电平时发射极与基极接通,
- // 电流饱合后,发射极到集电极接通,LED得到高电平,P2.0~P2.7输出低电平即可点灯。
- sbit ON_LED = P4^5; // 点灯总开关,三极管是小电流控制大电流的开关
- sbit LED_1 = P2^0; // 流水灯LED1
- sbit LED_2 = P2^1; // 流水灯LED2
- sbit LED_3 = P2^2; // 流水灯LED3
- sbit LED_4 = P2^3; // 流水灯LED4
- sbit LED_5 = P2^4; // 流水灯LED5
- sbit LED_6 = P2^5; // 流水灯LED6
- sbit LED_7 = P2^6; // 流水灯LED7
- sbit LED_8 = P2^7; // 流水灯LED8
-
- void main()
- {
- sys_init(); //系统初始化
- usb_init(); //USB CDC 接口配置
- EA = 1; //打开总中断
- ON_LED = 0 ; //打开LED总开关
- Timer0_Init();
-
- while(1)
- {
- LED_8 =0;
- delay_ms(5000);
- LED_8 =1;
- delay_ms(5000);
- }
- }
-
- void Timer0_Isr(void) interrupt 1
- {
- //放中断执行程序
- ON_LED = 0;
- LED_1 = !LED_1;
- }
-
- void Timer0_Init(void) //0.5秒@24.000MHz
- {
- AUXR &= 0x7F; //定时器时钟12T模式,这里用与运算是为了保证T0x12 = 0不变,7F=0111,1111
- TMOD &= 0xF0; //设置定时器模式为16位自动重装载,F0=1111,0000,T0_GATE= 0,T0_C/T=0,T0_M1=0,T0_M0=0
- TL0 = 0xFC; //设置定时初始值低8位
- TH0 = 0x45; //设置定时初始值高8位
- TM0PS = 0x14; //65536-{[SYSclk/(TM0PS+1)]*(0.1/12)}
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0 = 1; //使能定时器0中断
- }
-
- void sys_init()
- {
- WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
- EAXFR = 1; //扩展寄存器(XFR)访问使能
- CKCON = 0; //提高访问XRAM速度
-
- P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
- P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
- P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
- P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
- P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
- P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
- P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
- P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
-
- //====== USB 初始化 ======
- P3M0 &= ~0x03;
- P3M1 |= 0x03;
-
- IRC48MCR = 0x80;
- while (!(IRC48MCR & 0x01));
-
- // USBCLK = 0x00; //使用USB-HID需屏蔽此行
- // USBCON = 0x90; //使用USB-HID需屏蔽此行
- }
复制代码
|