找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7456|回复: 12
打印 上一主题 下一主题
收起左侧

基于51单片机用1kHZPWM无极调光的问题

[复制链接]
跳转到指定楼层
楼主
ID:69634 发表于 2015-4-16 09:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序如下,可以变亮变暗调节,问题是刚开始二极管总有一点光亮,不是全暗。不知是为什么

#include <reg52.h>
#include"intrins.h"
sbit PWMOUT = P0^0;
sbit bianan  = P3^2;
sbit bianliang = P3^3;
unsigned char HighRH = 0;
unsigned char HighRL = 0;
unsigned char LowRH = 0;
unsigned char LowRL = 0;
unsigned int dc=921;        // 计算1ms定时器计数=11059200 / 12/1000=921         1ms内调节PWM占空比
void ConfigPWM( );
void ConfigTimer1( );
void zhongjian(unsigned int dc);

void main()
{
        EA = 1;     //开总中断
           zhongjian( dc);
        ConfigPWM( );  //配置并启动PWM
        ConfigTimer1( );    //每50ms增加或减少一次
        while (1);
}

  void ConfigTimer1( )
{
    TMOD &= 0x0F;   //清零T1的控制位
    TMOD |= 0x10;   //配置T1为模式1
    TH1 = 0x3c;     //加载T1重载值
    TL1 = 0x11;
    ET1 = 1;        //使能T1中断
    TR1 = 1;        //启动T1
}

void ConfigPWM(  )
{
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = HighRH;   //加载T0重载值
    TL0 = HighRL;
    ET0 = 1;        //使能T0中断
    TR0 = 1;        //启动T0
    PWMOUT = 1;     //输出高电平
}

void zhongjian(unsigned int dc)
{
    unsigned int high, low;
    high = dc;                  //计算高电平所需的计数值
    low  = 922 - high;          //计算低电平所需的计数值
    high = 65536 - high ;       //计算高电平的定时器重载值并补偿中断延时
    low  = 65536 - low  ;       //计算低电平的定时器重载值并补偿中断延时
    HighRH = (unsigned char)(high>>8); //高电平重载值拆分为高低字节
    HighRL = (unsigned char)high;
    LowRH  = (unsigned char)(low>>8);  //低电平重载值拆分为高低字节
    LowRL  = (unsigned char)low;
}

void InterruptTimer0() interrupt 1
{
    if (PWMOUT == 1)  //当前输出为高电平时,装载低电平值并输出低电平
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }
    else              //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}

void InterruptTimer1() interrupt 3                //每50ms增加或减少一次内调节PWM占空比
{   
  static unsigned int index = 921;
  TH1 = 0x3c;     //加载T1重载值
  TL1 = 0x11;
  if(bianan == 0)     {index++;  if(index>= 921)   {index = 921;} }
  if(bianliang == 0)  {index--;    if(index<= 2)       {index = 1;}}
  zhongjian(index);
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:77023 发表于 2015-4-16 10:56 | 只看该作者
沙发!
回复

使用道具 举报

板凳
ID:76800 发表于 2015-4-17 07:56 | 只看该作者
高的真够复杂的,没细看你的程序。low  = 922 - high;          //计算低电平所需的计数值,这里不是垫了点底么?

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:69634 发表于 2015-4-17 20:03 | 只看该作者
8055 发表于 2015-4-17 07:56
高的真够复杂的,没细看你的程序。low  = 922 - high;          //计算低电平所需的计数值,这里不是垫了点 ...

low=1,是必要的,定时器加载值不能为0啊,low=1,约千分之一,不足以有点点亮,仍为全暗。
回复

使用道具 举报

5#
ID:69634 发表于 2015-4-17 20:05 | 只看该作者
8055 发表于 2015-4-17 07:56
高的真够复杂的,没细看你的程序。low  = 922 - high;          //计算低电平所需的计数值,这里不是垫了点 ...

你有这方面的程序吗,或者建议
回复

使用道具 举报

6#
ID:76471 发表于 2015-4-17 20:14 | 只看该作者
在LED控制端加个103或104电容,我也试过,微亮去不掉

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

7#
ID:76800 发表于 2015-4-17 20:20 | 只看该作者
在输出最小时关掉端口呗,不过我几年前做这个实验好像没注意到这个微亮,好像一点点亮星儿都么有,我一开始写代码是就在最微弱时关掉了端口,输出一个固定电平,保证不亮。

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

8#
ID:76800 发表于 2015-4-17 20:21 | 只看该作者
888zhjzhj 发表于 2015-4-17 20:05
你有这方面的程序吗,或者建议

有啊,用带PWM的单片机最简单了

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

9#
ID:69634 发表于 2015-4-17 22:12 | 只看该作者
8055 发表于 2015-4-17 20:20
在输出最小时关掉端口呗,不过我几年前做这个实验好像没注意到这个微亮,好像一点点亮星儿都么有,我一开始 ...

这个思路也很好,我试着改一下。带PWM的单片机就不用了
回复

使用道具 举报

10#
ID:69634 发表于 2015-4-18 09:28 | 只看该作者
按8055老师的意思,把程序修改一下,最微弱时关掉定时器,能做到led全暗。会微亮也许跟led特征有关。程序如下,请8055老师斧正。
#include <reg52.h>
#include"intrins.h"
sbit PWMOUT = P0^0;
sbit bianan  = P3^2;
sbit bianliang = P3^3;
unsigned char HighRH = 0;
unsigned char HighRL = 0;
unsigned char LowRH = 0;
unsigned char LowRL = 0;
unsigned int dc=921;        // 计算1ms定时器计数=11059200 / 12/1000=921         1ms内调节PWM占空比
void ConfigPWM( );
void ConfigTimer1( );
void zhongjian(unsigned int dc);

void main()
{
    EA = 1;     //开总中断
           zhongjian( dc);
        ConfigPWM( );  //配置并启动PWM
        ConfigTimer1( );    //每50ms增加或减少一次
        while (1);
}

  void ConfigTimer1( )
{
    TMOD &= 0x0F;   //清零T1的控制位
    TMOD |= 0x10;   //配置T1为模式1
    TH1 = 0x3c;     //加载T1重载值
    TL1 = 0x11;
    ET1 = 1;        //使能T1中断
    TR1 = 1;        //启动T1
}

void ConfigPWM(  )
{
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0为模式1
    TH0 = HighRH;   //加载T0重载值
    TL0 = HighRL;
    ET0 = 1;        //使能T0中断
    // TR0 = 1;        //启动T0
    PWMOUT = 1;     //输出高电平
}

void zhongjian(unsigned int dc)
{
    unsigned int high, low;
    high = dc;                  //计算高电平所需的计数值
    low  = 922 - high;          //计算低电平所需的计数值
    high = 65536 - high ;       //计算高电平的定时器重载值并补偿中断延时
    low  = 65536 - low  ;       //计算低电平的定时器重载值并补偿中断延时
    HighRH = (unsigned char)(high>>8); //高电平重载值拆分为高低字节
    HighRL = (unsigned char)high;
    LowRH  = (unsigned char)(low>>8);  //低电平重载值拆分为高低字节
    LowRL  = (unsigned char)low;
}

void InterruptTimer0() interrupt 1
{
    if (PWMOUT == 1)  //当前输出为高电平时,装载低电平值并输出低电平
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }
    else              //当前输出为低电平时,装载高电平值并输出高电平
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}

void InterruptTimer1() interrupt 3                //每50ms增加或减少一次内调节PWM占空比
{   
  static unsigned int index = 921;
  TH1 = 0x3c;     //加载T1重载值
  TL1 = 0x11;
  if(bianan == 0)     {TR0 = 1; index++;  if(index>= 921)   {TR0 = 0; index = 921; } }
  if(bianliang == 0)  {TR0 = 1; index--;    if(index<= 2)       {TR0 = 0; index = 1;    } }
  zhongjian(index);
}
回复

使用道具 举报

11#
ID:76158 发表于 2015-4-26 21:05 | 只看该作者
楼主 这个程序可以做到全灭 100级分级调光  只是频率不够准确  但是LED可以全灭 全亮
调光不会闪  你参考一下
我也是别人指导我写的:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uint num,a;  //定义num a 为全局变量
sbit pwm=P1^0;        //定义p1 0端口为 PWM输出口
sbit up=P3^4;          //定义PWM 增加按键
sbit dn=P3^5;                //定义PWM 减少按键
void delayms(uint);   //延迟子函数声明
void keyscan();         //按键函数声明
void pwm_print();                  //PWM子函数
void init();                //初始化函数
void main()   //主函数入口
{
        init();     //调用初始化函数
        while(1)    //循环
        {
        delayms(5); //延时子函数
        keyscan();  //调用按键扫描函数
       
        }
}
void init()     //初始化函数
{
        TMOD=0X01;  //工作模式选择
        TH0=(65535-10)/256;   //高位装载初始值
        TL0=(65535-10)%256;   //低位装载初始值
        EA=1;                 //开总中断
        ET0=1;                //开定时器0中断
        TR0=1;                                 //启动定时器0
}
//**********************************************************
void  Time0() interrupt 1 //中断函数
{
        TH0=(65536-10)/256;   //装载初值
        TL0=(65536-10)%256;   //装载初值
        num++;                //10us中断一次 num 加1
        if(num==100)          //判断num 值  是否等于100 如果等于100 说明1ms时间到 也就相当于定时为1KHZ频率
        {
                num=0;            //将num值清零
        }
        pwm_print();           //调用PWM函数
}
//**********************************************************
void delayms(uint xms)     //延时函数
{
        while(xms--);

}
//***********************************************************
void keyscan()            //按键子函数
{
   
        if(up==0)              //判断按键up 是否被按下
        {
                delayms(10);       //软件消抖
                if(up==0)          //再次判断按键up是否按下 如果被按下 则执行{}中语句
                {
                        a++;            //a的值+1
                        if(a>100)       //如果A的值大于100 a=100 定上界  避免A值会一直增加上去  
                    a=100;
                       
                }       
        }

        if(dn==0)              //判断按键dn 是否被按下
        {
                delayms(10);       //软件消抖
                if(dn==0)          //再次判断按键dn是否按下 如果被按下 则执行{}中语句
                {
                }
                if(a<=0)           //判断a是否小于0
                        {
                                a=0;       //如果A的值小于0 a=0 定下界  避免A值会一直减少,导致a的值 会越下界
                        }       
                else
                {
                        a--;           //如果a≠0 ,则执行A--  如果A小于等于0 则A一直=0
                }
        }
       
}
//***********************************************************
void pwm_print()            //PWM发生函数
{
        if(num<a)               //判断A的值是否大于num的值  也是比较两个数  ,如果a的值大于num 。   那么num 小于a值那段时间内 pwm 为导通时间 就是占空比的时间
        {
                pwm=0;         
        }
                else
                {
                        pwm=1;
                }
}       

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

12#
ID:76158 发表于 2015-4-26 21:08 | 只看该作者
这个调光程序 我编译通过的。没有任何问题,只是写法可能不算严谨,但是好在可以用
期望大家多指点改进!

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

13#
ID:76158 发表于 2015-4-26 21:24 | 只看该作者
888zhjzhj 发表于 2015-4-18 09:28
按8055老师的意思,把程序修改一下,最微弱时关掉定时器,能做到led全暗。会微亮也许跟led特征有关。程序如 ...

我调了一下你这个调光 越下界了  就是如果一直按着减少占空比的键的时候会回到最大状态。就是按着减小按键
LED慢慢变小 然后变得最大 这样子

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表