【51单片机】【protues仿真】基于51单片机智能路灯PCF8591系统
目录
一、主要功能
二、使用步骤
三、硬件资源
四、软件设计
五、实验现象
一、主要功能
1、LCD1602显示日期、时间、光照强度;
2、采用DS1302运行系统时间;
3、采用光敏电阻+PCF8591检测光照;
4、按键可修改系统时间、工作开始/结束时间、光照阈值;
5、工作时间:路灯点亮,
6、非工作时间:光照强度低于光照阈值,路灯点亮;
二、使用步骤
基于51单片机的智能路灯系统设计结合光控、时控、等多种功能,以实现节能和智能化管理,通过按键来切换模式和时间以及光敏阈值设置。
三、硬件资源
1、51单片机核心模块
2、按键模块
3、时钟模块
4、蜂鸣器模块
5、PCF8591模块
6、LCD1602显示模块
四、软件设计
#include<reg52.h>
#include <string.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbit en=P2^7;
sbit rw=P2^6; //如果硬件上rw接地,就不用写这句和后面的rw=0了
sbit rs=P2^5;
sbit I2C_SCL = P1^3;//I2C通信的两个引脚
sbit I2C_SDA = P1^4;
//DS1302时钟芯片与C51之间的引脚连接定义
sbit SCLK = P1^0;
sbit IO = P1^1;
sbit RST = P1^2;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit led_1 = P3^7;
uchar code tab1[]= {"20 - - "}; //年显示的固定字符
uchar code tab2[]= {" : : "}; //时间显示的固定字符
uchar count=0;
uchar Led_count=0;
uchar light;
uchar light_limit=100;
uchar Mode_flag = 0;
void Timer0Init(void);
void uart_init();
void delay(uint xms);//延时函数,有参函数
void write_1602com(uchar com);
void write_1602dat(uchar dat);
void write_ShouNum(uchar x,uchar y,uchar dat);
void lcd_init();//***液晶初始化函数****
uchar read_byte();//读一个字节
void write_byte(uchar dat);//写一个字节
void I2C_delay()//I2C延时函数
{
_nop_();
_nop_();
_nop_();
_nop_();
}
void I2C_start()//I2C起始信号
{
I2C_SDA = 1;
I2C_SCL = 1;
I2C_delay();
I2C_SDA = 0;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
}
void I2C_stop()//I2C停止信号
{
I2C_SDA = 0;
I2C_SCL = 0;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SDA = 1;
I2C_delay();
}
bit I2C_write(uint dat)//I2C写一个字节
{
bit ack = 0;
uint mask = 0;
for(mask=0x80;mask!=0;mask>>=1)
{
if((mask&dat) == 0)
I2C_SDA = 0;
else
I2C_SDA = 1;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
}
I2C_SDA = 1;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
ack = I2C_SDA;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
return (~ack);
}
uint I2C_read_ACK()//I2C读一个字节,并发送应答位
{
uint dat = 0;
uint mask = 0;
I2C_SDA = 1;
for(mask=0x80;mask!=0;mask>>=1)
{
if(I2C_SDA == 0)
dat = dat & (~mask);
else
dat = dat | mask;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
}
I2C_SDA = 0;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
return dat;
}
uint I2C_read_NACK()//I2C读一个字节,并发送非应答位
{
uint dat = 0;
uint mask = 0;
I2C_SDA = 1;
for(mask=0x80;mask!=0;mask>>=1)
{
if(I2C_SDA == 0)
dat = dat & (~mask);
else
dat = dat | mask;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
}
I2C_SDA = 1;
I2C_delay();
I2C_SCL = 1;
I2C_delay();
I2C_SCL = 0;
I2C_delay();
return dat;
}
uint get_ADC_vaule(uint chn)//获取AD值
{
uint value = 0;
I2C_start();//I2C起始信号
if(!I2C_write(0X90))//写入PCF8591地址及读写选择位为写
{
I2C_stop();
return 0;
}
// I2C_write(0X40 | chn);//写入PCF8591通道0
I2C_write(0x00 | chn);//写入PCF8591通道0
I2C_start();//I2C起始信号
I2C_write(0x48<<1 | 0x01);
I2C_read_ACK();//提供转换所需的时钟信号
value = I2C_read_NACK();//读取上一次转换的结果
I2C_stop();//I2C结束信号
return value;
}
//*******************主函数**************************
void main()
{
lcd_init(); //调用液晶屏初始化子函数
Timer0Init(); //定时器0初始化
// ds1302_init(); //调用DS1302时钟的初始化子函数
while(1) //无限循环下面的语句:
{
qiehaun();//模式切换
keyscan();//时间设置
set_work_time(); //设定工作时间
set_limit_light(); //设定光照阈值
light = 255-get_ADC_vaule(0); //读取ADC数值
}
}
五、实验现象
演示视频: