首先是 硬件电路图:
然后是数据手册中 找到 相关的寄存器, 首先是 GPIO的复用寄存器, 然后是 PWM的寄存器。
首先是 关于GPIO的 复用 , 这里是 Tout, 也就是 定时器, pwm 通过 定时器 通过某种方式来控制 引脚输出的 高低电平的。
然后是就是 去看 PWM的寄存器了。
先来看一下 寄存器的大致的结构。
TCFG0
这是一级分频
TCFG1
TCON
这里我不明白的就是 , 这个 update TCN , TCM 是什么意思呢? 它在更新什么呢?
------------------------------------------------------------------------------------------------------------------------
关于update 的解释。
具体的解释 就不解释了,太麻烦了,说说我的理解。
1 cpu 将 TCNTBn , TCMPBn 中的数字 下载到 TCNTn , TCMPn 也是需要一个时钟周期的。
2 这里的手动更新的意思是 ,立马把 TCNTBn , TCMPBn 中的数据 装到 TCNTn , TCMPn 中。
3 我没设计过 硬件, 但是 我猜测, 几遍是 把 pwm 的执行开关打开, 它内部也是有一个 执行顺序的。
-----------------------------------------------------------------------------------------------------------------------
TCN,TCM, 这两个就比较简单了。
时钟的计算 , 有个表格。
这是具体的 时钟的公式。
然后是 代码的解析。
#include "exynos_4412.h"
//#include "led.h"
void delay_ms(unsigned int num)
{
int i,j;
for(i=num; i>0;i--)
for(j=1000;j>0;j--)
;
}
void pwm_init(void)
{
// 这是在设置 复用
GPD0.CON = GPD0.CON & (~(0xf))| 0x2;
GPD0.PUD = GPD0.PUD & (~(0xf)) ;
// 这里 第一级分频 设置成了 249
PWM.TCFG0 = PWM.TCFG0 & (~(0xff))|0xf9;
// 第二级分频 设置成了 2
PWM.TCFG1 = PWM.TCFG1 & (~(0xf)) | 0x2;
// 那么最后的频率 就是 66/(249+1)/2 = 132K
PWM.TCMPB0 = 50;
PWM.TCNTB0 = 100;
// 这里设置了, 开启定时器,启动 手动更新。 我觉的这里 可以先不 开启定时器。
// 我觉得 这里 只是 设置 TCM , TCN 的值, 然后 设置 成自动装载 就可以了。
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 0) | (1 << 1) ;
}
void beep_on(void)
{
// 这里是 开启定时器, 并且设置了自动装载
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 0) | (1 << 3) ;
}
void beep_off(void)
{
PWM.TCON = PWM.TCON & (~(1 << 0)) ;
}
int main (void)
{
pwm_init();
while(1)
{
beep_on();
delay_ms(10000000);
beep_off(); //
delay_ms(1000000);
}
return 0;
}
这里 至于 时钟分频 为什么是 这个数值 ,我也不知道。
然后是源码的结构,以及源码的编译。
接下来是 我自己 适配一下 源码 编译 + 烧写到板子上。
编译时没有问题的, 我这里测试 , 即便是 把 蜂鸣器关掉 依然是 可以发生, 会不会是 有缘蜂鸣器呢?
嗯呢,经过我 的确认, 蜂鸣器 确实是 有源的蜂鸣器。
注意: 这里我发现一个现象, 就是一但我 将引脚设置成 tout 的话, 那么 不论 我 停止 定时器,还是 开启定时器,板卡上的蜂鸣器 一直是响的,也就是 说,这个引脚 一直是高电平。
应该是跟这里 有关的, 如果我关闭 定时器的话, 它一直是 3.3V, 如果我开启定时器的话, 那么它 比 3.3V 低, 但也是 高电平, 除非我 将占空比 设置的 很小, 低电平时间很长。
---------------------------------------------------------------------------------------------------------------------------
然后 我购买了 ,无缘的蜂鸣器,焊接在板子上。
重新编译程序, 发现 正常。
程序如下:
#include "exynos_4412.h"
//#include "led.h"
void delay_ms(unsigned int num)
{
int i,j;
for(i=num; i>0;i--)
for(j=1000;j>0;j--)
;
}
void pwm_init(void)
{
GPD0.CON = GPD0.CON & (~(0xf))| 0x2;
GPD0.PUD = GPD0.PUD & (~(0xf)) ;
PWM.TCFG0 = PWM.TCFG0 & (~(0xff))|0xf9;
PWM.TCFG1 = PWM.TCFG1 & (~(0xf)) | 0x2;
PWM.TCMPB0 = 50;
PWM.TCNTB0 = 100;
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 1) ;
}
void beep_on(void)
{
PWM.TCON = PWM.TCON & (~(0xff)) | (1 << 0) | (1 << 3) ;
}
void beep_off(void)
{
PWM.TCON = PWM.TCON & (~(1 << 0)) ;
}
int main (void)
{
pwm_init();
while(1)
{
beep_on();
delay_ms(500);
beep_off();
delay_ms(500);
}
return 0;
}
然后 这个 蜂鸣器是 3V的电压。
电阻是 42 欧的。
-------------------------------------------------------------------------------------------------------------------------------
我的疑问, 我并没有 清除中断, 为什么 程序是正常的呢?