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

本文介绍了如何使用STC15F2K60S2单片机通过PWM技术实现LED亮度调节和跑马灯效果。作者通过设置定时器中断,控制高电平和低电平的比例来调整LED亮度,并通过标志位确保每个PWM周期内LED的操作次数。此外,还展示了实现12.5%递增亮度的跑马灯效果和呼吸灯效果的代码示例。
摘要由CSDN通过智能技术生成

  

目录

  

 <吐槽>

 <引言>

  <操作>

(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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值