关键词:PWM脉宽调制;占空比;用PWM和一个按键控制LED亮度;小蜜蜂
一、知识点
1.占空比;高电平在一个周期中占的比例
2.PWM占空比的应用:直流电机调速;LED亮度调节;舵机角度调节等
二、实验
实验目的:
实验思路:
1.用定时器实现脉宽信号的输出
2.按键实现4种状态的循环,状态的2个改变量:工作模式、PWM占空比
所需部件:
1.L1位声明+HC573锁存器打开LED的Y4信道
2.定时器0初始化函数,计算初值(频率100HZ,周期为10ms,即10000us将1个周期分为100us*100次,100us决定计数初值,100次决定中断服务函数中的计数次数,以PWM_duty为分界,以count==100为清零节点,区分L1亮灭以实现占空比,从而让LED有不同亮度)
3.定时器中断服务函数,调节PWM占空比
4.扫描S7按键+状态位stat+Delay消抖
实验现象:
L1最初灭,按下S7,L1有10%的亮度;再按一次,L1有50%的亮度;再按一次,L1有90%的亮度;再按一次,L1熄灭,如此循环往复
完整代码:
#include <REGX52.H>
sbit L1=P0^0;
sbit S7=P3^0;
//如果是独立按键,J5跳帽接到2,3引脚
//如果是矩阵键盘,J5跳帽接到1,2引脚
void SelectHC573()
{
P2=(P2&0x1f)|0x80;
}
//*****************定时器相关
void Init_Timer0()
{
TMOD=0x01;
TH0=(65535-100)/256;
TL0=(65535-100)%256;
ET0=1;
EA=1;
TR0=0;//默认也是0,让定时器暂时不工作
}
unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-100)/256;
TL0=(65535-100)%256;
count++;
if(count==PWM_duty)
{
L1=1;
}
else if(count==100)
{
L1=0;
count=0;
}
}
//****************************
//*****************独立按键相关
void DelayK(unsigned int t)
{
while(t--);
}
unsigned char stat=0;
void ScanKeys()
{
if(S7==0)
{
DelayK(100);
if(S7==0)
{
switch(stat)
{
case 0:PWM_duty=10;L1=0;TR0=1;stat=1;break;
case 1:PWM_duty=50;stat=2;break;
case 2:PWM_duty=90;stat=3;break;
case 3:L1=1;TR0=1;stat=0;break;
}
while(S7==0);
}
}
}
//********************************
void main()
{
Init_Timer0();
SelectHC573();
L1=1;
while(1)
{
ScanKeys();
}
}
三、总结收获
1.J5跳帽随着独立键盘和矩阵键盘的不同而不同
//如果是独立按键,J5跳帽接到2,3引脚
//如果是矩阵键盘,J5跳帽接到1,2引脚
2.定时器0初始化函数,计算初值不同
①定时器处理脉冲占空比,将一个周期进行划分
②定时/计数器用作中断,是因为延时时间超出65.5ms,而进行分小凑大,eg.需延时500ms,将其分为50ms*10
3.占空比调节
思路:
因为题设L1亮度从0->...->90->0->...,所以不妨设一个周期里低电平在前,高电平在后。最初main函数里初始化L1=1;按下按键后,L1点亮,定时器开始计时,进行PWM脉宽调制(当count一到PWM_duty,L1灭,count一到100L1又亮,并清零count)
①简洁版:
unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-100)/256;
TL0=(65535-100)%256;
count++;
if(count==PWM_duty)
{
L1=1;
}
else if(count==100)
{
L1=0;
count=0;
}
}
②清晰版:
unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
TH0=(65535-100)/256;
TL0=(65535-100)%256;
count++;
if(count<=PWM_duty)
{
L1=0;
}
else if(count<100)
{
L1=1;
}
else
{
L1=0;
count=0;
{
}
③新思路(另一个实验)
清零和占空比分离,其中compare等效PWM_duty
void Timer0_Routine() interrupt 1
{
TL0 = 0x9C;
TH0 = 0xFF;
Counter++;
Counter%=100;//if(Counter>=100) Counter=0;同样的功能
if(Counter<Compare) LED=0;
else LED=1;
}
4.与PWM相关的按键控制中,需要调节:PWM_duty占空比设置、L1亮灭以及TR0(开始和结束时)、状态位
5.当只有一个按键调节多种状态时,可使用状态位进行切换(循环)
6.当出现按键不灵敏时,可在第二个if(S7==0)内加while(S7==0);空循环
unsigned char stat=0;
void ScanKeys()
{
if(S7==0)
{
DelayK(100);
if(S7==0)
{
switch(stat)
{
case 0:PWM_duty=10;L1=0;TR0=1;stat=1;break;
case 1:PWM_duty=50;stat=2;break;
case 2:PWM_duty=90;stat=3;break;
case 3:L1=1;TR0=1;stat=0;break;
}
while(S7==0);
}
}
}
7.main函数中while内和外的语句设置
void main()
{
Init_Timer0();
SelectHC573();
L1=1;
while(1)
{
ScanKeys();
}
}
四、联想拓展
1. 用4个键对应控制LED亮灭和直流电机转速
2.还可加上数码管显示
3.呼吸灯
详细参考:51单片机之LED呼吸灯&直流电机调速http://t.csdnimg.cn/3mGaZ
感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。