一、原理部分
PWM全称为脉冲宽度调制,在实际生活中很多地方都会见到这个技术的影子,例如灯的明暗调控,电机的转动速度还有幅度等等。在这些应用中我们需要使用不同的电压来达到目的,输出不同电压的方式有两种,一种是直接输出指定的电压值,还有一种就是PWM。
Ton为高电平持续时间
Toff为低电平持续时间
Ts一个周期时间
占空比=高电平持续时间/周期
简单来说一个io口只能输出固定的电压值如5V或者0V,我们要获取其他的电压值就可以通过占空比来控制io口的电压输出。假如现在需要一个3V的电压值,那么占空比就是60%,高电平持续时间占周期的60%,低电平占周期的40%。假设周期为10ms,那么就要让此io口输出高电平6ms的时间然后输出低电平4ms的时间,这样我们就输出了一个3V的电压。
在单片机中我们可以通过定时器来实现PWM的输出
具体步骤
一、开一个定时器
根据题目要求,假如题目要1khz的信号也就是周期为1ms,涉及到的占空比为10的整数倍时,就可以开100us的定时器,如果设计到的占空比不是10的整数倍时那么定时器就要开10us的。其他的以此类推。
二、定义一个变量用来当做周期使用
定义变量pwm_cycle变量,每次执行中断服务函数时这个变量自加,达到了题目要求的时间便清零。
三、定义一个控制pwm占空比的变量
定义变量pwm,pwm和占空比有关系,然后让pwm和pwm_cycle进行比较,pwm大的时候执行高电平,pwm小的时候执行低电平。这样就完成了一个可以自己控制占空比的信号输出。
二、代码部分
实验平台:CT107D
实验芯片:stc15f2k60s2
实验现象:呼吸灯
代码如下
#include<stc15f2k60s2.h>
bit flag_pwn;
unsigned char led_dat;
void Timer0Init() //[email protected]
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0x88;
TH0 = 0xFF;
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
}
void ShowLed(unsigned char led_dat)
{
P2 = P2&0x1f|0x80;
P0 = led_dat;
P2 = P2&0x1f;
}
void T0_time() interrupt 1
{
static unsigned int count = 0,n = 0,pwn = 0;
TL0 = 0x88;
TH0 = 0xFF;
if(++count >= 1000) //周期10ms
{
count = 0;
}
if(++n >= 100) //每隔1ms变化一次pwn
{
n = 0;
if(flag_pwn == 0)
{
pwn++; //PWN增加,灯泡由亮到暗
if(pwn == 1000)
{
flag_pwn = 1;
}
}
else if(flag_pwn == 1)
{
pwn--; //PWN减少,灯泡由暗到亮
if(pwn == 0)
{
flag_pwn = 0;
}
}
}
if(count > pwn) //亮
{
ShowLed(0x00);
}
else //暗
{
ShowLed(0xff);
}
}
void CloseFucker()
{
P2 = P2&0x1f|0xa0;
P0 = 0xaf;
P2 = P2&0x1f;
}
void main()
{
CloseFucker();
Timer0Init();
while(1)
{
;
}
}