1: PWM其实是一个定时器,配置这些寄存器要注意,需要打开特殊功能寄存器的开关。
1 程序:P_SW2 |= 0x80; // 最高位EAXFR置1 允许访问XFR寄存器
P_SW2的B7位要置1,才能使用特殊功能寄存器哦。
2:打开想要使用PWM模块的时钟,我们这里用PWM0;
我们现在系统时钟,不分频,即B4置0,B0到B3也置0;
2 程序:PWM0CKS = 0X00; // 选择PWM0的时钟为系统时钟
3: 允许PWM0模块允许,在PWM全局设置寄存器里配置;
每一位详细设置如下;
允许PWM0运行的话,PWMSET的B0置1;
3 程序:PWMSET |= 0X01; // 使能PWM0模块
4: 把引脚绑定PWM0模块,因为引脚非常多,绑定的时候要看清楚哦,例如P0.5引脚设置为PWM引脚;
PWM05CR寄存器,ENO置1打开,IN1置1初始电平为高,IN1置0初始电平为低。
4 程序:PWM05CR = 0X80;//把P0.5引脚设置为PWM引脚 ,初始电平是低电平
5:配置PWM的周期和占空比寄存器,
因为PWM是定时器,我们打开以后他就从0开始往上跑,跑到多少截至呢?就是通过PWM0CH和PWM0CL设置的,即周期。
在头文件中这两个8位寄存器是在一起的,我们直接搞个宏定义当一个16位寄存器用吧,
5 程序:#define PWM0C (*(unsigned int volatile xdata *)0xFF00)
这样PWM0C就能替代PWM0CH和PWM0CL了,注意0xFF01地址可千万别瞎折腾。
6:配置占空比,
这4个寄存器共同作用来设置占空比,PWM本质是一个定时器,从0开始计数一直到PWM0C设置的值又重新开始,一直循环;但是计数到T1设置的值引脚会变为低电平,计数到T2设置的值引脚会变为高电平,注意哦,这里我们初始化PWM的时候设置初始电平为低,当遇到T1周期的时候依然为低,也就是不变,这种情况下我们保持T1为0,控制T2就等于控制了占空比。
为了方便,把T2的两个8位寄存器重定义为一个16位的寄存器;
头文件里面找到T1,T2
然后在程序里定义
6 程序:
#define PWM05T1 (*(unsigned int volatile xdata *)0xFF38)
#define PWM05T2 (*(unsigned int volatile xdata *)0xFF3A)
这样就可以直接用一个寄存器设置了。
7:打开PWM0模块,是需要PWMCFG01寄存器的B0位置1;其中B3是状态位,产生中断会置1;B2是归零中断允许,归零是当周期从零计数到设置值的时候,继续从零开始,循环往复;
7 程序:PWMCFG01 = 0X05; // PWM0CEN=1开启PWM定时器开始计数
然后打开总中断,
程序: EA=1;
8:PWM中断服务函数;在中断列表里面查找PWM0的中断号;
9:整个配置PWM05的函数
10:上个蜂鸣器例子吧
#include “stc8g.h”
#include “intrins.h”
/* 寄存器定义 */
#define PWM5C (*(unsigned int volatile xdata *)0xFCA0)
#define PWM53T1 (*(unsigned int volatile xdata *)0xFCC8)
#define PWM53T2 (*(unsigned int volatile xdata *)0xFCCA)
/* 定义音调 低音 中音 高音 */
unsigned int tone_low[7]={0x20A0, 0x1D13, 0x19E7, 0x187E, 0x15CE, 0x136D, 0x1141}; // 1234567 @35MHz
unsigned int tone_mid[7]={0x1058, 0x0E90, 0x0CF8, 0x0C3F, 0x0AE7, 0x09B7, 0x08A7}; // 1234567 @35MHz
unsigned int tone_high[7]={0x082A, 0x0746, 0x067B, 0x061E, 0x0574, 0x04DB, 0x0454}; // 1234567 @35MHz
/* 固定延时1毫秒 */
void Delay1ms() //@35MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 46;
j = 113;
do
{
while (–j);
} while (–i);
}
/* n毫秒延时函数 参数给几 就延时几毫秒 */
void delay_ms(unsigned int ms)
{
while(ms–)
{
Delay1ms();
}
}
/* 蜂鸣器初始化 */
void beep_init()
{
P_SW2 |= 0X80; // 允许访问XFR
PWMSET |= (1<<5);// 使能PWM5模块
PWM5CKS = 0X0F; // 设置为系统时钟的16分频
PWM5C = tone_low[0];
PWM53T1 = PWM5C/2; // 遇到T1输出低电平
PWM53T2 = 0; // 遇到T2输出高电平
PWM53CR = 0XC0; // 把引脚设置为PWM输出口 初始电平是高电平 并关闭所有触发点中断
}
/* 主函数 */
void main()
{
unsigned char i=0; // 定义一个8位变量
P5M0 = 0X00; //设置P5.0~P5.7为双向口模式
P5M1 = 0X00;
beep_init(); // 蜂鸣器初始化
while(1)
{
/* 允许输出音调 */
PWMCFG45 |= 0X10; // 开启PWM5
/* 依次发出低音1234567 */
for(i=0;i<7;i++)
{
PWM5C = tone_low[i];//改变周期
PWM53T1 = PWM5C/2;//占空比为50%
delay_ms(200);
}
/* 依次发出中音1234567 */
for(i=0;i<7;i++)
{
PWM5C = tone_mid[i];//改变周期
PWM53T1 = PWM5C/2;//占空比为50%
delay_ms(200);
}
/* 依次发出高音1234567 */
for(i=0;i<7;i++)
{
PWM5C = tone_high[i];//改变周期
PWM53T1 = PWM5C/2;//占空比为50%
delay_ms(200);
}
/* 关闭PWM模块 停止输出音调 */
PWMCFG45 &= ~0X10; // 关闭PWM5
delay_ms(1000); // 等待1秒钟
}
}