【蓝桥杯单片机进阶强化-04】PCF8591与24C02综合应用-智能照明自动控制器

【1】题目要求

      在蓝桥杯大赛“单片机设计与开发”的在CT107D综合训练平台上,利用竞赛提供的IIC底层驱动代码,设计程序,实现以下的功能:

    1- 系统上电后,通过采样PCF8591通道1光敏电阻RD1的实时数据,并根据该数据控制8个LED灯的亮灭情况。

       灯光的控制分为5个等级:

       等级1255 <= 光照数据 < 200L1点亮。

       等级2200 <= 光照数据 < 150L1~L2点亮。

       等级3150 <= 光照数据 < 100L1~L4点亮。

       等级4100 <= 光照数据 < 50L1~L6点亮。

       等级550 <= 光照数据 < 0L1~L8点亮。

    2- 灯光控制等级光敏数据实时显示在数码管上,如下如所示,灯光等级在左,光敏实时数据在右

    3- 按下S4按键,将当前的灯光控制等级和光敏电阻的数据保存到存储器24C020x010x02内存单元中。

    4- 按下S5按键时,读取存储在24C02的历史数据并显示在数码管上,松开S5按键后,恢复显示实时数据

         【蓝桥杯单片机进阶强化-04】PCF8591与24C02综合应用-智能照明自动控制器_第1张图片

【2】参考资料

    1-【蓝桥杯单片机进阶强化-01】IIC总线接口技术基础

    2-【蓝桥杯单片机进阶强化-02】PCF8591的基本原理与A/D转换应用

    3-【蓝桥杯单片机进阶强化-03】24C02存储器的基本原理与应用

【3】参考源码共享

#include "regx52.h"
#include "absacc.h"
#include "iic.h"

sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned char dat_rd1 = 0;		//光敏电阻实时数据
unsigned char level = 0;		//当前灯光控制等级
unsigned char bak_level = 0;	//光敏电阻历史数据
unsigned char bak_rd1 = 0;		//历史灯光控制等级

//数码管显示段码数组
unsigned char code SMG_duanma[18]=
		{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
		 0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
//简单的延时函数
void DelaySMG(unsigned int t)
{
	while(t--);
}
/*=====================显示单位数码管函数=====================*/
void DisplaySMG_Bit(unsigned char pos, unsigned char value)
{
	XBYTE[0xE000] = 0xFF;				//消隐
	XBYTE[0xC000] = 0x01 << pos;		//选择数码管的位置
	XBYTE[0xE000] = value;				//输出数码管显示的内容
}

/*=====================显示当前的实时数据=====================*/
void Display_now()
{
	DisplaySMG_Bit(0, SMG_duanma[16]);			
	DelaySMG(500);
	DisplaySMG_Bit(1, SMG_duanma[level]);
	DelaySMG(500);
	DisplaySMG_Bit(2, SMG_duanma[16]);
	DelaySMG(500);
			
	DisplaySMG_Bit(3, 0xFF);
	DelaySMG(500);
	DisplaySMG_Bit(4, 0xFF);
	DelaySMG(500);
	
	DisplaySMG_Bit(5, SMG_duanma[dat_rd1 / 100]);
	DelaySMG(500);
	DisplaySMG_Bit(6, SMG_duanma[(dat_rd1 % 100) / 10]);
	DelaySMG(500);
	DisplaySMG_Bit(7, SMG_duanma[dat_rd1 % 10]);
	DelaySMG(500);
}

/*=====================显示读取的历史数据=====================*/
void Display_old()
{
	DisplaySMG_Bit(0, SMG_duanma[16]);
	DelaySMG(500);
	DisplaySMG_Bit(1, SMG_duanma[bak_level]);
	DelaySMG(500);
	DisplaySMG_Bit(2, SMG_duanma[16]);
	DelaySMG(500);
			
	DisplaySMG_Bit(3, 0xFF);
	DelaySMG(500);
	DisplaySMG_Bit(4, 0xFF);
	DelaySMG(500);
	
	DisplaySMG_Bit(5, SMG_duanma[bak_rd1 / 100]);
	DelaySMG(500);
	DisplaySMG_Bit(6, SMG_duanma[(bak_rd1 % 100) / 10]);
	DelaySMG(500);
	DisplaySMG_Bit(7, SMG_duanma[bak_rd1 % 10]);
	DelaySMG(500);
}

/*===================采样PCF8591通道1的数据===================*/
void Read_RD1()
{
	IIC_Start();					//起始信号
	IIC_SendByte(0x90); 			//设备写地址
	IIC_WaitAck();  				//等待应答
	IIC_SendByte(0x01); 			//设置控制寄存器
	IIC_WaitAck();  				//等待应答
	IIC_Stop(); 					//停止信号
	
	IIC_Start();					//起始信号
	IIC_SendByte(0x91); 			//设备读地址
	IIC_WaitAck(); 				    //等待应答
	dat_rd1 = IIC_RecByte(); 	    //读取当前通道1的数据
	IIC_Ack(0); 					//产生非应答信号
	IIC_Stop(); 					//停止信号
}

/*======================灯光等级控制函数======================*/
void Right_Auto()
{
	Read_RD1();						//读取光敏电阻的实时数据
	if(dat_rd1 > 200)				//等级1
	{
		XBYTE[0x8000] = 0xfe;		//点亮L1
		level = 1;
	}
	else if(dat_rd1 > 150)		    //等级2
	{
		XBYTE[0x8000] = 0xfc;		//点亮L1~L2
		level = 2;
	}
	else if(dat_rd1 > 100)		    //等级3
	{
		XBYTE[0x8000] = 0xf0;		//点亮L1~L4
		level = 3;
	}
	else if(dat_rd1 > 50)			//等级4
	{
		XBYTE[0x8000] = 0xc0;		//点亮L1~L6
		level = 4;
	}
	else							//等级5
	{
		XBYTE[0x8000] = 0x00;		//点亮L1~L8
		level = 5;
	}
}

/*=======================24C02字节写函数=======================*/
void Write_24C02(unsigned char addr, unsigned char dat)
{
	IIC_Start();					//起始信号					
	IIC_SendByte(0xa0); 			//设备写地址
	IIC_WaitAck();					//等待应答
	IIC_SendByte(addr); 			//发送内存字节地址
	IIC_WaitAck(); 					//等待应答
	IIC_SendByte(dat); 				//写入目标数据
	IIC_WaitAck();					//等待应答
	IIC_Stop();						//停止信号
}

/*=======================24C02字节读函数=======================*/
unsigned char Read_24C02(unsigned char addr)
{
	unsigned char tmp;
	IIC_Start();					//起始信号			
	IIC_SendByte(0xa0); 			//设备写地址
	IIC_WaitAck();					//等待应答
	IIC_SendByte(addr); 			//发送内存字节地址
	IIC_WaitAck(); 					//等待应答

	IIC_Start();					//起始信号
	IIC_SendByte(0xa1); 			//设备读地址
	IIC_WaitAck();					//等待应答
	tmp = IIC_RecByte();			//读出目标数据
	IIC_Ack(0); 					//产生非应答信号
	IIC_Stop();						//停止信号
	return tmp;
}

/*=======================按键扫描处理函数=======================*/
void Scan_Keys()
{
	if(S4 == 0)								
	{
		DelaySMG(100);
		if(S4 == 0)
		{
			//将当前的灯光控制等级和光敏电阻数据写入24C02存储器
			Write_24C02(0x01, level);
			DelaySMG(1000);				//等待数据写入完成
			Write_24C02(0x02, dat_rd1);
			
			while(S4 == 0)
			{
				Display_now();			//在等待按键松开时刷新数码管
			}
		}
	}
	if(S5 == 0)
	{
		DelaySMG(100);
		if(S5 == 0)
		{
			//读出24C02中的历史数据
			bak_level = Read_24C02(0x01);
			bak_rd1 = Read_24C02(0x02);
			while(S5 == 0)
			{
				Display_old();		//在S5按键按下时,显示历史数据
			}
		}
	}
}
/*============================主函数============================*/
void main()
{
	while(1)
	{
		Right_Auto();			//光敏数据实时采样和灯光控制
		Display_now();			//数码管动态显示
		Scan_Keys();			//按键扫描处理
	}
}

【特别注意】

      在调用竞赛举办方提供的IIC总线接口底层驱动代码的时候,务必认真阅读代码文件,确保无误。另外,在读取PCF8591的模拟输入数据时,在代码正确仍然无法获得准确数据,可以增大IIC驱动程序中的时序延时长度,即“iic.h”文件中的somenop

【更多蓝桥杯独家干货】:可参阅 “小蜜蜂科教” 公众号。

【蓝桥杯单片机进阶强化-04】PCF8591与24C02综合应用-智能照明自动控制器_第2张图片

你可能感兴趣的:(蓝桥杯单片机)