之前使用555搭建PWM电路,需要一些阻容器件配合,能产生周期改变、占空比改变的PWM波,与我们经常谈及的PWM有些不同。由于需要改变外围器件的值,这种方式还是比较麻烦的。这次,我们在学习单片机的基础上,利用单片内部的定时器来实现PWM波。
在实验开始之前,先理解PWM,以及利用定时器产生PWM的原理。
PWM是脉冲宽度调制的英语缩写,通过改变信号的脉冲宽度来控制电路的技术。在PWM中,信号的周期保持恒定不变,但脉冲的宽度可以调节。PWM被广泛用于电机控制、LED调光、电源变换等系统中。通过改变占空比(高电平的时间与脉冲周期的比值),实现对输出功率的精确控制。

相对于NE555,单片机可以进行编程,完成灵活控制。下面我们在不使用单片机定时器的基础上实现PWM波。基本原理是:在程序的主循环中对变量不断进行加1计数,技术范围是0到99。当计数值处于0~49之间时,使某个GPIO口输出0;在计数值处于50~99之间时,使某个GPIO口输出1,这样我们就得到了占空比为50% 的脉冲波。这里50就可以作为阈值使用,改变这个阈值,就能改变脉冲波的占空比。这是最简单、最容易理解的实现方式。代码如下:
typedef unsigned charu8;
typedef unsigned intu16;
typedef unsigned longu32;
// 工作主频
#define MAIN_Fosc 24000000UL
sbit PWMOUT = P2^0; // PWM输出
// 计数变量
u8 cnt = 0;
u8 threshold=50;
void delay_ms(u8 ms);
void delay_us(u8 us);
/******************** 主函数 **************************/
void main(void) {
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P2M1 = 0x00; P2M0 = 0x00; // 准双向口
P40 = 0;//LED Power On
cnt=0;
while(1) {
if (cnt<threshold) PWMOUT = 0;
delay_us(5); // 改变延时数据,可以改变脉冲波的周期
if (cnt>(threshold-1)) PWMOUT = 1;
delay_us(5); // 这里的值一定要和前面的一致,否则会改变占空比
cnt=(cnt+1)%100;
}
}
//========================================================================
// 函数: void delay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
//========================================================================
void delay_ms(u8 ms) {
u16 i;
do {
i = MAIN_Fosc / 6000;
while(--i);
} while(--ms);
}
void delay_us(u8 us) {
u16 i;
do {
i = MAIN_Fosc / 6;
while(--i);
} while(--us);
}
实际上上记程序中的处理,还是有一点误差的。就是判断值范围的那个地方,条件成立和条件不成立时,执行的代码是不一样的。条件成立时多之心了一个代码,尽管代码执行的周期很短。但如果这个周期相对于整个脉冲波的周期的比例很低的时候,可以忽略不计。在程序中,改变阈值threshold就可以改变占空比。
下次实验,我将使用定时器完成PWM波的生成。
我要赚赏金
