1. 如果MCU有Timer和PWM,可以实现无闪烁调光
InitPWM; //PWM输出驱动LED
InitTimer;
for (Duty=0;Duty<=DUTY_MAX;Duty++){
SetPWM(Duty);
SetTimer(STEP_TIME);
}
总共由最暗到最亮的时间是DUTY_MAX*STEP_TIME
2. 如果没有Timer和PWM,将以上SetPWM和SetTimer用循环语句代替,通过IO口驱动LED,由于软件DELAY与实际时间的误差以及中断响应的不确定性,会造成在最暗和最亮附近出现闪烁现象。 学习了。 mark mark 很反感碰到什么问题就用单片机做,单片机也是数电的一种,用555定时器做就行了!! mark 学习了 我这里有个用一个定时器控制的8位流水灯,效果就是像外面广告装饰的滴水或者流星的那种效果。基于飞思卡尔XS128编写。
/*
** ===================================================================
** Event :TI1_OnInterrupt (module Events)
**
** From bean :TI1
** Description :
** When a timer interrupt occurs this event is called (only
** when the bean is enabled - <Enable> and the events are
** enabled - <EnableEvent>). This event is enabled only if a
** <interrupt service/event> is enabled.
** Parameters: None
** Returns : Nothing
** ===================================================================
*/
void TI1_OnInterrupt(void)
{
/* Write your code here ... */
count++;
////////////////////////////////
if(count==256)
{
data=move;
move=(move>>1)|(move<<7);
count=0;
}
////////////////////////////////
Byte1_PutVal(data);//这个函数是往IO口送8位值
//以下是实现LED点亮时间控制,实现由亮到灭的效果
if(count%2==0) {Byte1_PutVal((data<<1)|(data>>7));} //0xfd
if(count%4==0) {Byte1_PutVal((data<<2)|(data>>6));} //0xfb
if(count%8==0) {Byte1_PutVal((data<<3)|(data>>5));} //0xf7
if(count%16==0) {Byte1_PutVal((data<<4)|(data>>4));} //0xef
if(count%32==0) {Byte1_PutVal((data<<5)|(data>>3));} //0xdf
if(count%64==0) {Byte1_PutVal((data<<6)|(data>>2));} //0xbf
if(count%128==0){Byte1_PutVal((data<<7)|(data>>1));} //0x7f
////////////////////////////////
} mark~~ 能用手动调节亮暗变化吗?或是在指定时间内从亮变灭.是什么样的思路? mark MARK 关注关注 标记学习 图示: T不变,T1变化,这样就能实现LED渐亮渐灭
|<-------T--->|
|<---T1-->|
___________ ___________
_____| |____| |______ mark 学习了 亮暗时间怎么控制呢? 这个主要是看你的灯数的多少。实现的方法可以是纯软件或软硬结合的。灯数少30只灯左右使用纯软件方法即可实现。可以形成光影流水的效果。灯多了,必须要软硬结合了。基本的解决方法是产生占空比可调的脉冲串,不论哪种方法,可控制的灯数量多,要管理的参数巨大。基本的思想可分为线性值和权值法(我自己的称呼)两种。两种方法都是对时间的权值做出定义,前者为1,后者为8 4 2 1 .
如果希望计算占空比的频率,可以粗略算一下:人眼的视觉暂留特性为40毫秒,因此,led灯最少,一秒要亮-黑 25次,这样就不会闪,大家想一下荧光灯,它是50次。如果led从最暗到最亮,分成16个档,那么它的占空比最低是1:15,最亮时是15:1,所以这个灯如果持续工作在最暗状态,它的工作频率就是1/40毫秒/16=1/2.5毫秒=400hz。也就是说,当一个定时器每2.5毫秒触发一次时,可以维持led产生16级不同强度的光看上去不闪烁。
实际应用中一般要在100级以上,否则最暗一级发出来的光仍然是比较亮的。我用M8内部振荡字ff做过22个100级的光影流水灯,效果还是可以的。
-----------------------------------------------------------
这很值得学习!
控制不好,LED最暗处容易闪烁,一般可调节输出占空比、频率、和LED亮度(固定了)三个参数摆脱闪烁,最终我们需要调节的就是占空比和脉冲频率。
灯光控制很多采用DMX信号,256级,如果按照上面计算公式,频率就要6K多HZ. mark mark 回复【楼主位】WANGMING
-----------------------------------------------------------------------
//发光二极管纯软件PWM示例程序
//编译环境 ICCAVR V7.16A
//系统时钟1MHZ,内部RC
//日期:2011.07.22
//***********************************************************************
// 包含文件
//***********************************************************************
#include <string.h>
#include <stdio.h>
#include <iom48v.h>
#include <macros.h> //Atmega128头文件
#define uchar unsigned char
#define ulong unsigned long
#define uintunsigned int
/*------------------------------------------------------------------------------
函数说明
------------------------------------------------------------------------------*/
//---------------------延时程序说明------------------------
void delay_1us(void); //1us延时函数
void delay_10us(void); //10us延时函数
void delay_1ms(void); //1ms延时函数
void delay_nus(unsigned int n); //n us延时函数
void delay_nms(unsigned int n); //n ms延时函数
//---------MCU端口初始化程序说明---------
void port_init(void);
//==============================================================================
//*************************************************************************
// 系统初始化子程序
//*************************************************************************
void port_init(void)
{
DDRB=0xff; //设置PB口为输出
PORTB=0x00;
DDRC=0x3f; //设置PB口为输出
PORTC=0xc0;
DDRD=0xff; //设置PB口为输出
PORTD=0x00;
}
/**************延时程序****************/
/*1M内部RC时钟*/
//1us
void delay_1us(void) //1us延时函数
{
_NOP();
}
//10us
void delay_10us(void) //10us延时函数
{
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
delay_1us();
}
//nus
void delay_nus(uint n) //N us延时函数
{
uint i=0;
for (i=0;i<n;i++)
delay_1us();
}
//1ms
void delay_1ms(void) //1ms延时函数
{
unsigned char i=13;
while(i--)
{
delay_10us();
}
}
//nms
void delay_nms(uint n) //N us延时函数
{
while(n--)
{
delay_1ms();
}
}
//*************************************************************************
// 主程序
//*************************************************************************
void main(void)
{ uint i,j,k;
uchar temp=0x01;
port_init();
while(1)
{
for(i=0;i<1000;)
{//for(j=0;j<1;j++)
{
for(k=0;k<3;k++)
{PORTB=temp;PORTD=0xff;
delay_nus(i+1);
PORTB=0;PORTD=0;
delay_nus(1000-i);
}
}
if(i<200) i+=8;
else if((i>=200)&&(i<500)) i+=50;
else i+=120;
}
for(i=0;i<1000;)
{//for(j=0;j<1;j++)
{
for(k=0;k<3;k++)
{PORTB=temp;PORTD=0xff;
delay_nus(1000-i);
PORTB=0;PORTD=0;
delay_nus(i+1);
}
}
if(i<200) i+=8;
else if((i>=200)&&(i<500)) i+=50;
else i+=120;
}
temp<<=1;
if(temp==0) temp=1;
}
} 用PWM调节占空比 mark mark mark pwm #include < reg51.h >
#include < intrins.h >
sbitK1 =P1^4 ; //增加键
sbitK2 =P1^5 ; //减少键
sbitBEEP =P3^7 ; //蜂鸣器
unsigned char PWM=0x7f ; //赋初值
void Beep();
void delayms(unsigned char ms);
void delay(unsigned char t);
void main()
{
P1=0xff;
TMOD=0x21 ;
TH0=0xfc ; //1ms延时常数
TL0=0x66 ; //频率调节
TH1=PWM ; //脉宽调节
TL1=0 ;
EA=1;
ET0=1;
ET1=1;
TR0=1 ;
while(1)
{
do{
if(PWM!=0xff)
{PWM++ ;delayms(10);}
else Beep() ;
}
while(K1==0);
do{
if(PWM!=0x02)
{PWM-- ;delayms(10);}
else Beep() ;
}
while(K2==0);
}
}
/*********************************************************/
// 定时器0中断服务程序.
/*********************************************************/
void timer0() interrupt 1
{
TR1=0 ;
TH0=0xfc ;
TL0=0x66 ;
TH1=PWM ;
TR1=1 ;
P0=0x00 ; //启动输出
}
/*********************************************************/
// 定时器1中断服务程序
/*********************************************************/
void timer1() interrupt 3
{
TR1=0 ;
P0=0xff ; //结束输出
}
/*********************************************************/
//蜂鸣器子程序
/*********************************************************/
void Beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(100);
BEEP=!BEEP; //Beep取反
}
BEEP=1; //关闭蜂鸣器
delayms(100);
}
/*********************************************************/
// 延时子程序
/*********************************************************/
void delay(unsigned char t)
{
while(t--) ;
}
/*********************************************************/
// 延时子程序
/*********************************************************/
void delayms(unsigned char ms)
{
unsigned char i ;
while(ms--)
{
for(i = 0 ; i < 120 ; i++) ;
}
} 学习! mark! 向高手们学习 光影流水灯,标记 强人
呵呵
我一周前开始学习,以后少不了要向大家请教!
页:
1
[2]