【蓝桥杯第十一届省赛-电压采集】
#include "reg52.h"
#include "iic.h"
/*=============================================================
Date:2022-1-26
Author:小殷同学
Version:1.0
==============================================================*/
sfr P4 = 0xc0;
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L1 = P3^4;
sbit L2 = P3^5;
sbit L3 = P4^2;
sbit L4 = P4^4;
sbit Led1 = P0^0;
sbit Led2 = P0^1;
sbit Led3 = P0^2;
sbit Led4 = P0^3;
unsigned char Rd2 = 0,Vp = 200,Count = 0; //PCF8591电压采集 vP 和计数记录
unsigned char setmode = 0;// 模式切换记录
unsigned char invalid_key = 0;//无效次数按键记录
unsigned char count_flag = 0,led_flag = 0,v_flag = 0; //计时5s 和led标志
unsigned char code smg_duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
unsigned char SMG_Duan_Dot[] = {0x40,0x79,0x34,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//---------------------------简单延时--------------------------
void Delay(unsigned char t)
{
while(t--);
}
//-----------------------74HC138初始化-------------------------
void Init_74HC138(unsigned char n)
{
switch(n)
{
case 4:P2 = (P2 & 0x1f) | 0x80;break;
case 5:P2 = (P2 & 0x1f) | 0xa0;break;
case 6:P2 = (P2 & 0x1f) | 0xc0;break;
case 7:P2 = (P2 & 0x1f) | 0xe0;break;
case 0:P2 = (P2 & 0x1f) | 0X00;break;
}
}
//------------------------系统初始化---------------------------
void Init_System(void)
{
Init_74HC138(4);
P0 = 0xff; //关闭LED
Init_74HC138(5);
P0 = 0x00; //关闭继电器和蜂鸣器
}
//-----------------------数码管安位显示------------------------
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
Init_74HC138(6);
P0 = (0x01 << pos);
Init_74HC138(7);
P0 = dat;
}
//-----------------------关闭数码管----------------------------
void SMG_Close(void)
{
Init_74HC138(6);
P0 = 0xff;
Init_74HC138(7);
P0 = 0xff;
}
//-----------------------------数码管界面显示-------------------
//1000 0011 0xc1 u 0011 0001 0x8c p 1101 1001 0x9b n
//1.数据界面
void SMG_Display_Data(void)
{
SMG_DisplayBit(0,0xc1);
Delay(200);
SMG_DisplayBit(1,smg_duan[11]);
Delay(200);
SMG_DisplayBit(2,smg_duan[11]);
Delay(200);
SMG_DisplayBit(3,smg_duan[11]);
Delay(200);
SMG_DisplayBit(4,smg_duan[11]);
Delay(200);
SMG_DisplayBit(5,SMG_Duan_Dot[Rd2/100]);
Delay(200);
SMG_DisplayBit(6,smg_duan[Rd2/10%10]);
Delay(200);
SMG_DisplayBit(7,smg_duan[Rd2%10]);
Delay(200);
SMG_Close();
Delay(200);
}
//2.参数界面
void SMG_Display_Paramter(void)
{
SMG_DisplayBit(0,0x8c);
Delay(200);
SMG_DisplayBit(1,smg_duan[11]);
Delay(200);
SMG_DisplayBit(2,smg_duan[11]);
Delay(200);
SMG_DisplayBit(3,smg_duan[11]);
Delay(200);
SMG_DisplayBit(4,smg_duan[11]);
Delay(200);
SMG_DisplayBit(5,SMG_Duan_Dot[Vp/100]);
Delay(200);
SMG_DisplayBit(6,smg_duan[Vp/10%10]);
Delay(200);
SMG_DisplayBit(7,smg_duan[Vp%10]);
Delay(200);
SMG_Close();
Delay(200);
}
//3.计数界面
void SMG_Display_Count(void)
{
SMG_DisplayBit(0,0x9b);
Delay(200);
SMG_DisplayBit(1,smg_duan[11]);
Delay(200);
SMG_DisplayBit(2,smg_duan[11]);
Delay(200);
SMG_DisplayBit(3,smg_duan[11]);
Delay(200);
SMG_DisplayBit(4,smg_duan[11]);
Delay(200);
if(Count > 99)
{
SMG_DisplayBit(5,smg_duan[Count/100]);
Delay(200);
}
if(Count > 9)
{
SMG_DisplayBit(6,smg_duan[Count/10%10]);
}
Delay(200);
SMG_DisplayBit(7,smg_duan[Count%10]);
Delay(200);
SMG_Close();
Delay(200);
}
//-----------------------------AIN3 Rd2检测--------------------
//Rd2 0x03
unsigned char Read_Rd2_Data(void)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
//--------------------------AT24C02写入数据--------------------
void Write_AT24C02(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();
}
//-----------IIC_Stop();---------------AT24C02读取数据--------------------
unsigned char Read_AT24C02(unsigned char addr)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return temp;
}
//----------------------------按键扫描-------------------------
void KeyScans(void)
{
H3 = 0;
H1 = H2 = H4 = 1;
L1 = L2 = L3 = L4 = 1;
//S17 vp减 0.5到0时返回5.0v
if(L1 == 0)
{
Delay(20);
if(L1 == 0)
{
while(L1 == 0)
{
if(setmode == 1)
{
Vp -= 50;
if(Vp == 0) //边界处理
{
Vp = 500;
}
invalid_key = 0;
}
else
{
invalid_key++; //无效次数累加
}
}
}
}
//S13
if(L2 == 0)
{
Delay(20);
if(L2 == 0)
{
while(L2 == 0)
{
Count = 0;
}
}
}
H4 = 0;
H1 = H3 = H2 = 1;
L1 = L2 = L3 = L4 = 1;
//S16 加0.5加到5时 -》0
if(L1 == 0)
{
Delay(20);
if(L1 == 0)
{
while(L1 == 0)
{
if(setmode == 1)
{
Vp += 50;
if(Vp == 500) //边界处理
{
Vp = 0;
}
invalid_key = 0;
}
else
{
invalid_key++;//无效次数累加
}
}
}
}
//s12
if(L2 == 0)
{
Delay(20);
if(L2 == 0)
{
while(L2 == 0)
{
if(setmode == 0) //数据显示界面
{
setmode = 1;
SMG_Display_Data();
}
else if(setmode == 1) //参数显示界面
{
setmode = 2;
Write_AT24C02(0x00,Vp*10);
Delay(200);
SMG_Display_Paramter();
}
else if(setmode == 2) //计数显示界面
{
setmode = 0;
SMG_Display_Count();
}
}
}
}
}
//------------------------定时器初始化------------------------
void Init_Timer(void)
{
TMOD = 0x01;
TH0 = (65535-50000)/256;//50ms
TL0 = (65535-50000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
//---------------------------Led功能函数----------------------
void Led_Running(void)
{
//指示灯L1:当VAIN3 < VP的状态持续时间超过5秒时,L1点亮,否则熄灭
if(Rd2 < Vp)
{
TR0 = 1;
}
else
{
TR0 = 0;
count_flag = 0;
led_flag = 0;
}
Init_74HC138(4);
if(led_flag == 1) //VIN3 < Vp超过5s
{
Led1 = 0;
}
else
{
Led1 = 1;
}
//指示灯L2:当前计数值为奇数时,L2点亮,否则熄灭。
if(Count % 2 == 0)
{
Led2 = 1;
}
else
{
Led2 = 0;
}
//指示灯L3:连续3次以上(含3次)的无效按键操作触发L3点亮,直到出现有效的按键操作,L3熄灭
if(invalid_key >= 3)
{
Led3 = 0;
}
else
{
Led3 = 1;
}
Init_74HC138(0);
}
//--------------------------主函数-----------------------------
void main(void)
{
Init_System();
Vp = Read_AT24C02(0x00) * 10;
while(1)
{
Rd2 = Read_Rd2_Data();// 计算转换电压
Rd2 = (Rd2/256.0*5)*100;
switch(setmode)
{
case 0:SMG_Display_Data();break;
case 1:SMG_Display_Paramter();Delay(2000);break;
case 2:SMG_Display_Count();break;
}
if(Rd2 > Vp)
{
v_flag = 1;
}
else if(Rd2 < Vp)
{
if(v_flag == 1)
{
Count++;
v_flag = 0;
}
}
KeyScans();
Led_Running();
}
}
//---------------------中断服务函数-------------------------
void Server_Timer0() interrupt 1
{
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
count_flag++;
if(count_flag > 100) // 大于5s
{
count_flag = 0;
led_flag = 1;
TR0 = 0;
}
}