关键词:跟B站江科大自化协老师学;LED呼吸灯;直流电机调速;PWM
LED呼吸灯:
实验愿景:希望LED灯像呼吸一样由亮变暗,再由暗变亮,依次循环往复
尝试1:让LED灯亮
void main()
{
LED=0;
while(1)
{
}
}
实验现象:LED发出较亮的光
尝试2:让LED灯亮、暗,放到while(1)循环中不断执行
void main()
{
while(1)
{
LED=0;
LED=1;
}
}
实验现象:LED仍一直发出亮光
解释:LED亮灭速度很快,且在不断循环,肉眼看不出区别
改进目的:让人眼能分辨出LED的亮、灭
改进1:联想PWM占空比,可以通过让LED=0;和LED=1;的比例不同,实现亮、暗分明
代码如下:
#include <REGX52.H>
sbit LED=P2^0;
void main()
{
while(1)
{
LED=0;
LED=1;
LED=1;
LED=1;
LED=1;
LED=1;
LED=1;
LED=1;
}
}
实验现象:LED发出稳定亮光
反思:很多的LED=1;相当于让LED较长时间停留在灭的状态,相当于Delay,可能是Delay的次数不够,所以仍看不出明显变化,但重复复制粘贴LED=1;操作多且没有可重复操作性,所以前面可以加上自定义的Delay模块(不必精准的时间延时,只需一定次数的Delay),再在main中2个LED操作后分别加上Delay
改进2:
void Delay(unsigned int t)
{
while(t--);
}
void main()
{
while(1)
{
LED=0;
Delay(20);
LED=1;
Delay(100);
}
}
实验现象:通过调节2个Delay(分别简写D1、D2)中的值,发现LED亮的程度有变化,但肉眼看仍是稳定发光
D1(20);D2(100) 低高 ——>LED较暗
D1(100);D2(20) 高低 ——>LED较亮
D1(100);D2(100) 同 ——>LED较亮
D1(1000);D2(1000) 同——>LED较亮
猜想:如果想实现呼吸灯亮->暗->亮->...的现象,就需要Delay中的值有落差及变化,再结合PWM中占空比基本保持不变,就可以让2个Delay中的和等于1个常数,内部进行变化,但每次循环的总体是不变的(这里我有点解释不清,有懂的网友可以批评指正,谢谢!)
改进3:
void main()
{
unsigned char Time;
while(1)
{
for(Time=0;Time<100;Time++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
}
实现现象:LED仍稳定发光,肉眼看不出明显变化
猜想:每一个Time=i 相当于脉冲的一个周期,但这个周期只有1次,不能稳定存在一小段时间,而整个for循环又很快,所以视觉上1个Time的变化不明显,即亮暗比不明显,所以可以在for的内部,再添一个循环,循环变量为i
改进4:
void main()
{
unsigned char Time,i;
while(1)
{
for(Time=0;Time<100;Time++)
{
for(i=0;i<20;i++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
}
}
实现现象:实现了LED呼吸灯从暗到亮的可见过程,但下一个循环就是直接再从暗到亮,视觉上存在突变, 所以再来1个for循环,实现呼吸效果
最终版本:
void main()
{
unsigned char Time,i;
while(1)
{
for(Time=0;Time<100;Time++)
{
for(i=0;i<20;i++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
for(Time=100;Time>0;Time--)
{
for(i=0;i<20;i++)
{
LED=0;
Delay(Time);
LED=1;
Delay(100-Time);
}
}
}
}
实现现象:实现LED呼吸灯效果
收获提升:
1.学会LED不同明暗程度的调节(亮灭比不同,通过Delay中的数值进行调节)
2.学会让一个脉冲在一小段时间保持稳定存在,即再在内部添一个for循环,实现亮->灭的可见过程
3.运用联想PWM的相关知识
直流电机调速
实验愿景:希望依次按下按键,数码管上显示不同的档位0-3,LED灯随档位不同亮度发生变化。将LED灯换成Motor,使电机可按不同档位的速度运转
实验所需模块:定时器、数码管显示、按键控制
理论依据:
实验过程:
S1:定时器初始化以及定时器中断设置
其中,定时器的时间进行修改,原本是1ms,但太慢了调至100us,因为对于PWM驱动电机来说,在一定范围,频率越高越好,越快越稳定,但过快也没必要,一来是对资源比较占用,二来是可能会增加开关损耗,硬件电路允许,一般调至10k-20k(频率过低会出现抖动,1k左右可能会有蜂鸣器的叫声,不会有太大影响,但人耳能听见,可以再调高至人耳听不见的范围)——>main中每隔100us就进入中断函数一次
S2:根据PWM产生方法,设置计数器Counter和比较值Compare,让Counter在定时器中断中每次加1,直至100又清零重来,同时在中断中将Counter和Compare进行比较,从而分支LED输出时高电平还是低电平。
#include "Timer0.h"
#include "Key.h"
#include "Nixie.h"
sbit LED=P2^0;
unsigned char Counter,Compare;
unsigned char KeyNum,Speed=0;
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;
}
S3:while循环中实现按键控制、数码管显示
每按下按键1,档位Speed加1,0-3循环,并将Speed和Compare进行一一匹配,最后数码管静态显示档位
void main()
{
Timer0_Init();
//Compare=5;
while(1)
{
KeyNum=Key();
if(KeyNum==1)
{
Speed++;
Speed%=4;
if(Speed==0) Compare=0;
if(Speed==1) Compare=5;//低电平占5%,亮的占5%
if(Speed==2) Compare=50;
if(Speed==3) Compare=100;//将Speed和Compare一一对应
}
Nixie(1,Speed);
}
}
S4:在引脚定义和中断函数中,将LED换成Motor,并将其极性反转
最终代码:
#include <REGX52.H>
#include "Delay.h"
#include "Timer0.h"
#include "Key.h"
#include "Nixie.h"
sbit Motor=P1^0;
unsigned char Counter,Compare;
unsigned char KeyNum,Speed=0;
void main()
{
Timer0_Init();
//Compare=5;
while(1)
{
KeyNum=Key();
if(KeyNum==1)
{
Speed++;
Speed%=4;
if(Speed==0) Compare=0;
if(Speed==1) Compare=5;//低电平占5%,亮的占5%
if(Speed==2) Compare=50;
if(Speed==3) Compare=100;//将Speed和Compare一一对应
}
Nixie(1,Speed);
}
}
void Timer0_Routine() interrupt 1
{
TL0 = 0x9C;
TH0 = 0xFF;
Counter++;
Counter%=100;//if(Counter>=100) Counter=0;同样的功能
if(Counter<Compare) Motor=1;
else Motor=0;
//Motor和LED的极性是反的,LED低电平亮,Motor高电平运转,所以只需调节1和0,即可改变极性
}
收获提升:
1.实现按下按键,数码管上显示不同的档位0-3,LED灯随档位不同亮度发生变化。
2.Counter%=100;//if(Counter>=100) Counter=0;同样的功能
3.定时器中断中放入计数和判断功能,不占用main中内存,实现多个任务进行
特别感谢B站江科大自化协老师的教程,本文描述、整理如有错误,欢迎批评指正!