基于单片机的PWM输出对Led的常见应用

  

目录

  

 <吐槽>

 <引言>

  <操作>

(1)让led以20%的亮度实现跑马效果(取消LedPwmTime=4的注释)。

(2)让led以12.5%的亮度来实现跑马效果,跑马时间间隔400ms.

(3)让led每隔0.5s亮度增加14%(1/7),实现持续3.5s的呼吸灯效果。

整个测试工程:

 <吐槽>

           继几天前做第九套蓝桥杯赛题彩灯控制器后,当时灯的亮度等级让我顿时不知道怎么操作,良久后才把它做出来。以“今天对明天而言永远都是早的一天,明天对于今天永远都是晚的一天” 的原则,趁早趁现在也就是在今天我把PWM琢磨了一遍,感觉还行。(然后第二天测试,老师认为PWM的亮度等级不应该是灯亮度等级太低在闪烁。我认为答案是定时的时间还是太长,在一个周期内,高电平的持续时间和低电平的持续时间并没有欺骗过人的眼睛,所以把pwm调低而灯在闪,所以要把pwm的一个周期的时间调得更低,经过测试7ms-15ms内操作pwm是可行的,再经过调试,发现达到了预期效果)。

所用的开发板是蓝桥杯单片机的一块基于stc15f2k60s2的stc开发板。

 <引言>

        对于PWM:简而言之:就是高电平的持续时间(脉冲宽度)占整个时钟周期的比例,对于单片机而言用定时是再好不过的了,比如要百分之20的亮度,定时器1ms产生一次中断,则在前20次中断的前5次中断让其为高电平,其余15次中断为低电平,又由于若是频繁的对led灯操作会电平不稳定,所以要在前5次中断中只对led灯操作一次,其余15次中断也只操作一次,怎么做?——设标志位。

在之前的彩灯控制器的里以一定亮度等级 进行流转跳跃显示。如下图

 而操作LED的PWM就改变了其亮度。

  <操作>

(1)让led以20%的亮度实现跑马效果(取消LedPwmTime=4的注释)。

/*******************
函数名称:LedTest1
功能:让led以20%的亮度实现跑马效果(取消LedPwmTime=4的注释)
作者:yzh
邮箱:2649483892@qq.com
***********************/


void LedTest1(){// 
	if(time<500){
			if(LedTime<=LedPwmTime&&PwmFlag==1){//由于PwmFlag进判断后被赋予不同值,
																					        以同20ms内的不同阶段只操作led一次
					Led(leds);
						PwmFlag=2;
			}
			else if(PwmFlag==2&&LedTime>LedPwmTime){
						Led(8);
						PwmFlag=3;
			}
			if(LedTime==20){
				LedTime=0;
				PwmFlag=1;
			}
		}
		if(time==500){//每500ms 
			PwmFlag=1;
			time=0;
			leds++;
			if(leds>7)leds=0;
		}
}

(2)让led以12.5%递增的亮度来实现跑马效果,跑马时间间隔400ms.

 /**********************
函数名称:LedTest2
功能:让led以12.5%递增的亮度来实现跑马效果,跑马时间间隔400ms
作者:yzh
邮箱:2649483892@qq.com
***********************/

void LedTest2(){
	
	if(time<400){
			 
				
			  if(LedTime<9){
					
						if(PwmFlag==1&&LedPwmTime>=LedTime){//28ms内的高电平时间
																								//(由于有个等号,所以尽管为LedPwmTime为0也会有微光。
							Led(leds);
							PwmFlag=2;
						}
						else if(PwmFlag=2&&LedTime>LedPwmTime){//剩余低电平时间
							
							Led(8);
							PwmFlag=3;
						}	
				}
				 if(LedTime==8){
						LedTime=0;
						 
						PwmFlag=1;
					}
	}
		
		if(time==400){
			PwmFlag=1;
			LedPwmTime+=1; 
			if(LedPwmTime==8)LedPwmTime=0;//0 1 2 3 4 5 6 7 8
			time=0;
			leds++;
			if(leds>7)leds=0;
		}
}

(3)让led每隔0.5s亮度增加14%(1/7),实现持续3.5s的呼吸灯效果。

 /**********************
函数名称:LedTest3
功能:让led0实现3.5s呼吸灯效果
作者:yzh
邮箱:2649483892@qq.com
***********************/
void LedTest3(){
	
	if(time<1000){
		if(PwmFlag==1&&LedPwmTime>LedTime){
			Led(leds);
			PwmFlag=2;
		}
		else if(PwmFlag==2&&LedPwmTime<LedTime){
			
			Led(8);//熄灭
			PwmFlag=3;
	
		}
		if(LedTime==7){
		LedTime=0;
			PwmFlag=1;
		}
		
	}
	if(time==500){
		PwmFlag=1;
		time=0;
		LedPwmTime+=1;//每0.5s亮度增1/7
		if(LedPwmTime==8)LedPwmTime=0;
	}
	
}

整个测试工程:

main.c

 

#include "sys.h"

u16 time=0;
u8 s=0;
bit ledflag=0;
//u8 LedPwmTime=4;
u8 LedPwmTime=0;
u16 LedTime=0;
u8 PwmFlag=0;
u8 leds=0;


/*******************
函数名称:LedTest1
功能:让led以20%的亮度实现跑马效果(取消LedPwmTime=4的注释)
作者:yzh
邮箱:2649483892@qq.com
***********************/


void LedTest1(){// 
	if(time<500){
			if(LedTime<=LedPwmTime&&PwmFlag==1){//由于PwmFlag进判断后被赋予不同值,
																					//所以同20ms内的不同阶段只操作led一次
					Led(leds);
						PwmFlag=2;
			}
			else if(PwmFlag==2&&LedTime>LedPwmTime){
						Led(8);
						PwmFlag=3;
			}
			if(LedTime==20){
				LedTime=0;
				PwmFlag=1;
			}
		}
		if(time==500){//每500ms 
			PwmFlag=1;
			time=0;
			leds++;
			if(leds>7)leds=0;
		}
}
/**********************
函数名称:LedTest2
功能:让led以12.5%递增的亮度来实现跑马效果,跑马时间间隔400ms
作者:yzh
邮箱:2649483892@qq.com
***********************/

void LedTest2(){
	
	if(time<400){
			 
				
			  if(LedTime<28){
					
						if(PwmFlag==1&&LedPwmTime>=LedTime){//28ms内的高电平时间
																								//(由于有个等号,所以尽管为LedPwmTime为0也会有微光。
							Led(leds);
							PwmFlag=2;
						}
						else if(PwmFlag=2&&LedTime>LedPwmTime){//剩余低电平时间
							
							Led(8);
							PwmFlag=3;
						}	
				}
				 if(LedTime==8){
						LedTime=0;
						 
						PwmFlag=1;
					}
	}
		
		if(time==400){
			PwmFlag=1;
			LedPwmTime+=1; 
			if(LedPwmTime==8)LedPwmTime=0;//0 1 2 3 4 5 6 7 8
			time=0;
			leds++;
			if(leds>7)leds=0;
		}
}
/**********************
函数名称:LedTest3
功能:让led0实现3.5s呼吸灯效果
作者:yzh
邮箱:2649483892@qq.com
***********************/
void LedTest3(){
	
	if(time<1000){
		if(PwmFlag==1&&LedPwmTime>LedTime){
			Led(leds);
			PwmFlag=2;
		}
		else if(PwmFlag==2&&LedPwmTime<LedTime){
			
			Led(8);//熄灭
			PwmFlag=3;
	
		}
		if(LedTime==7){
		LedTime=0;
			PwmFlag=1;
		}
		
	}
	if(time==500){
		PwmFlag=1;
		time=0;
		LedPwmTime+=1;//每0.5s亮度增1/7
		if(LedPwmTime==8)LedPwmTime=0;
	}
	
}

void main(){
	
 
	 sys_init();
	Timer0Init();
	 
	while(1){
		
		 LedTest3();//测试
 
	}
	
}

void time0() interrupt 1{
	
	time++;
	LedTime++;
  
	 
	
	
}

sys.c



#include "sys.h"
 

sbit buzz=P0^6;
sbit rely=P0^4;
void sys_init(){
	
	P0=0xff;
	P2=P2&0x1f|0x80;
	P0=0xff;
	P2=P2&0x1f;
	
	P0=0xff;
	P2=P2&0x1f|0xe0;
	P0=0xff;
	P2=P2&0x1f;
	
	P0=0;
	P2=P2&0x1f|0xc0;
	P0=0;
	P2=P2&0x1f;
	
	P0=0;
	P2=P2&0x1f|0xA0;
	buzz=0;
	rely=0;
	P2=P2&0x1f;
	
	
	
	
}

void Timer0Init(void)		//1000微秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}

void Led(u8 chi){//点亮任一led灯
	
	P0=0xff;
	P2=P2&0x1f|0x80;
	if(chi<=7)P0=~(1<<chi);
	else P0=0xff;
	P2=P2&0x1f;
	
	
}

sys.h


#ifndef __SYS_H_
#define __SYS_H_
#include  "stc15f2k60s2.h"
 
typedef unsigned char u8;
typedef unsigned int u16;
void Timer0Init(void);
void Led(u8 chi);
void sys_init();

#endif

posted @   昊月光华  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示