上期我们学习了定时器的相关内容,这次我们来学习PWM脉宽调制
什么是PWM
PWM(Pulse Width Modulation)简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在测量、通信、工控等方面。
PWM的频率
在一秒内,电平从高电平变化为低电平,再从低电平变化为高电平的次数就是PWM的频率
频率的单位为HZ(赫兹),计算公式:f = 1/T
PWM的周期
在一个PWM波形中,电压经过一个完整的高电平和低电平所用的时间就是一个周期,
计算公式:T = 1/f
举个栗子:
占空比
在一个周期内,高电平的时间占整个周期占比称为占空比,计算公式: Duty = 高电平时间 /T
利用PWM控制LED的亮度
任务要求
控制原理
- 通过设置不同的占空比,控制LED在一个周期内亮起的时间,实现对LED亮度的控制,
- 定义一个LED工作模式mode,通过按键按下改变mode,再通过mode去调节占空比,实现对LED亮度的控制。
- f = 100HZ,那么T = 1/100 = 0.01s = 10ms 我们可以控制定时器每0.1s触发一次,那么触发一百次就是一个周期,假设现在占空比为50%,那么电平就应该在第50次触发定时器中断时由高电平跳变为低电平
不同mode对应的占空比如下:
完全熄灭 mode = 0 Duty = 0%
10%亮度 mode= 1 Duty = 10%
50%亮度 mode = 2 Duty = 50%
90%亮度 mode = 3 Duty = 90%
代码实现
1.main.c
#include <STC15F2K60S2.H>
sbit Key7 = P3^0; //位定义按键S7
unsigned char Timer0_Duty = 0; //定义占空比
unsigned char LED_MOde = 0; //定义LED工作模式
unsigned char Timer0_Count = 0;
//延时函数,延时xms
void Delayxms(unsigned int x) //@12.000MHz
{
unsigned char i, j,k;
for(k=0;k<x;k++)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
//LED控制函数,控制L1的亮起和熄灭
void LED_Control(unsigned int Flag)
{
if(Flag)
{
P2 = 0x1F | 0x80;
P0 = 0xFE;
}
else
{
P2 = 0x1F | 0x80;
P0 = 0xFF;
}
}
//按键扫描函数,判断S7是否按下
unsigned int Key_Scan(void)
{
if(Key7==0)
{
Delayxms(20);
if(Key7==0)
{
LED_MOde >= 3 ? LED_MOde=0 : LED_MOde++;
while(!Key7)
{
}
return 1;
}
}
return 0;
}
//占空比改变函数,根据LED的工作模式,控制占空比
void Duty_Control(unsigned Mode)
{
if(Mode == 0)
{
Timer0_Duty = 0;
}
switch(Mode)
{
case 1: Timer0_Duty = 10;
break;
case 2: Timer0_Duty = 50;
break;
case 3: Timer0_Duty = 90;
break;
}
}
//定时器0初始化函数,0.1ms触发一次中断
void Timero_Init(void)
{
TMOD = TMOD | 0x00; //设置工作模式为16位自动重装载
TL0 = 0x9B; //设置定时器溢出时间为0.1ms
TH0 = 0xFF;
ET0 = 1; //开启定时器0中断允许
EA =1; //开启中断总允许
TR0 = 1; //开启定时器0
}
void main()
{
Timero_Init(); //定时器0初始化
while(1)
{
if(Key_Scan()); //判断S7是否按下
Duty_Control(LED_MOde); //通过LED工作模式改变占空比
}
}
//定时器0中断服务函数
void Timer0_Interrupt() interrupt 1
{
Timer0_Count>100 ? Timer0_Count=0 : Timer0_Count++ ;
if(Timer0_Count <= Timer0_Duty)
{
LED_Control(1);
}
else
{
LED_Control(0);
}
}