一、项目要求
设计一款声控LED智能灯,该灯含有8个灯珠,采用一个按键统一控制灯的开与关,也可以通过声音控制开灯,开灯后根据环境光亮度,点亮多个灯珠(最暗时点亮8个灯珠,最亮时点亮1个灯珠)。
二、使用的硬件
1. 51单片机实验板,以及电源线、下载线、杜邦线
2. 声音传感器、PCF8591数模转换模块、光敏电阻、独立按键、LED灯
三、设计方案
通过外部中断的开关和声音传感器统一控制灯的开与关,然后用PCF8591数模转换上的光敏电阻把当前环境光的亮度传给单片机,单片机通过光照强度来控制亮几个灯
系统连接图:
四、源代码
1、PCF8591数模转换函数
#include <pcf8591.h>
sbit scl=P2^0; //I2C 时钟
sbit sda=P2^1; //I2C 数据
bit ack; //应答标志位
/*******************************************************************
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
sda=1; /*发送起始条件的数据信号*/
_nop_();
scl=1;
_nop_(); /*起始条件建立时间大于4.7us,延时*/
_nop_();
_nop_();
_nop_();
_nop_();
sda=0; /*发送起始信号*/
_nop_(); /* 起始条件锁定时间大于4μs*/
_nop_();
_nop_();
_nop_();
_nop_();
scl=0; /*钳住I2C总线,准备发送或接收数据 */
_nop_();
_nop_();
}
/*******************************************************************
功能: 结束I2C总线,即发送I2C结束条件.
********************************************************************/
void Stop_I2c()
{
sda=0; /*发送结束条件的数据信号*/
_nop_(); /*发送结束条件的时钟信号*/
scl=1; /*结束条件建立时间大于4μs*/
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
sda=1; /*发送I2C总线结束信号*/
_nop_();
_nop_();
_nop_();
_nop_();
}
/*******************************************************************
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void I2C_SendByte(u8 c)
{
u8 i;
for(i=0;i<8;i++) /*要传送的数据长度为8位*/
{
if((c<<i)&0x80)sda=1; /*判断发送位*/
else sda=0;
_nop_();
scl=1; /*置时钟线为高,通知被控器开始接收数据位*/
_nop_();
_nop_(); /*保证时钟高电平周期大于4μs*/
_nop_();
_nop_();
_nop_();
scl=0;
}
_nop_();
_nop_();
sda=1; /*8位发送完后释放数据线,准备接收应答位*/
_nop_();
_nop_();
scl=1;
_nop_();
_nop_();
_nop_();
if(sda==1)ack=0;
else ack=1; /*判断是否接收到应答信号*/
scl=0;
_nop_();
_nop_();
}
/*******************************************************************
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数应答从机。
********************************************************************/
u8 I2C_RcvByte()
{
u8 retc=0,i;
sda=1; /*置数据线为输入方式*/
for(i=0;i<8;i++)
{
_nop_();
scl=0; /*置时钟线为低,准备接收数据位*/
_nop_();
_nop_(); /*时钟低电平周期大于4.7μs*/
_nop_();
_nop_();
_nop_();
scl=1; /*置时钟线为高使数据线上数据有效*/
_nop_();
_nop_();
retc=retc<<1;
if(sda==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
_nop_();
_nop_();
}
scl=0;
_nop_();
_nop_();
return(retc);
}
/********************************************************************
功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(bit a)
{
if(a==0)sda=0; /*在此发出应答或非应答信号 */
else sda=1; /*0为发出应答,1为非应答信号 */
_nop_();
_nop_();
_nop_();
scl=1;
_nop_();
_nop_(); /*时钟低电平周期大于4μs*/
_nop_();
_nop_();
_nop_();
scl=0; /*清时钟线,住I2C总线以便继续接收*/
_nop_();
_nop_();
}
/************************************************************
* 函数功能 : PCF8591的输出端输出模拟量
******************* *****************************************/
bit Pcf8591_DaConversion(u8 addr,u8 channel,u8 Val)
{
Start_I2c(); //启动总线
I2C_SendByte(addr); //发送器件地址
if(ack==0)return(0);
I2C_SendByte(0x40|channel); //发送控制字节
if(ack==0)return(0);
I2C_SendByte(Val); //发送DAC的数值
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/************************************************************
* 函数功能 : 写入一个控制命令
************************************************************/
bit PCF8591_SendByte(u8 addr,u8 channel)
{
Start_I2c(); //启动总线
I2C_SendByte(addr); //发送器件地址
if(ack==0)return(0);
I2C_SendByte(0x40|channel); //发送控制字节
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/************************************************************
* 函数功能 : 读取一个转换值*/
u8 PCF8591_RcvByte(u8 addr)
{
u8 dat;
Start_I2c(); //启动总线
I2C_SendByte(addr+1); //发送器件地址
if(ack==0)return(0);
dat=I2C_RcvByte(); //读取数据0
Ack_I2c(1); //发送非应答信号
Stop_I2c(); //结束总线
return(dat);
}
2、Main函数
#include<config.h>
#include<uart.h>
#include <pcf8591.h>
sbit RL=P2^2; //声控
sbit gnd=P3^4;
//sbit Switch=P3^2;
sbit beep=P2^3; //蜂鸣器引脚
int flag=1,flag1=1;
u8 print[20];
void delay_ms(u16 x)//毫秒延时函数
{u16 i;
u8 j;
for(i=0;i<x;i++)
for(j=0;j<115;j++);
}
void delay_us(u8 t) //10倍微秒延时函数,延时10*t微秒
{u8 i;
for(i=0;i<=t;i++);
}
void Alarm(u8 t) //蜂鸣器报警,持续t秒
{
u8 i,j,k;
for(j=0;j<t;j++)
{ for(i=0;i<200;i++)
{beep=0;delay_us(50);beep=1;delay_us(50);}
for(k=0;k<100;k++)
{beep=0;delay_us(110);beep=1;delay_us(110);}
}
}
void main()
{
u8 light;
P1=0xff;
EA=1;
IT0=1;
EX0=1;
gnd=0;
Init_COM(); //初始化
flag=1;
while(1)
{
PCF8591_SendByte(AddWr,1);//启动AIN0通道模数转换,光敏
light=PCF8591_RcvByte(AddWr);//读出转换数字值
light=255-light;
delay_ms(200);
sprintf(print,"L:%3bu",light);
Print_str_COM(print); //将采集的值送串口
if(RL==1){flag=!flag;delay_ms(150);}
if(flag==0)
{
//if(light=0){ P1=0XFF;}
if(light>0&&light<30){P1=0X00;}
if(light>=30&&light<60){P1=0X01;}
if(light>=60&&light<90){P1=0X03;}
if(light>=90&&light<120){P1=0X07;}
if(light>=120&&light<150){P1=0X0F;}
if(light>=150&&light<180){P1=0X1F;}
if(light>=180&&light<210){P1=0X3F;}
if(light>=210&&light<=255){P1=0X7F;}
//delay_ms(3000);
//P1=0XFF;
}
else
{
P1=0XFF;delay_ms(10);//break;
}
}
}
void int0() interrupt 0
{
flag=!flag;
}
五、实验效果
由于不能上传视频,所以我将效果视频上传至优酷,请点击观看------->声控LED智能灯
问题咨询及项目源码请加群:
QQ群
名称:IT项目交流群
群号:245022761