打印

LED漸變控制

[复制链接]
4534|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
LHMLHM|  楼主 | 2007-7-20 19:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
ayb_ice| | 2007-7-20 19:15 | 只看该作者

有定时器中断就可以...

使用特权

评论回复
板凳
computer00| | 2007-7-20 19:23 | 只看该作者

PWM控制

使用特权

评论回复
地板
gyt| | 2007-7-20 19:55 | 只看该作者

2051绝对可以

使用特权

评论回复
5
conwh| | 2007-7-20 20:25 | 只看该作者

都对

使用特权

评论回复
6
LHMLHM|  楼主 | 2007-7-21 08:19 | 只看该作者

都知可以

是否有現成的程序,貢獻一下,不勝感激.

THANKS!

使用特权

评论回复
7
jdwang| | 2007-7-21 10:01 | 只看该作者

建议用PCA9532控制灯的亮度

建议用PCA9532控制灯的亮度,9532是I2C接口,16位LED调光器电路,各路可分别单独控制亮度,很好用,不过价钱较贵,前几年是30多元一片,我们曾在电气自动化杂志发表过**介绍PCA9532。

使用特权

评论回复
8
lsqdesign| | 2007-7-21 10:09 | 只看该作者

调PWM的占空比

用IO脚输出PWM方波。用定时器调PWM的占空比。

使用特权

评论回复
9
古道热肠| | 2007-7-21 11:19 | 只看该作者

这个现成的,是Hot大叔的,给你好好调试一下,发现BUG来灌

返回 侃单片机 精华区 
零耗时低频宽脉冲软PWM信号控制Keil C51演示程序 
 hotpower 发表于 11/17/2004 6:08:46 PM 侃单片机 ←返回版面    

/*----------------------------------------------------------------
       零耗时低频宽脉冲软PWM信号控制Keil C51演示程序
C51文件PwmDemo.c 
HotPower@126.com    作于2004.11.17与大雁塔村队部
在uV3中对PWM信号进行"实时仿真"效果逼真。
-----------------------------------------------------------------*/
#include <REGX52.h>
//#include <stdio.h>
#include <intrins.h>

/*------------------------------------------------
        AT89S5X SFR定义(REGX52.h中未定义)
--------------------------------------------------*/
sfr   AUXR    = 0x8e;
sfr   WDTRST  = 0xa6;
sfr16 TIMEER2 = 0xcc;
sfr16 RCAP2   = 0xca;

/*-----------------------------------------------
        PWM管脚定义
------------------------------------------------*/
sbit  PWM     = P1^0;//可以为任意IO管脚

typedef struct Systemstruct{//系统数据结构
  unsigned int PwmCount;//700~2300uS
  unsigned int RamTest;//内部ram自检变量
/*--------------------------------------------------------------------
注意将STARTUP.A51中的IDATALEN改写为0,RamTest才能完成MCU掉电自检。
IDATALEN        EQU     00H     ; the length of IDATA memory in bytes.
---------------------------------------------------------------------*/
}SystemData;//系统数据结构(此时只是定义了一个新的数据类型SystemData)

//全局变量定义(全局结构)
SystemData SystemBuffers;//申请系统数据结构缓冲区

#define T2_20mS -20000 //MCU主频12MHz,12分频,T2_20mS=20MS

/*----------------------------------------------------------------------
        系统函数
-----------------------------------------------------------------------*/
void MainInit(void);//系统初始化
void ClrWdt(void);//喂狗
void SystemInit(void);//系统初始化
void SystemSetup(void);//系统设置
void SystemIoInit(void);//系统接口初始化
void UserSetup(void);//用户运行环境设置
void TimeInit(void);//定时器定时参数初始化


/*-----------------------------------------
         主程序初始化
-------------------------------------------*/
void MainInit(void)//系统初始化
{
  SystemIoInit();//系统接口初始化
  ClrWdt();//清除看门狗计数器
  if (SystemBuffers.RamTest != 0x55aa) {//内存测试
    SystemInit();//系统上电初始化
  }
  SystemSetup();//系统运行环境设置
  UserSetup();//用户运行环境设置
}

void SystemInit(void)//系统初始化
{
  SystemBuffers.RamTest = 0x55aa;//内存初始化
}

void SystemSetup(void)//系统设置
{
  AUXR = 0x01;//关闭EMI
  TimeInit();//定时器定时参数初始化
  IP = 0x20;//中断优先级ET2
}

void UserSetup(void)//用户运行环境设置
{
/*--------------------------------------------
  在此加入用户运行环境设置代码
----------------------------------------------*/
}

void SystemIoInit(void)
{
  IE = 0x00;//关闭中断
  P0 = 0xff;//P0口初始化
  P1 = 0xfe;//P1口初始化,PWM=0
  P2 = 0xff;//P2口初始化
  P3 = 0xff;//P3口初始化
}

void TimeInit()
{
/*----------------------------------
      定时器0定时参数设置
----------------------------------*/
  TL0 = 0;
  TH0 = 0;
//  TR0 = 1;//启动定时器0
/*----------------------------------
      定时器1定时参数设置
----------------------------------*/
  TL1 = 0xfd;
  TH1 = 0xfd;
  PCON = 0x00;//SMOD_=0,GF0_=0;//清除疯狗标志
//  TR1 = 1;//启动定时器1
/*----------------------------------
      定时器2定时参数设置
----------------------------------*/
  TIMEER2 = T2_20mS;//上电20mS后PWM开始工作
  PWM = 0;//上电后无PWM信号
  SystemBuffers.PwmCount = 700;//首次PWM脉宽为700uS
  RCAP2   = 0 - SystemBuffers.PwmCount;//首次PWM脉宽为700uS
  TR2     = 1;//启动定时器2(上电后20mS内PWM信号为低电平)
/*----------------------------------
      定时器参数设置
----------------------------------*/
  TMOD    = 0x22;//定时方式(8位自动装载)
}




/*---------------------------------------------------------------------
         外部INT0中断服务程序(PWM+10uS)
----------------------------------------------------------------------*/
void int0proc() interrupt IE0_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount <= 2290) //PWM高电平脉宽上界-10
    SystemBuffers.PwmCount += 10;//递增未越界
  else 
    SystemBuffers.PwmCount = 700;//递增越界翻到下界
}

/*---------------------------------------------------------------------
         定时器T0中断服务程序
----------------------------------------------------------------------*/
void t0proc() interrupt TF0_VECTOR using 2
{
  if (PCON & GF0_) {//中断是从主循环内跳入的才能喂狗
    ClrWdt();//清除看门狗计数器
    PCON &= ~GF0_;//清除疯狗标志 
  }
}

/*---------------------------------------------------------------------
         外部INT1中断服务程序(PWM-10uS)
----------------------------------------------------------------------*/
void int1proc() interrupt IE1_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount > 700) //PWM高电平脉宽下界
    SystemBuffers.PwmCount -= 10;//递减未越界
  else 
    SystemBuffers.PwmCount = 2300;//递减越界翻到上界
}


/*------------------------------------
         定时器T1中断服务程序
------------------------------------*/

void t1proc() interrupt TF1_VECTOR using 2
{
/*--------------------------------------------
  在此加入用户代码(与串口复用T1)
----------------------------------------------*/
}

/*------------------------------------
         串口SIO中断服务程序
------------------------------------*/

void sioproc() interrupt SIO_VECTOR using 2
{
  if (RI) {//接收中断
    RI = 0;
/*--------------------------------------------
  在此加入用户串口接收代码
----------------------------------------------*/
  }
  if (TI) {//发送中断
    TI = 0;
/*--------------------------------------------
  在此加入用户串口发送代码
----------------------------------------------*/
  }
}

/*-----------------------------------------------------------------------------
         定时器T2中断服务程序(20mS)
零耗时低频宽脉冲软PWM信号控制演示程序

软件工作环境及要求:
MCU主频12MHz,软PWM控制IO模拟。PWM脉宽调节10uS
PWM频率20mS=50Hz, PWM高电平脉宽700uS~2300uS,PWM低电平脉宽19300uS~17700uS

"零耗时"并非不耗时。只是没用软件空等待等恼人的函数。
其主要原理是利用低频宽脉冲软PWM信号的“低速”而T2的16位定时器自动装载功能。
T2在每个PWM周期内中断两次。即PWM高电平和PWM低电平各中断1次。
合理应用RCAP2的预装载功能并进行简单的减法运算而轻松完成任务的要求。

本演示程序只需经过简单的修改,即可实现变PWM频率等功能。
为演示方便未用宏定义,否则会更通用。但必须在“低频宽脉冲”的相对条件下。

本文纯属虚构,若有雷同请原谅!
------------------------------------------------------------------------------*/

void t2proc() interrupt TF2_VECTOR using 1
{
static unsigned int PwmCount;//系统内部PWM高电平PwmCount(用户无法访问)
/*-----------------------------------------------------------------------------
  PWM软件IO模拟,任务中未加关PWM控制,可以再加限定/PWM电平信号翻转标志。
  即:SystemBuffers.PwmCount=0为关闭PWM电平信号输出(PWM=0)
  注意SystemBuffers.PwmCount不能过小.
  本软PWM控制模块与Windows的原则相同
  --不主张用户直接开展PWM管脚,而是控制SystemBuffers.PwmCount变量。
例:
-------------------------------------------------------------------------------
  if (SystemBuffers.PwmCount == 0) {//关断PWM信号。(不主张用户直接开展PWM管脚)
    PWM = 0;//关闭PWM电平信号输出,并强迫执行RCAP2 = 0 - PwmCount;RCAP2=0(最宽)
    PwmCount = 0;//PWM高电平脉宽为0,PWM低电平脉宽为T2的最大定时时间。
  }
  else
------------------------------------------------------------------------------*/
  PWM = ~PWM;//PWM电平信号翻转

  TF2 = 0;//清除标志
  if (PWM) {//在PWM高电平时至少有700uS的预算时间
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
    PwmCount = SystemBuffers.PwmCount;//只在PWM上升沿处取用户PWM高电平PwmCount 
/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM高电平PwmCount装入到TIMEER2中
   故此时应该计算PWM低电平20mS-PwmCount到RCAP2中
------------------------------------------------------------------------------*/
//    RCAP2 = 0 - (20000 - PwmCount);//注意定时器是+1器
    RCAP2 = PwmCount - 20000;//(优化计算)注意定时器是+1器(RCAP2首次为-19300)
  }
  else {//在PWM低电平时至少有17700uS的预算时间
/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM低电平20mS-PwmCount装入到TIMEER2中
   故此时应该计算PWM高电平PwmCount到RCAP2中
-------------------------------------------------------------------------------*/
    RCAP2 = 0 - PwmCount;//注意定时器是+1器(RCAP2首次为-700)
  }
/*------------------------------------------------------------------------------
   PWM高电平RCAP2定时时间 + PWM低电平RCAP2定时时间 = PWM周期20mS
-------------------------------------------------------------------------------*/
}


void ClrWdt(void)//喂狗
{
  WDTRST = 0x1e;//89s52内狗
  WDTRST = 0xe1;//89s52内狗
}


void main(void)
{
  MainInit();//系统初始化
  while (1) {//主循环
    IE   |= 0xbf;//保证全部中断可靠
    TCON |= 0x55;//保证定时器打开,外部中断为边沿触发.
    PCON |= GF0_ | IDL_;//喂疯狗(GF0_=1)并进入空闲状态(IDL_=1)
    _nop_();
    _nop_();
  }
}





签名:


●█〓██▄▄▄▄▄▄ ●●●●●●→ 
▄▅██████▅▄▃▂ 灌水入坛,传播非典! 
██████████████ 
◥⊙▲⊙▲⊙▲⊙▲⊙▲⊙▲◤ 

使用特权

评论回复
10
zhaNgxu198| | 2007-7-21 11:21 | 只看该作者

我也想要呀

我现在用220V的交流电,有几十个灯,要求七彩同步.
我只知道需要采工频,不然时间长了就不同步了.硬件电路都已经做好了.
我想问下这个工频到底怎么个采**如何加到程序里面实现同步的,会把采工频做到外部中断里吗?万分感谢.只要说说怎么做就行了,代码我自己写,谢谢

使用特权

评论回复
11
zhaNgxu198| | 2007-7-21 11:36 | 只看该作者

古道热肠

有七彩的不?我发现你这里只有单色的??有的话希望你能发份给我,zhangxu198@tom.com,或者告诉我工频是怎样采的?加到程序哪个地方?

使用特权

评论回复
12
古道热肠| | 2007-7-21 11:47 | 只看该作者

楼上的这个东东没见过实物

  您说电路已做好了,如果贴出来的话,大家也许会帮你想想办法。七彩同步在电视里舞台上见过,应该是控制直流电灯**吧。

使用特权

评论回复
13
LHMLHM|  楼主 | 2007-7-23 10:42 | 只看该作者

程序找到一個

程序網上找到一個,如下,但燈在漸變的過程中有時會閃一下,不是每個周期會閃:
請高手看看,謝啦!
#include<at89x52.h>
#define flash1 P2_1
#define flash2 P1_0
#define flash3 P1_2

#define a 2        //漸變速度控制;
#define b 300
#define c 256

#define uchar unsigned char
#define uint unsigned int 
uchar percent,light,times;//percent,times:占空比控制;light:控制漸亮漸滅
uint i;

void delay();//延時函數

void pulse() interrupt 1 using 0 //計時器0中斷服務程式

    TH0 = -b/c;
    TL0 = -b%c;
    if (times++ == percent)
    {
        flash1=0;
        flash2=0;
        flash3=1;
    }
    else if (times == 100)
    {
        times = 0;
        flash1=1;
        flash2=1;
        flash3=0;
    }
}
void main()
{
    times = 100;
    percent = 100;
    light = 1;
    TMOD = 0x01;     //計時器0工作在方式1;
    TH0 = -b/c; //賦初值,不同的TH0和TL0值對應不同的調製頻率,而上面已說過,調製頻率不能太高,否則
    TL0 = -b%c; //會達不到調節效果。
    EA = 1;
    ET0 = 1;
    TR0 = 1;
    do
    {
        delay(); 
        if (percent <100 && light==1)
        percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電
        else light = 0;
        if (percent >0 && light ==0)
        percent = percent-a; //壓,從而實現漸亮漸滅調節
        else light = 1; //改變percent的增減幅度可以控制速度的快慢
    }
    while(1);
}
void delay()
{
    for(i = 0;i<6576;i++);

使用特权

评论回复
14
conwh| | 2007-7-23 10:53 | 只看该作者

LS的可能是PWM的频率太低,在占空比小的情况可能出现闪动

使用特权

评论回复
15
zhangxu198| | 2007-7-31 10:27 | 只看该作者

我在上面改了一下,这样能实现七彩渐变吗?

#include<at89x52.h>
#define red P1_2
#define green P1_3
#define blue P1_4

#define a 1        //漸變速度控制;
#define b 300
#define c 256

#define uchar unsigned char
#define uint unsigned int 
uchar percent,light,times;//percent,times:占空比控制;light:控制漸亮漸滅
uint i,j,k,p1;

bit  flag;
void red_light();
void yellow_light();
void green_light();
void cyan_light();
void blue_light();
void purple_light();
void white_light();
void white_red();
void delay();//延時函數
void change();
void delay500ms();

void pulse() interrupt 1 using 0 //計時器0中斷服務程式

    TH0 = -b/c;
    TL0 = -b%c;
    if(times++<100)
       {flag=1;}
    else{
         flag=0;}
}
void main()

    times = 0;
    percent = 100;
    light = 1;
    flag=1;
    TMOD = 0x01;     //計時器0工作在方式1;
    TH0 = -b/c; //賦初值,不同的TH0和TL0值對應不同的調製頻率,而上面已說過,調製頻率不能太高,否則
    TL0 = -b%c; //會達不到調節效果。
    EA = 1;
    ET0 = 1;
    TR0 = 1;
    red_light();
    do
    {
       yellow_light();
       green_light();
       cyan_light();
       blue_light();
       purple_light();
       white_light();
       white_red();
    }
    while(1);
}


void red_light()
{
   if(flag==1)
        {
             red=1;
             green=0;
             blue=0;
             delay(); 
//LED渐渐点亮
             percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=0;
             green=0;
             blue=0;
             delay(); 
           }
     else{
          red=1;
          green=0;
          blue=0;
          delay500ms();
          times=0;
         }
}

void yellow_light()
{
   if(flag==1)
        {
             red=1;
             green=1;
             blue=0;
             delay(); 
//LED渐渐点亮
             percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=1;
             green=0;
             blue=0;
             delay(); 
           }
     else{
          red=1;
          green=1;
          blue=0;
          delay500ms();
          times=0;
         }

}

void green_light()
{
   if(flag==1)
        {
             red=1;
             green=1;
             blue=0;
             delay(); 
//LED渐渐灭
             percent = percent-a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=0;
             green=1;
             blue=0;
             delay(); 
           }
     else{
          red=0;
          green=1;
          blue=0;
          delay500ms();
          times=0;
         }
}

void cyan_light()
{
   if(flag==1)
        {
             red=0;
             green=1;
             blue=1;
             delay(); 
//LED渐渐点亮
             percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=0;
             green=1;
             blue=0;
             delay(); 
           }
     else{
          red=0;
          green=1;
          blue=1;
          delay500ms();
          times=0;
         }
}

void blue_light()
{
   if(flag==1)
        {
             red=0;
             green=1;
             blue=1;
             delay(); 
//LED渐渐点亮
             percent = percent-a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=0;
             green=1;
             blue=1;
             delay(); 
           }
     else{
          red=0;
          green=0;
          blue=1;
          delay500ms();
          times=0;
         }
}

void purple_light()
{
   if(flag==1)
        {
             red=1;
             green=0;
             blue=1;
             delay(); 
//LED渐渐点亮
             percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=0;
             green=0;
             blue=1;
             delay(); 
           }
     else{
          red=1;
          green=0;
          blue=1;
          delay500ms();
          times=0;
         }
}

void white_light()
{
   if(flag==1)
        {
             red=1;
             green=1;
             blue=1;
             delay(); 
//LED渐渐点亮
             percent = percent+a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=1;
             green=0;
             blue=1;
             delay(); 
           }
     else{
          red=1;
          green=1;
          blue=1;
          delay500ms();
          times=0;
         }
}


void white_red()
{
   if(flag==1)
        {
             red=1;
             green=1;
             blue=1;
             delay(); 
//LED渐渐灭
             percent = percent-a;//調節percent值可以改變占空比,通過不同的占空比,輸出不同的電

             red=1;
             green=0;
             blue=0;
             delay(); 
           }
     else{
             red=1;
             green=0;
             blue=0;
          delay500ms();
          times=0;
         }
}



void delay()
{
    for(i = 0;i<6576;i++);
}  

void delay500ms(void)

       {

       unsigned char i,j,k;

        for(i=15;i>0;i--)

        for(j=202;j>0;j--)

        for(k=81;k>0;k--);

       }

烧进去试了一下,实现不了七彩渐变,请帮忙看看为什么不行呀?

使用特权

评论回复
16
小乐213| | 2013-11-8 23:13 | 只看该作者
大神们,能不能提供一个基于DMX512控制单片机七彩渐变的程序呢?PCB已打样,求求大神们了。

使用特权

评论回复
17
riddlecn| | 2013-11-9 12:30 | 只看该作者
不错  应该还是要用PWM来实现的
建议求助贴原理图,大家还能帮你想想办法

使用特权

评论回复
18
小乐213| | 2013-11-12 00:05 | 只看该作者
能不能帮我想个办法啊。。。我的DMX512啊。大神们求热心啊。。我快疯了。

使用特权

评论回复
19
dragon20100708| | 2013-11-12 11:18 | 只看该作者
mark

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

25

帖子

0

粉丝