关于定时器(+PWM波)~

学习使我强壮!!!
准备学习PWM,然后,,,发现自己貌似并不是很懂定时(计数)器这个东东,emmm,木得关系,再学习一下!!!
【关于定时器(+PWM波)~】明确:
1. 时钟周期 = 1/11059200,1个机器周期 = 12个时钟周期;
2. 关于定时功能的实现:定时器内部有一个寄存器,开始计数后,每隔一个机器周期(12/11059200秒)自动加一,当加到上限(比如16位的定时器,最大值是65535),那么加到65535后再加1(65536)就会溢出,然后自动清0,定时就是利用这个特点,我们设置一个初始值,让定时器从这个初始值开始加1,加到65536清0,实现1次计时,那么定时值 = (65536 - 初始值),一句话,从某一个初值开始,经过确定的时间后溢出,这就是定时;
3. 定时器分为:定时器0和定时器1;
4. 注意图中红色线框部分:(以定时器0为例)当写TR0 = 1后,定时器就会每隔1个机器周期自动加1
关于定时器(+PWM波)~
文章图片

5. 两个工作模式(模式1和模式2):
关于定时器(+PWM波)~
文章图片

模式1:计数范围是 0~65535,溢出后,只要不对 THn 和 TLn 重新赋值,则从 0 开始计数;
模式2:只有 TLn做加 1 计数,计数范围 0~255,THn 的值并不发生变化,而是保持原值,TLn 溢出后,TFn就直接置 1 了,并且 THn 原先的值直接赋给 TLn,然后 TLn 从新赋值的这个数字开始计数(用来产生串口的通信波特率)
6. 关于TMOD: 低四位是定时器0,高四位是定时器1,要控制定时器0,我们就需要让低四位置1,定时器1,让高四位置1
关于定时器(+PWM波)~
文章图片

7. 让我们来看一下计数初值是怎么计算的呢?加入说我们要定时2ms,也就是0.002秒,设需要计时x个机器周期,那么 x * (12/11059200) = 0.002 ,那么x = 0.002 *(11059200 / 12),而这个x就是我们程序中的tmp了,这个tmp是我们需要计时的个数,那我们的初值怎么计算呢?很简单,只要用 65536-tmp 就好了呀,来看一下代码:

void ConfigTimer0(u8 ms) { u32 tmp; tmp = 11059200 / 12; tmp = (tmp * ms) / 1000; tmp = 65536 - tmp; T0RH = (u8)(tmp >> 8); T0RL = (u8)tmp; TMOD &= 0xF0; TMOD |= 0x01; TH0 = T0RH; TL0 = T0RL; ET0 = 1; TR0 = 1; }

总之就记住一句话!!!计时个数(tmp) = (11059200/12) * 定时时间
明白了上面那些,我们再来看一下PWM波(调占空比)的程序叭~
/*PWM是指高电平占的百分比*/ void ConfigTimer1(u32 fr, u8 dc)//fr代表频率(时间= 1/fr),dc表示高电平所占的份额 { u8 high,low; u32 tmp2; tmp2 = 11059200/12/fr; //算出对应频率下的计数次数 high = (tmp2 * dc) / 100; //高电平的计数次数 low = tmp2 - high; //低电平的计数次数 high = 65536 - high; //高电平的初值 low = 65536 - low; //低电平的初值 HIGHRH = (u8)(high >> 8); //给高八位赋值 HIGHRL = (u8)high; //给低八位赋值 LOWRH = (u8)(low >> 8); LOWRL = (u8)low; TMOD &= 0x0F; //选定定时器1,定时器0也可以,这里我用的是定时器1 TMOD |= 0x10; TH1 = HIGHRH; //给寄存器高八位赋值 TL1 = HIGHRL; //给寄存器低八位赋值 ET1 = 1; //开启中断1 TR1 = 1; //开启计数器 PWMOUT = 1; //讲输出口拉高 }

    推荐阅读