一、原理分析
使用定时器输出PWM(脉宽调制)信号是通过微控制器的定时器模块来生成一种周期性的脉冲信号,通过控制脉冲的高电平时间(占空比)来控制输出信号的平均功率。以下是生成PWM信号的基本原理概述:
-
定时器工作原理:
- 定时器是微控制器中的一个功能模块,用于产生精确的时间延时或周期性的计时功能。
- 定时器通常由一个计数器和一个时钟源组成,计数器根据时钟源的脉冲信号进行计数,当计数器的值达到设定的初值时,产生中断或者触发特定的事件。
-
PWM信号生成原理:
- 在生成PWM信号时,定时器被配置为工作在定时器/计数器模式,计数器从一个初始值开始计数,当计数器的值达到设定的比较值时,产生一个输出比较中断。
- 通过调整比较值和定时器的初值,可以控制PWM信号的周期和占空比。PWM信号的周期由定时器的溢出周期决定,而占空比则由比较值和初值的关系决定。
-
控制占空比:
- 要控制PWM信号的占空比,可以通过调整比较值来实现。占空比定义为高电平时间与周期的比值,通过改变比较值的大小,可以改变高电平的持续时间,从而改变占空比。
- 通过定时器中断服务函数中的逻辑,根据计数器的值和比较值的关系来控制输出信号的高低电平状态,实现PWM信号的输出。
-
应用领域:
- PWM信号广泛应用于电机控制、LED亮度调节、音频处理等领域,通过调节占空比可以实现对输出信号的精确控制。
二、思维导图
三、示例代码
基于定时器0的PWM控制功能,通过按键S7来调节LED L1的亮度。
sbit s7 = P3^0;
sbit L1 = P0^0;
unsigned char count = 0;
unsigned char pwm = 0;
unsigned char stat = 0;
//初始化定时器0
void Init_timer0()
{
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
TMOD = 0x01;
ET0 = 1;
EA = 1;
}
void service_timer0() interrupt 1
{
TH0 = (65536 - 100) / 256;
TL0 = (65536 - 100) % 256;
count++;
if(count == pwm)
{
L1 = 1;
}
else if (count >= 100)
{
L1 = 0;
count = 0;
}
}
void scan_key()
{
if(s7 == 0)
{
delay_key(100);
if(s7 == 0)
{
switch(stat)
{
case 0:
L1 = 0;
TR0 = 1;
pwm = 10;
stat = 1;
break;
case 1:
pwm = 50;
stat = 2;
break;
case 2:
pwm = 90;
stat = 3;
break;
case 3:
L1 = 1;
TR0 = 0;
stat = 0;
break;
}
while(s7 == 0);
}
}
}
void main()
{
P2 = (P2 & 0x1f) | 0x80;
L1 = 1;
Init_timer0()
while(1)
{
scan_key();
}
}
实现基于定时器0的PWM(脉宽调制)控制功能,通过按键S7来控制PWM的占空比。解释一下代码的主要功能和实现思路:
-
定义了一个位控制变量
sbit
,用于表示P3口的第0位引脚,对应按键S7;另外定义了一个位控制变量sbit
,用于表示P0口的第0位引脚,对应LED L1。同时定义了三个全局变量count
、pwm
和stat
,分别用于计数、存储PWM值和状态控制。 -
Init_timer0()
函数用于初始化定时器0,设置定时器初值为65536 - 100,工作模式为方式1(16位定时器),开启定时器0中断,并开启总中断。 -
service_timer0()
函数是定时器0的中断服务函数,每次定时器0溢出时会执行该函数。在函数中,重新设置定时器0的初值,然后根据计数值count
和PWM值pwm
控制LED L1的亮灭状态,实现PWM控制。 -
scan_key()
函数用于扫描按键S7的状态,并根据按键的按下情况和当前状态进行PWM占空比的调节。具体实现包括延时检测按键稳定按下、根据状态控制PWM值和LED L1的状态,并在按键释放后更新状态。 -
main()
函数中首先配置P2口的引脚,然后初始化定时器0,将LED L1初始设为亮,进入主循环中不断扫描按键状态并进行PWM控制。
四、特别注意!!!
如果把上述代码中所有的 TH0 = (65536 - 100) / 256; TL0 = (65536 - 100) % 256; 换成 TH0 = (0 - 100) / 256; TL0 = (0 - 100) % 256; 后LED L1就会闪烁。
当将定时器0的初值设置为(0 - 100)
时,会导致LED L1闪烁的原因在于定时器0的初值为负数,这可能会导致定时器计数出现异常情况,从而影响了PWM控制的稳定性。可能的原因:
-
负数初值问题:在定时器0的工作中,初值的设定是为了控制定时器的计数范围和溢出周期。当初值为负数时,由于定时器寄存器是无符号的,负数会被解释为一个很大的正数,这可能导致定时器计数溢出的情况出现异常。
-
定时器计数异常:当定时器0的初值为负数时,定时器的计数范围可能会受到影响,导致计数溢出的时机不再稳定。这可能会导致PWM控制的频率和占空比出现异常变化,从而导致LED L1的闪烁现象。
建议保持定时器0的初值为正数,以确保定时器的正常计数和稳定工作。