基于51单片机的带显示温度亮度多功能智能台灯软件源码

#include <reg52.h>             //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义    变量范围0~255
#define uint  unsigned int     //无符号整型 宏定义    变量范围0~65535
#include "eeprom52.h"
#include "intrins.h"
#include "ds1302.h"
#include "lcd1602.h"
#include "ultrasonic_wave.h"//超声波头函数

bit flag_200ms ;
bit flag_100ms ;
bit flag_beep1_en;//定时模式开启标志
bit flag_beep2_en;
bit flag_beep3_en;

sbit k1=P1^4;     //时间设置切换
sbit k2=P1^5;     //光标移动
sbit k3=P1^6;     //加
sbit k4=P1^7;     //减
sbit k5=P2^7;     //手动/自动

sbit ADC_CS = P3^5;     //ADC0832引脚定义
sbit ADC_CLK = P3^6;     
sbit ADC_DAT = P3^7;
     
sbit LED = P2^6;     //自动模式指示灯

sbit dq   = P2^1;      //18b20 IO口的定义
      
sbit Module = P2^2;      // 人体红外感应引脚定义
sbit Beep = P2^0;      // 蜂鸣器引脚定义
 
sbit Lamp = P1^3;      // 照明灯定义
uchar gCount=0;          // 全局计数变量
uchar gIndex;          // 亮度变量,0是最暗,9是最亮,一共10档
uint  gTime=0;                                // 计时变量,用于计时多久没检测到有人

uint temperature ;    //温度变量

uchar menu_1;          //时间/定时模式切换
uchar menu_2;          //调整时间
uchar ret;              //AD采集结果

uchar key_time,flag_value;      //用做连加的中间变量
bit key_500ms  ;


/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
    SectorErase(0x2000);
    byte_write(0x2000, fen1);
    byte_write(0x2001, shi1);
    byte_write(0x2002, open1);
    byte_write(0x2058, a_a);    
}

/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
    fen1  = byte_read(0x2000);
    shi1  = byte_read(0x2001);
    open1 = byte_read(0x2002);
    a_a   = byte_read(0x2058);
}

/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
    read_eeprom();        //先读
    if(a_a != 1)        //新的单片机初始单片机内问eeprom
    {
        fen1  = 3;
        shi1  = 8;
        open1  = 1;
        a_a = 1;
        write_eeprom();       //保存数据
    }    
}

/*********************************************************/
// ADC0832的时钟脉冲
/*********************************************************/
void WavePlus()
{
    _nop_();
    ADC_CLK = 1;
    _nop_();
    ADC_CLK = 0;
}

/*********************************************************/
// 获取指定通道的A/D转换结果
/*********************************************************/
uchar Get_ADC0832()

    uchar i;
    uchar dat1=0;
    uchar dat2=0;
    
    ADC_CLK = 0;                // 电平初始化
    ADC_DAT = 1;
    _nop_();
    ADC_CS = 0;
    WavePlus();                    // 起始信号 
    ADC_DAT = 1;
    WavePlus();                    // 通道选择的第一位
    ADC_DAT = 0;      
    WavePlus();                    // 通道选择的第二位
    ADC_DAT = 1;
    
    for(i=0;i<8;i++)        // 第一次读取
    {
        dat1<<=1;
        WavePlus();
        if(ADC_DAT)
            dat1=dat1|0x01;
        else
            dat1=dat1|0x00;
    }
    
    for(i=0;i<8;i++)        // 第二次读取
    {
        dat2>>= 1;
        if(ADC_DAT)
            dat2=dat2|0x80;
        else
            dat2=dat2|0x00;
        WavePlus();
    }
    
    _nop_();                        // 结束此次传输
    ADC_DAT = 1;
    ADC_CLK = 1;
    ADC_CS  = 1;   

    if(dat1==dat2)            // 返回采集结果
        return dat1;
    else
        return 0;

/*********************************************************/
// 自动控制
/*********************************************************/
void AutoControl(uchar num)
{
    if(num<30)                                        // 最亮
        gIndex=9;
    else if((num>35)&&(num<45))                    
        gIndex=8;
    else if((num>50)&&(num<60))                
        gIndex=7;
    else if((num>65)&&(num<75))
        gIndex=6;
    else if((num>80)&&(num<90))
        gIndex=5;
    else if((num>95)&&(num<105))
        gIndex=4;
    else if((num>110)&&(num<120))
        gIndex=3;
    else if((num>125)&&(num<135))
        gIndex=2;
    else if((num>140)&&(num<150))
        gIndex=1;
    else if(num>155)                                 // 最暗
        gIndex=0;
}


/***********************18b20初始化函数*****************************/
void init_18b20()
{
    bit q;
    dq = 1;                //把总线拿高
    delay_uint(1);        //15us
    dq = 0;                //给复位脉冲
    delay_uint(80);        //750us
    dq = 1;                //把总线拿高 等待
    delay_uint(10);        //110us
    q = dq;                //读取18b20初始化信号
    delay_uint(20);        //200us
    dq = 1;                //把总线拿高 释放总线
}

/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
    uchar i;
    for(i=0;i<8;i++)
    {                     //写数据是低位开始
        dq = 0;             //把总线拿低写时间隙开始 
        dq = dat & 0x01; //向18b20总线写数据了
        delay_uint(5);     // 60us
        dq = 1;             //释放总线
        dat >>= 1;
    }    
}

/*************读取18b20内的数据***************/
uchar read_18b20()
{
    uchar i,value;
    for(i=0;i<8;i++)
    {
        dq = 0;             //把总线拿低读时间隙开始 
        value >>= 1;     //读数据是低位开始
        dq = 1;             //释放总线
        if(dq == 1)         //开始读写数据 
            value |= 0x80;
        delay_uint(5);     //60us    读一个时间隙最少要保持60us的时间
    }
    return value;         //返回数据
}

/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
    uint value;              
    uchar low;               //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
    init_18b20();           //初始化18b20
    write_18b20(0xcc);       //跳过64位ROM
    write_18b20(0x44);       //启动一次温度转换命令
    delay_uint(50);           //500us

    init_18b20();           //初始化18b20
    
    write_18b20(0xcc);       //跳过64位ROM
    write_18b20(0xbe);       //发出读取暂存器命令
    
    EA = 0;
    low = read_18b20();       //读温度低字节
    value = read_18b20();  //读温度高字节
    EA = 1;
    value <<= 8;           //把温度的高位左移8位
    value |= low;           //把读出的温度低位放到value的低八位中
    value *= 0.625;           //转换到温度值 小数
    return value;           //返回读出的温度 带小数
}

/******************1ms 延时函数*******************/
void delay_1ms(uint q)
{
    uint i,j;
    for(i=0;i<q;i++)
        for(j=0;j<120;j++);
}

///******************写星期函数*******************/
//void write_week(uchar hang,uchar add,uchar week)//写星期函数
//{
//    if(hang==1)   
//        write_com(0x80+add);
//    else
//        write_com(0x80+0x40+add);      
//    switch(week)
//    {
//        case 1:write_data('M');//星期数为1时,显示
//               write_data('O');
//               write_data('N');
//               break;
//       
//        case 2:write_data('T');//星期数据为2时显示
//               write_data('U');
//               write_data('E');
//               break;
//        
//        case 3:write_data('W');//星期数据为3时显示
//               write_data('E');
//               write_data('D');
//               break;
//        
//        case 4:write_data('T');//星期数据为4是显示
//               write_data('H');
//               write_data('U');
//               break;
//        
//        case 5:write_data('F');//星期数据为5时显示
//               write_data('R');
//               write_data('I');
//               break;
//        
//        case 6:write_data('S');//星期数据为6时显示
//               write_data('T');
//               write_data('A');
//               break;
//        
//        case 7:write_data('S');//星期数据为7时显示
//               write_data('U');
//               write_data('N');
//               break;
//    }
//}

/******************写亮度函数*******************/
void write_light(uchar hang,uchar add,uchar light)//写星期函数
{
    if(hang==1)   
        write_com(0x80+add);
    else
        write_com(0x80+0x40+add);      
    
    write_data(0x30+light);//显示亮度等级
        
}

/*************时钟显示***************/
void init_1602_ds1302()
{
    write_sfm2_ds1302(1,1,shi);           //显示时
    write_sfm2_ds1302(1,4,fen);           //显示分
    write_sfm2_ds1302(1,7,miao);       //显示秒
    write_light(2,13,gIndex);            //显示亮度
  //write_sfm1(1,14,week);               //显示星期
    if(temperature<900)
    {
        write_sfm3_18B20(1,11,temperature);       //显示温度
    }
    write_sfm2_ds1302(2,2,nian);   //显示年
    write_sfm2_ds1302(2,5,yue);       //显示月    
    write_sfm2_ds1302(2,8,ri);       //显示日             
}                                       

/************定时器0初始化程序*********/
void init_time0()      
{
    EA   = 1;           //开总中断
    TMOD = TMOD|0x01;      //定时器0、工作方式1 
    TH0  = 252;          //给定时器0的TH0装初值
    TL0  = 24;          //给定时器0的TL0装初值
    ET0  = 1;          //开定时器0中断 
    TR0  = 1;          //允许定时器0定时
}

/********************独立按键程序*****************/
uchar key_can;     //按键值

void key()     //独立按键
{
    static uchar key_new;
    key_can = 20;                   //按键值还原
    if(k1==0)          //检测按键K1是否按下
    {    
        delay_1ms(10);   //消除抖动 一般大约10ms
        if(k1==0)     //再次判断按键是否按下
        {
               key_new = 0;
            key_can = 1;                  
        }
        while(!k1);     //检测按键是否松开
    }
    else
    key_new = 1;    
    
    if(k2==0)          //检测按键K1是否按下
    {    
        delay_1ms(10);   //消除抖动 一般大约10ms
        if(k2==0)     //再次判断按键是否按下
        {
               key_new = 0;
            key_can = 2;
        }
        while(!k2);     //检测按键是否松开
    }
    else
    key_new = 1;
    
    if(k3==0)          //检测按键K1是否按下
    {    
        delay_1ms(10);   //消除抖动 一般大约10ms
        if(k3==0)     //再次判断按键是否按下
        {
               key_new = 0;
            key_can = 3;      
        }
        while(!k3);     //检测按键是否松开
    }
    else
    key_new = 1;    
    
    if(k4==0)          //检测按键K1是否按下
    {    
        delay_1ms(10);   //消除抖动 一般大约10ms
        if(k4==0)     //再次判断按键是否按下
        {
               key_new = 0;
            key_can = 4;      
        }
        while(!k4);     //检测按键是否松开
    }
    else
    key_new = 1;
    
    if(k5==0)          //检测按键K5是否按下
    {    
        delay_1ms(10);   //消除抖动 一般大约10ms
        if(k5==0)     //再次判断按键是否按下
        {
               LED=~LED;                    // 切换LED灯状态      
        }
        while(!k5);     //检测按键是否松开
    }            
        
}

/**********************设置函数************************/
void key_with()
{
    if(key_can == 1)    
    {
        menu_1++;
        if(menu_1 == 1)      
        {
            menu_2 = 1;
            write_string(1,0,"    :  :    W:  ");            
            write_string(2,0," 20  -  -       ");    
        }
        
        if(menu_1 > 1)   
        {
            menu_1 = 0;
            write_guanbiao(1,2,0);    
            init_1602_dis_csf();      //初始化液晶显示        
        }
    }
    if(key_can == 2)    
    {
        flag_200ms = 1;
        if(menu_1 == 1)         
        {
            menu_2 ++;
            if(menu_2 > 7)
                menu_2 = 1;
        }
    }
    if(menu_1 == 1)
    {
        if(menu_2 == 1)          
        {
            if(key_can == 3)    
            {
                shi+=0x01;
                if((shi & 0x0f) >= 0x0a)
                    shi = (shi & 0xf0) + 0x10;       ///***shi & 0xf0低四位清零,(shi & 0xf0) + 0x10向高位进1(高四位加1)***///                if(shi >= 0x24)
                    shi = 0;
            }        
            if(key_can == 4)    
            {
                if(shi == 0x00)      
                    shi = 0x24;
                if((shi & 0x0f) == 0x00)  
                    shi = (shi | 0x0a) - 0x10;     ///***如果个位为0,高四位减1***///
                shi -- ; 
            }                      
        }
        if(menu_2 == 2)          
        {
            if(key_can == 3)    
            {
                fen+=0x01;
                if((fen & 0x0f) >= 0x0a)
                    fen = (fen & 0xf0) + 0x10;
                if(fen >= 0x60)
                    fen = 0;
            }        
            if(key_can == 4)      
            {
                if(fen == 0x00)
                    fen = 0x5a;
                if((fen & 0x0f) == 0x00)
                    fen = (fen | 0x0a) - 0x10;
                fen -- ;
            }    
        }
        if(menu_2 == 3)        
        {
            if(key_can == 3)    
            {
                miao+=0x01;
                if((miao & 0x0f) >= 0x0a)
                    miao = (miao & 0xf0) + 0x10;
                if(miao >= 0x60)
                    miao = 0;
            }    
            if(key_can == 4)      
            {
                if(miao == 0x00)
                    miao = 0x5a;
                if((miao & 0x0f) == 0x00)
                    miao = (miao | 0x0a) - 0x10;
                miao -- ;            
            }
        }
        if(menu_2 == 4)          
        {
            if(key_can == 3)    
            {
                week+=0x01;
                if((week & 0x0f) >= 0x0a)
                    week = (week & 0xf0) + 0x10;
                if(week >= 0x08)
                    week = 1;
            }        
            if(key_can == 4)          
            {
                if(week == 0x01)
                    week = 0x08;
                if((week & 0x0f) == 0x00)
                    week = (week | 0x0a) - 0x10;
                week -- ;
            }    
        }
        if(menu_2 == 5)         
        {
            if(key_can == 3)    
            {
                nian+=0x01;
                if((nian & 0x0f) >= 0x0a)
                    nian = (nian & 0xf0) + 0x10;
                if(nian >= 0x9a)
                    nian = 1;
            }        
            if(key_can == 4)    
            {
                if(nian == 0x01)
                    nian = 0x9a;
                if((nian & 0x0f) == 0x00)
                    nian = (nian | 0x0a) - 0x10;
                nian -- ;        
            }    
        }
        if(menu_2 == 6)          
        {
            if(key_can == 3)    
            {
                yue+=0x01;
                if((yue & 0x0f) >= 0x0a)
                    yue = (yue & 0xf0) + 0x10;
                if(yue >= 0x13)
                    yue = 1;
            }        
            if(key_can == 4)      
            {
                if(yue == 0x01)
                    yue = 0x13;
                if((yue & 0x0f) == 0x00)
                    yue = (yue | 0x0a) - 0x10;
                yue -- ;                    
            }    
        }
        if(menu_2 == 7)          
        {
            if(key_can == 3)    
            {
            ri+=0x01;
            if((ri & 0x0f) >= 0x0a)
                ri = (ri & 0xf0) + 0x10;
            if(ri >= 0x32)
                ri = 0;            
            }        
            if(key_can == 4)          
            {
                if(ri == 0x01)
                    ri = 0x32;
                if((ri & 0x0f) == 0x00)
                    ri = (ri | 0x0a) - 0x10;
                ri -- ;            
            }    
        }
        write_sfm2_ds1302(1,2,shi);       
        write_sfm2_ds1302(1,5,fen);       
        write_sfm2_ds1302(1,8,miao);      
        write_sfm1(1,14,week);                      
        write_sfm2_ds1302(2,3,nian);       
        write_sfm2_ds1302(2,6,yue);       
        write_sfm2_ds1302(2,9,ri);       
  ///***write_sfm3_18B20(2,12,temperature);       
        switch(menu_2)       // 光标显示
        {
            case 1:  write_guanbiao(1,2,1);  break;
            case 2:  write_guanbiao(1,5,1);  break;
            case 3:  write_guanbiao(1,8,1);  break;
            case 4:  write_guanbiao(1,14,1);  break;
            case 5:  write_guanbiao(2,3,1);  break;
            case 6:  write_guanbiao(2,6,1);  break;
            case 7:  write_guanbiao(2,9,1);  break;
        }
        write_time();       //把时间写进去
    }                
                
}

/*****************主函数********************/
void main()
{    
    P0 = P1 = P2 = P3 = 0xff;    //单片机IO口初始化为1
    
    LED=0;                        // 指示灯点亮(自动模式指示灯)
    ret=Get_ADC0832();            // 获取AD采集结果(环境光照强度)
    AutoControl(ret);            // 上电先进行一次自动亮度控制    
    AutoControl(ret+7);

    delay_1ms(150);
    Init_ultrasonic_wave();      //超声波定时器初始化
    init_time0();         //初始化定时器
    init_ds1302();         //ds1302初始化
    init_1602();         //lcd1602初始化
    init_1602_dis_csf(); //lcd1602初始化显示
    init_eeprom();       //开始初始化保存的数据
    temperature = read_temp();    //先读出温度的值
    delay_1ms(650);
    temperature = read_temp();    //先读出温度的值
    while(1)
    {

        key();        //按键程序
        if(key_can < 10)
        {
            key_with();    
            if(menu_1 == 0)
            {
                if(LED==1)
                {
                    if(key_can == 2)  //左移键
                    {
                        gIndex=1;
                    }
    
                    if(key_can == 3)  //加键
                    {
                       gIndex=5;                
                    }
    
                    if(key_can == 4)  //减键
                    {
                        gIndex=9;
                    }
                }                                           
            }
        }
            
        /* 亮度控制 */
        if(LED==0)                            // 如果LED是亮的                    
        {
            if(gTime<60000)
            {
                ret=Get_ADC0832();            // 获取AD采集结果(环境光照强度)
                AutoControl(ret);            // 进行自动控制    
            }
        }
        delay_1ms(100);

        /*检测是否有人*/
        if(Module==1)
        {
            gTime=0;                                // 检测到有人,则把60秒计时清零
        }
        if(gTime>60000)                                // 如果gTime的值超过了60000
        {
            gTime=60000;                            // 则把gTime的值重新赋值为60000,避免过大溢出
            gIndex=0;                                // 如果1分钟检测不到有人,则把台灯熄灭
        }


        if(flag_200ms == 1)
        {                         
            flag_200ms = 0;
            if(menu_1 == 0)
            {
                read_time();          //读时间
                temperature = read_temp();    //先读出温度的值
                init_1602_ds1302();   //显示时钟
            }
        }
        delay_1ms(1);

           StartModule();//启动超声波
        while(!RX)      //当RX为零时等待
        TR1=1;          //开启计数
        while(RX);      //当RX为1计数并等待
        TR1=0;          //关闭计数
        delay_1ms(20);
                
        Conut(); //计算距离
           //距离小于30
        if(L_ < 30)
        {                                 
             Beep=~Beep;
             delay_1ms(1);    
             Beep=~Beep;
             delay_1ms(1);
             delay_1ms(100);    
        }
        else
        Beep=1;

    }
}

/**************定时器0中断程序*****************/
void time0() interrupt 1
{                                                                      
    static uchar value;
    TH0 = 252;
    TL0 = 24;       //1ms
    value ++;       
    if((value % 100) == 0)     //100ms  
    {
        flag_100ms = 1;
    }
    if(value >= 200)     //200ms
    {
        value = 0;
        flag_200ms = 1;
    }

    gTime++;                    // 每1毫秒,gTime变量加1
    gCount++;                    // 每1毫秒,gCount变量加1    
    if(gCount==10)                // 如果gCount加到10了
    {
        gCount=0;                        // 则将gCount清零,进入新一轮的计数
        if(gIndex!=0)                // 如果说台灯不是最暗的(熄灭)
        {
            Lamp=0;                        // 则把台灯点亮
        }
    }
    if(gCount==gIndex)        // 如果gCount计数到和gIndex一样了
    {
        if(gIndex!=9)                // 如果说台灯不是最亮的
        {
            Lamp=1;                        // 则把台灯熄灭
        }
    }

}

void time1() interrupt 3          //T1中断用来计数器溢出,超过测距范围
{
    TH1=0;
    TL1=0;
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GJZGRB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值