找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4473|回复: 4
收起左侧

单片机智能照明系统原理图与程序设计 红外对管检测人数

  [复制链接]
ID:887876 发表于 2021-3-31 22:04 | 显示全部楼层 |阅读模式
        本设计是使用两个红外对管来检测是否有人进入办公室并进行人数统计,人数最多统计到二位数99人,并实时将人数显示到液晶屏LCD上,液晶屏同时显示实时日期/时间/星期;
使用4个LED灯模拟办公室的照明灯,在符合条件开启时,人数为0时灯不亮,人数小于10人亮一个灯,10-20人亮二个灯,20-30人亮三个灯,大于30人则全亮四个灯;
系统分自动/手动模式,可以通过按键切换模式,并有LED指示当前所在模式;
在自动模式下,可以设定定时时间段,在定时时间段内,当办公室有人(人数大于0)的情况下,如果光线暗弱则自动打开照明灯,照明灯点亮个数根据人数而定,不在定时时间段或者办公室无人的情况下,关闭所有照明灯;
另外在手动模式下,可以通过手动开关控制照明灯的亮灭,人数统计部分仍然生效;

制作出来的实物图如下:
07848188-cc6a-4b4f-bbfd-b9816f164fd3.jpg ffc0f9d3-f5a5-4982-9961-95ae33e22119.jpg d932de09-16e6-4cc6-8580-0e5eccf2c24a.jpg 0be0cd27-e0a9-4c62-8461-eb9d06a1fe67.jpg

电路原理图如下:
原理图.png
元件清单:
元器件    型号    数量
单片机最小系统    stc89c52    1
液晶显示    LCD1602    1
红外模块        2
时钟芯片    DS1302    1
光敏电阻模块        1
按钮        5
led        6
电阻    300欧姆    2
数据线        1

程序流程图:
51hei.png

单片机源程序如下:
/*******************说明:**************************
将实时时钟数据通过LCD1602显示
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
uchar dis_time_buf[16]={0};
//LCD1602引脚定义
//采用8位并行方式,DB0~DB7连接至LCDDATA0~LCDDATA7
sbit RS=P2^2;
sbit RW=P2^1;
sbit CS=P2^0;
#define LCDDATA P0
//时钟DS1302引脚定义
sbit RST=P2^4;
sbit IO=P2^5;
sbit SCK=P2^6;

sbit guangmin = P1^3;//光敏传感器

sbit led1 = P3^3;  //6个指示灯
sbit led2 = P3^2;
sbit led3 = P1^7;
sbit led4 = P1^0;
sbit led5 = P1^4;
sbit led6 = P1^5;

sbit K1=P3^5;        //按键
sbit K2=P3^7;
sbit K3=P3^4;
sbit K4=P3^6;
sbit K5=P1^6;

sbit Ir1=P1^1;        //red Ir
sbit Ir2=P1^2;



//DS1302地址定义
#define ds1302_sec_add                        0x80                //秒数据地址
#define ds1302_min_add                        0x82                //分数据地址
#define ds1302_hr_add                        0x84                //时数据地址
#define ds1302_date_add                        0x86                //日数据地址
#define ds1302_month_add                0x88                //月数据地址
#define ds1302_day_add                        0x8a                //星期数据地址
#define ds1302_year_add                        0x8c                //年数据地址
#define ds1302_control_add                0x8e                //控制数据地址
#define ds1302_charger_add                0x90                                          
#define ds1302_clkburst_add                0xbe

//flag
uchar flag_led1_sta = 0;
uchar flag_led2_sta = 0;
uchar flag_led3_sta = 0;
uchar flag_led4_sta = 0;
uchar flag_led5_sta = 0;

uchar flag_person_cont = 0;
uchar flag_person_cont_buf[3]=000;
uint flag_per_add = 0;
uint flag_per_cut = 0;
uint flag_mode_choose = 1;
uint flag_guang = 1;
//初始时间定义
uchar time_buf[8] = {0x20,0x21,0x02,0x01,0x11,0x47,0x55,0x02};//初始时间2020年11月17号11:47:55 week:2
/*************************延时函数*********************************/
//功能:延时1毫秒
//入口参数:x
//出口参数:无
//说明:当晶振为12M时,j<112;当晶振为11.0592M时,j<122
void Delay_xms(uint x)
{
  uint i,j;
  for(i=0;i<x;i++)
    for(j=0;j<112;j++);
}
//功能:12us延时
//STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍
void Delay_xus(uint t)                                          
{
  for(;t>0;t--)
   {
         _nop_();
   }
}
//控制LCD写时序
void LCD_en_write(void)      
{
   CS=1;   
    Delay_xus(20);
   CS=0;   
        Delay_xus(20);
}

//写指令函数
void Write_Instruction(uchar command)
{
  RS=0;
  RW=0;
  CS=1;
  LCDDATA=command;
  LCD_en_write();//写入指令数据
}

//写数据函数
void Write_Data(uchar Wdata)
{
  RS=1;
  RW=0;
  CS=1;
  LCDDATA=Wdata;
  LCD_en_write();//写入数据
}

//字符显示初始地址设置
void LCD_SET_XY(uchar X,uchar Y)
{
  uchar address;
  if(Y==0)
    address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80
  else
    address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0xC0
  Write_Instruction(address);//写指令,设置显示初始地址
}
//在第X行Y列开始显示Wdata所对应的单个字符
void LCD_write_char(uchar X,uchar Y,uchar Wdata)
{
  LCD_SET_XY(X,Y);//写地址
  Write_Data(Wdata);//写入当前字符并显示
}
//清屏函数
void LCD_clear(void)
{
  Write_Instruction(0x01);
  Delay_xms(5);
}
void led_init()
{
        led1=1;
        led2=1;
        led3=1;
        led4=1;
        led5=0;
        led6=1;
}
//显示屏初始化函数
void LCD_init(void)
{        
        Write_Instruction(0x38);                                //8bit interface,2line,5*7dots
        Delay_xms(5);
        Write_Instruction(0x38);        
        Delay_xms(5);
        Write_Instruction(0x38);        

        Write_Instruction(0x08);        //关显示,不显光标,光标不闪烁
        Write_Instruction(0x01);        //清屏
        Delay_xms(5);

        Write_Instruction(0x04);        //写一字符,整屏显示不移动
        //Write_Instruction(0x05);        //写一字符,整屏右移
        //Write_Instruction(0x06);        //写一字符,整屏显示不移动
        //Write_Instruction(0x07);        //写一字符,整屏左移
        Delay_xms(5);

        //Write_Instruction(0x0B);        //关闭显示(不显示字符,只有背光亮)
        Write_Instruction(0x0C);        //开显示,光标、闪烁都关闭
        //Write_Instruction(0x0D);        //开显示,不显示光标,但光标闪烁
        //Write_Instruction(0x0E);        //开显示,显示光标,但光标不闪烁
        //Write_Instruction(0x0F);        //开显示,光标、闪烁均显示
}
//DS1302初始化函数
void ds1302_init(void)
{
        RST=0;                        //RST脚置低
        SCK=0;                        //SCK脚置低
}
//向DS1302写入一字节数据
void ds1302_write_byte(uchar addr, uchar d)
{
        uchar i;
        RST=1;                                        //启动DS1302总线        
        //写入目标地址:addr
        addr = addr & 0xFE;   //最低位置零,寄存器0位为0时写,为1时读
        for (i = 0; i < 8; i ++) {
                if (addr & 0x01) {
                        IO=1;
                        }
                else {
                        IO=0;
                        }
                SCK=1;      //产生时钟
                SCK=0;
                addr = addr >> 1;
                }        
        //写入数据:d
        for (i = 0; i < 8; i ++) {
                if (d & 0x01) {
                        IO=1;
                        }
                else {
                        IO=0;
                        }
                SCK=1;    //产生时钟
                SCK=0;
                d = d >> 1;
                }
        RST=0;                //停止DS1302总线
}

//从DS1302读出一字节数据
uchar ds1302_read_byte(uchar addr) {

        uchar i,temp;        
        RST=1;                                        //启动DS1302总线
        //写入目标地址:addr
        addr = addr | 0x01;    //最低位置高,寄存器0位为0时写,为1时读
        for (i = 0; i < 8; i ++) {
                if (addr & 0x01) {
                        IO=1;
                        }
                else {
                        IO=0;
                        }
                SCK=1;
                SCK=0;
                addr = addr >> 1;
                }        
        //输出数据:temp
        for (i = 0; i < 8; i ++) {
                temp = temp >> 1;
                if (IO) {
                        temp |= 0x80;
                        }
                else {
                        temp &= 0x7F;
                        }
                SCK=1;
                SCK=0;
                }        
        RST=0;                                        //停止DS1302总线
        return temp;
}
//向DS302写入时钟数据
void ds1302_write_time(void)
{
        ds1302_write_byte(ds1302_control_add,0x00);                        //关闭写保护
        ds1302_write_byte(ds1302_sec_add,0x80);                                //暂停时钟
        ds1302_write_byte(ds1302_charger_add,0xa9);            //涓流充电
        ds1302_write_byte(ds1302_year_add,time_buf[1]);                //年
        ds1302_write_byte(ds1302_month_add,time_buf[2]);        //月
        ds1302_write_byte(ds1302_date_add,time_buf[3]);                //日
        ds1302_write_byte(ds1302_hr_add,time_buf[4]);                //时
        ds1302_write_byte(ds1302_min_add,time_buf[5]);                //分
        ds1302_write_byte(ds1302_sec_add,time_buf[6]);                //秒
        ds1302_write_byte(ds1302_day_add,time_buf[7]);                //周
        ds1302_write_byte(ds1302_control_add,0x80);                        //打开写保护     
}
//从DS302读出时钟数据
void ds1302_read_time(void)  
{
        time_buf[1]=ds1302_read_byte(ds1302_year_add);                //年
        time_buf[2]=ds1302_read_byte(ds1302_month_add);                //月
        time_buf[3]=ds1302_read_byte(ds1302_date_add);                //日
        time_buf[4]=ds1302_read_byte(ds1302_hr_add);                //时
        time_buf[5]=ds1302_read_byte(ds1302_min_add);                //分
        time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59
        time_buf[7]=ds1302_read_byte(ds1302_day_add);                //周         
}
void Display(void)
{

   LCD_write_char(1,0,dis_time_buf[0]+'0');

   LCD_write_char(2,0,dis_time_buf[1]+'0');

.......限于篇幅余下代码请下载附件..............

全部资料51hei下载地址:
智能照明系统.7z (2.67 MB, 下载次数: 118)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:969225 发表于 2021-11-5 20:45 来自手机 | 显示全部楼层
请问一下,会显示温度吗?
回复

使用道具 举报

ID:1064522 发表于 2023-3-2 15:59 | 显示全部楼层
能改成在开发板上运行的代码吗
回复

使用道具 举报

ID:1072897 发表于 2023-6-11 18:55 | 显示全部楼层
要是有人能根据楼主的程序做个仿真图就好了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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