1. pwm脉宽调制器
脉宽调制器: 一种硬件设备, 用于 动态调制 方波 的 一些属性, 方波的周期,频率,占空比
占空比? : 有效电平占 整个周期的比值
可以使用PWM 控制功率, 控制频率 用于 开关电源 或 逆变器
1.1 原理
PWM原理: 如图所示
本质就是一个定时器:
由原理可知:
输出波形的 频率 = 总线时钟 / (分频值+1) / 重载值 ;
输出波形的 占空比 = 比较值 / 重载值
1.2 pwm标准时钟的频率
100Mhz
2. 实验:使用pwm驱动蜂鸣器 以500hz 占空比50% 发出声响
输出定时器信号的 频率 = 总线时钟 /固定分频/ (分频值+1) / 重载值 ;
占空比 = 比较寄存器/重载值
实现功能 输出一个 500hz 方波 占空比 50%
500hz = 100M / (分频值+1) / 重载值 ; //这里不固定分频
500hz = 100M / (99+1) / 重载值 ;
500hz = 1M / 重载值 ;
重载值 = 2K
0.5 = 比较值 / 重载值 ;
比较直 = 1K
2.1 看原理图
1292页
我们走红色线路
1. 硬件 : 蜂鸣器
2. 电路图
芯片管脚 PD0_0 ---- XpwmTOUT0 PWM输出
3. pwm控制器 芯片手册
5个 pwm
0-3 有 PWM 输出
0 pwm 有 死区控制
4 pwm 没有输出
死区控制: 主要用于控制 半H桥电路 或 全H桥电路 有用
控制器 结构框图 1292 页
2.2 配置寄存器
TCFG0 两路预分频
TCFG0 : 两路预分频 死区配置
[7:0] = 预分频
TCFG1 5路固定分频
TCFG1 : 5路 固定分频 配置
[3:0] = 0-4 分别对应 1/1 1/2 1/4 1/8 1/16
TCNTB0: PWM0 重载寄存器 32bit 0 - 2^32-1
TCMPB0: PWM0 比较寄存器
TCNTO0: PWM0 计数寄存器 只读
TCON : 总控
TCON : 总控
[4] = 0 不使能死区
[3] = 0 单次模式 1 自动重装
[2] = 1 打开输出
[1] = 1 装载 重载寄存器 比较寄存器
[0] = 1 启动pwm0
2.3 写代码
pwm_test----main.c
#include"exynos_4412.h"
#include"uart.h"
//使用pwm驱动蜂鸣器 以500hz 占空比50% 发出声响
//pwm 初始化
void pwm_init(){//配置GPD0_0 为pwm功能GPD0.CON = (GPD0.CON & ~(0xf<<0)) | (2<<0);//配置pwm控制器,五路固定分频 TCFG1 [3:0] = 0 这里蛇蛇不固定分频PWM.TCFG1 &= ~(0xf);//两路预分频 TCFG0 [7:0] = 99 100M/(99+1) = 1MPWM.TCFG0 = (PWM.TCFG0 & ~(0xff<<0)) | (99<<0);//重载值PWM.TCNTB0 = 2000;//比较寄存器PWM.TCMPB0 = 1000;//配置总控//不使能死区PWM.TCON &= ~(1<<4);//自动重装PWM.TCON |= 1<<3;//打开输出PWM.TCON |= 1<<2;//装载TCNTB0 TCMPB0PWM.TCON |= 1<<1;//关闭装载PWM.TCON &= ~(1<<1);//启动pwmPWM.TCON |= 1;}int main()
{int a = 100;uart_init();printf("hello!a=%d\r\n",a);pwm_init();while(1);return 0;
}
3. 使用蜂鸣器调出音律
这里我们调制 高音即可
输出定时器信号的 频率 = 总线时钟 /固定分频/ (分频值+1) / 重载值 ;
占空比 = 比较寄存器/重载值
pwm_muisc-----main.c
#include"exynos_4412.h"
#include"uart.h"//pwm 模拟音律播放volatile unsigned int count = 0;//毫秒级变量//延时 ms
void delay(unsigned short ms){unsigned int tmp = count;//存放刚进入delay函数时 count 的数值// while(count <= tmp+ms);//这种算法没有规避溢出问题while(count-tmp < ms);//这种算法规避了溢出问题,不必纠结算法,用就完事了}//中断初始化
exit_init(){//GIC 面向中断源//开启总中断ICDDCR = 1;//配置端口中断使能//中断模式: wdt中断 id 75//75/32=2 75%32=11ICDISER.ICDISER2 |= 1<<11;//配置端口优先级 优先级设置为5//75/4= 18 75%4=3 ---- [15:8]ICDIPR.ICDIPR18 = (ICDIPR.ICDIPR18 & ~(0xff<<24)) | (5<<24);//配置中断源送去哪个cpu处理 0x1表示直送cpu0//寄存器分步格局 与ICDIPR 完全一样 ICDIPTR.ICDIPTR18 = (ICDIPTR.ICDIPTR18 & ~(0xff<<24)) | (0x1<<24);//GIC 面向cpu//cpu响应中断使能 =1 使能 =0 不使能CPU0.ICCICR = 1;//配置cpu过滤优先级CPU0.ICCPMR = 255;}//中断响应,c语言入口函数,在汇编汇总调用,当irq异常触发时
void do_irq(){//获取中断号int id = CPU0.ICCIAR;//根据中断id来处理对应的事件switch(id){case 75:count++;//先清除中断 源头的挂起 看门狗的中断//写入任何值清除WDT.WTCLRINT = 8;//在清除GIC分配器层中断挂起 与ICDISER_CPU 结构一样 id:57//置为1 清除ICDICPR.ICDICPR2 |= 1<<11;break;}//最后清除cpu中断挂起//写入中断id清除对应中断挂起CPU0.ICCEOIR = id;}//看门狗初始化
void dog_init(){//预分频WDT.WTCON = (WDT.WTCON &~(0xff<<8)) | (24<<8);//固定分频WDT.WTCON = (WDT.WTCON &~(0x3<<3)) | (0<<3);//触发中断信号 [2] 时间到,是否触发中断信号 = 1 触发中断 WDT.WTCON |= 1<<2;//重载寄存器WDT.WTDAT = 250;//计数寄存器WDT.WTCNT =250;//开启看门狗WDT.WTCON |= 1<<5;
}//pwm 初始化
void pwm_init(){//配置GPD0_0 为pwm功能GPD0.CON = (GPD0.CON & ~(0xf<<0)) | (2<<0);//配置pwm控制器,五路固定分频 TCFG1 [3:0] = 0 这里设不固定分频PWM.TCFG1 &= ~(0xf);//频率 = 总线时钟 /固定分频/ (分频值+1) / 重载值 ;//两路预分频 TCFG0 [7:0] = 99 100M/(99+1) = 1MPWM.TCFG0 = (PWM.TCFG0 & ~(0xff<<0)) | (99<<0);//重载值PWM.TCNTB0 = 2000;//比较寄存器 占空比 = 比较寄存器/重载值PWM.TCMPB0 = 1000;//配置总控//不使能死区PWM.TCON &= ~(1<<4);//自动重装PWM.TCON |= 1<<3;//打开输出PWM.TCON |= 1<<2;//装载TCNTB0 TCMPB0PWM.TCON |= 1<<1;//关闭装载PWM.TCON &= ~(1<<1);}//启动pwm
void pwm_start(){//启动pwmPWM.TCON |= 1;
}//关闭pwm
void pwm_stop(){//启动pwmPWM.TCON &= ~1;
}//改变音色
void chanage_pinlv(unsigned int hz){//重载值PWM.TCNTB0 = 1000000/hz;//比较寄存器 //占空比我们设为50%PWM.TCMPB0 = 1000000/hz/2;//装载TCNTB0 TCMPB0PWM.TCON |= 1<<1;//关闭装载PWM.TCON &= ~(1<<1);//打开pwmpwm_start(); //因为我们在播放音律函数时 停止了pwm 所以每次改变音色 都要重新开启pwm
}//定义音符频率
#define H1 1046
#define H2 1175
#define H3 1318
#define H4 1397
#define H5 1568
#define H6 1760
#define H7 1976
#define ST 0//播放音律
void play(){chanage_pinlv(H1);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H2);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H3);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H4);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H5);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H6);delay(1000);//响一秒pwm_stop();delay(500);//停一秒chanage_pinlv(H7);delay(1000);//响一秒pwm_stop();delay(500);//停一秒
}int main()
{uart_init();printf("music!!!\r\n");//看门狗初始化dog_init();//中断初始化exit_init();//pwm初始化pwm_init();//开启pwmpwm_start();int i=0;while(1){play();delay(2000);//所有音律播放完成总体停2秒}return 0;
}