1. 功能介绍
这是基于 STC89C52 单片机设计的灯光控制系统,实现对室内灯光的控制,采集光敏传感器,红外线热释电传感器,声音传感器,光照照度传感器等数据进行处理,完成室内灯光的智能控制。
支持的功能与设计要求:
1、室内光控系统的传感部分主要是对环境数据、室内光强、室内噪声、是否有物体接近等进行采集,需要使用单片机模块、人体红外传感器、光敏传感器和噪音传感器;
2、整个室内灯光控制系统的应用主要集中在灯具的控制上,主要是控制灯具的光强、开闭。系统采用智能传感器技术和单片机技术,有利于系统的智能化;
3、系统包括三个主要流程。感应器感应到人体点亮灯,感应器感应到光强改变灯的亮度,感应器感应到一定音量点亮灯。在控制系统中,各传感器设备和控制单元最终以指定方式与主控制器相连,实现各单元之间的通讯和控制;
声音传感器作用是采集当前环境的声音,传递给单片机进行处理,通过预设的阀值进行分析,判断是否有人过来,实现声控开灯的功能;
热释电人体采集传感器可以通过红外功能探测周围是否有发热的物体,正常人体会发出红外光的,当传感器检测到周围指定范围内有人活动时,会通过高点电平的方式通知单片机,单片机根据预先设置的逻辑完成开灯操作。
光敏传感器用于采集周边环境的光强度,通过光强区分白天黑夜,如果光的环境较暗,就需要开灯,如果较亮就需要关灯,单片机得到光强之后通过处理,配合其他传感器的数据,最终判断是否需要开灯关灯
完整项目资料包下载地址: https://download.csdn.net/download/xiaolong1126626497/75319474
2. 硬件介绍
3. 设计思路与相关硬件介绍
3.1 主程序设计
程序的主要功能: STC89C52 单片机作为核心器件,首先初始化 BH1750 光敏传感器,再初始化定时器,开始进行定时器扫描工作。在主函数循环里不断读取光敏、声音传感器、人体感应传感器的数据设置开关灯的状态,以便对采集到的数据作进一步处理。当定时器中断产生后,在定时器中断服务函数里进行处理 LED 的状态。
主程序框架图如下所示:
定时器的运行流程图:
3.2 光敏传感器
光敏传感器采用 BH1750,这是一个 IIC 总线接口的数字光敏传感器,需要封装 IIC 标准的函数接口,完成数据读取。
IIC 总线的通信过程分别由开始信号、结束信号、发送数据、响应信号、接收数据五个部分构成。当 SCL 时钟线为高电平的时候,SDA 数据线不允许变化,当 SCL 时钟线为低电平的时候,SDA 数据线可以在 0 和 1 之间任意变化。 只有当 SCL 时钟线为高电平的时候,IIC 总线电路才能对 SDA 数据线上的电平(0 或 1)进行读取,当 SCL 时钟线为低电平的时候,无论 SDA 数据是高还是低电平,IIC 总线都不对 SDA 数据线进行采样读取。
BH1750 光敏传感器流程图设计:
3.3 声音检测、人体感应传感器
声音检测和人体感应传感器输出的都是 0 和 1,所以代码比较简单,和按键原理一样,读取输入的电平即可,灵敏度可以调整模块上面的电位器。
下面是程序检测的流程图:
4. 项目代码
4.1 BH1750 传感器代码
//------------------------------------
void Delay5us();
void Delay5ms();
void BH1750_Start(); //起始信号
void BH1750_Stop(); //停止信号
void BH1750_SendACK(bit ack); //应答ACK
bit BH1750_RecvACK(); //读ack
void BH1750_SendByte(BYTE dat); //IIC单个字节写
BYTE BH1750_RecvByte(); //IIC单个字节读
/**************************************
延时5微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数,注意时钟过快时需要修改
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5us()
{
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
/**************************************
延时5毫秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
当改用1T的MCU时,请调整此延时函数
**************************************/
void Delay5ms()
{
WORD n = 560;
while (n--);
}
/**************************************
起始信号
**************************************/
void BH1750_Start()
{
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 0; //产生下降沿
Delay5us(); //延时
SCL = 0; //拉低时钟线
}
/**************************************
停止信号
**************************************/
void BH1750_Stop()
{
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
Delay5us(); //延时
SDA = 1; //产生上升沿
Delay5us(); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(bit ack)
{
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
/**************************************
接收应答信号
**************************************/
bit BH1750_RecvACK()
{
SCL = 1; //拉高时钟线
Delay5us(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
Delay5us(); //延时
return CY;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void BH1750_SendByte(BYTE dat)
{
BYTE i;
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
Delay5us(); //延时
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
BH1750_RecvACK();
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
BYTE BH1750_RecvByte()
{
BYTE i;
BYTE dat = 0;
SDA = 1; //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
Delay5us(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
Delay5us(); //延时
}
return dat;
}
//*********************************
void Single_Write_BH1750(uchar REG_Address)
{
BH1750_Start(); //起始信号
BH1750_SendByte(SlaveAddress); //发送设备地址+写信号
BH1750_SendByte(REG_Address); //内部寄存器地址,
// BH1750_SendByte(REG_data); //内部寄存器数据,
BH1750_Stop(); //发送停止信号
}
//*********************************************************
//
//连续读出BH1750内部数据
//
//*********************************************************
void Multiple_read_BH1750(void)
{ uchar i;
BH1750_Start(); //起始信号
BH1750_SendByte(SlaveAddress+1); //发送设备地址+读信号
for (i=0; i<3; i++) //连续读取2个地址数据,存储中BUF
{
BUF[i] = BH1750_RecvByte(); //BUF[0]存储0x32地址中的数据
if (i == 3)
{
BH1750_SendACK(1); //最后一个数据需要回NOACK
}
else
{
BH1750_SendACK(0); //回应ACK
}
}
BH1750_Stop(); //停止信号
Delay5ms();
}
//初始化BH1750,根据需要请参考pdf进行修改****
void Init_BH1750()
{
Single_Write_BH1750(0x01);
}
复制代码
4.2 定时器代码
void Timer0Interrupt(void) interrupt 1
{
TL0 = 0xAE; //设置定时初始值
TH0 = 0xFB; //设置定时初始值
count++;
timecount++;
if(timecount>20000)timecount=20000;
if(timecount<12000)
{
if(count<out)
{
LED = 0;
}
else if(count<100)
{
LED = 1;
}
else
count=0;
}
else
{
LED = 1;
}
}
复制代码
4.3 main 函数代码
void main()
{
delay300ms(); //延时300ms
Init_BH1750(); //初始化BH1750
TL0 = 0xAE; //设置定时初始值
TH0 = 0xFB; //设置定时初始值
EA = 1;
ET0 = 1;
TR0 = 1;
ADDR = 0;
LED = 1;
while(1)
{
unsigned char disbuff[9]={0};
if(RT == 1 || SY == 0)
{
timecount = 0;
Single_Write_BH1750(0x01); // power on
Single_Write_BH1750(0x10); // H- resolution mode
delay_nms(180); //延时180ms
Multiple_Read_BH1750(); //连续读出数据,存储在BUF中
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1];//合成数据,即光照数据
out = dis_data/80;
if(out>100)out=100;
if(out<10)out=10;
delay_nms(100);
}
}
}
复制代码
评论