写定时器代码,首先需要知道基础知识,如下
1.什么是定时器
定时器就是CPU的小秘书,CPU可以让定时器在一个时间段后叫他。
所以定时器的关键词 就是 :时间段 + 中断。
常见的和定时器相关的硬件:
PWN定时器:
带有PWM功能的定时器
系统定时器:
给OS生成时间片的,OS使用时间片调度进程。
看门狗定时器:
带有复位功能的定时器
RTC:
不是定时器,而是时钟,确定时间点的,也能产生中断,精度为,年月日时分秒星期
对于定时器只需要抓住 时间段 和 中断即可,中断前面讲过。
时间段 = 时钟周期 * 计数值
所以要抓时间段,就是抓 时钟周期 和 计数值。
时钟周期一般是是 源时钟 和 分频 和MUX 得到的。
计数值一般有个寄存器专门存放,如 TCNT,
工作逻辑是,一个时钟周期,TCNT中的计数值减一,减到0就发出中断。
2. PWM定时器
PWM定时器 关键词: PWM 、 定时器
先看定时器,按照上面的分析学定时器,就是学如何设置 时钟周期 和 计数值。
看 SoC数据手册可有下图:
先看时钟周期:
时钟源有可选 PCLK 或SCLK_PWM
选定时钟源后进行了两次分频,涉及 预分频器,和分频器,并且可以看出有些PWM定时器是共用预分频器的。
这样就得到了时钟周期
再看计数值
Control Logic模块中 TCNTB设置计数值。
设置了计数值。
分析完了定时器,再分析 PWM
先说什么是 PWM,
PWM就是输出这样的电势变化,即周期的进行 0,1电势变化。
实际运用比如PWM调光。
PWM的关键词:时钟周期 、占空比
时钟周期通过上面的选时钟源和分频可以确定。
占空比:
占空比通过 TCMP 设置,
当
TCNT < TCMP 时,输出低电平
TCNT > TCMP 时,输出高电平
这样 高电平输出为 T * duty
低电平输出为 T*(1-duty)
这样就完成了 PWM定时器的设置思路。
下面讲特别的功能:
(1)双缓冲
有两对寄存器,TCNT和TCNTB ,TCMP 和 TCMPB,其中TCNT和TCMP是PWM定时器工作使用的寄存器,但是程序员无法操作,程序员只能操作TCMPB和 TCNTB,将设置的值写入 B 寄存器中,然后可以将其刷入 TCNT和TCMP中。
(2)自动重加载
定时器的工作通常是重复的,当完成一次定时,又开始下一次定时,所以 SoC提供了硬件实现的自动重加载,开启自动重加载后,完成定时后, TCNTB 和 TCMPB 的值会被自动刷入 TCNT 和 TCMP 中。
(3)输出电平反转器
即将输出高、低进行反转,设置占空比。
3. 实战蜂鸣器
步骤一样,先回顾蜂鸣器的基本知识,然后看原理图,再结合SoC数据手册,按照蜂鸣器原理写代码。
3.1 基本知识
蜂鸣器如下,
当通电时,上面两个铁皮就会相吸,不同电就放开,当有一定频率人耳就听得见了。
这个特性和PWM符合,所以使用PWM定时器的PWM功能就能实现。
(2)看原理图
可以看出,上面有个三极管,当PWMTOUT2输出高时,三级管就会接通,VDD_IO就会有电流。
所以编程需要设置 PWMTOUT2 引脚模式为PWMTOUT模式。
那么现在思路就是设置PWM定时器并使其输出PWM波,并设置上面的引脚输出PWM。
对于 PWM 定时器,这里只需要PWM功能,所以只需要设置 时间周期(也就是工作频率),和 占空比(也就是 TCNT 和 TCMPB),然后要使用 自动刷新。
#define GPD0CON (0xE02000A0) #define TCFG0 (0xE2500000) #define TCFG1 (0xE2500004) #define CON (0xE2500008) #define TCNTB2 (0xE2500024) #define TCMPB2 (0xE2500028) #define rGPD0CON (*(volatile unsigned int *)GPD0CON) #define rTCFG0 (*(volatile unsigned int *)TCFG0) #define rTCFG1 (*(volatile unsigned int *)TCFG1) #define rCON (*(volatile unsigned int *)CON) #define rTCNTB2 (*(volatile unsigned int *)TCNTB2) #define rTCMPB2 (*(volatile unsigned int *)TCMPB2) void pwm_init() { rGPD0CON &= ~(0xf << 8); rGPD0CON |= (2 << 8); // 设置预分频 rTCFG0 &= ~(0xff << 8); rTCFG0 |= (65 << 8); // 设置分频 rTCFG1 &= ~(0xf << 8); rTCFG1 |= (1 << 8); // auto reload rCON |= (1 << 15); // 设置计数值 rTCNTB2 = 50; // 设置占空比 rTCMPB2 = 25; // Manual Update rCON |= (1 << 13); rCON &= ~(1 << 13); // start rCON |= (1 << 12); }
此外,我们还知道,通过调节分频即时钟周期,可以调节蜂鸣器发出的音频HZ,调节占空比可以调节音量大小。