二:PWM配置

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秒钟

}

}