【蓝桥杯第十二届省赛】
#include "reg52.h"
#include "onewire.h"
#include "iic.h"
/*============================================
第十二届蓝桥杯单片机
Date:2022.2.4
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;
unsigned char Temperature = 25;
unsigned char Temperature_Param = 25;//温度参数设置
unsigned int voltage = 325; //电压 扩大100倍方便计算显示
unsigned char interface_mode = 0,work_mode = 1; //界面切换 工作模式
unsigned char Temperature_start = 0,DAC_start = 0,count = 0;// 温度 DAC刷新标志 计时
unsigned char code SMG_duama[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//数码管段码不带小数点
unsigned char code SMG_DOT[10] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//数码管段码带小数点
//------------------------------简单延时-------------------------
void Delay(unsigned int t)
{
while(t--);
}
//-------------------------74HC138初始化-------------------------
void Init_74HC138(unsigned char n)
{
switch(n)
{
case 0:P2 = (P2 & 0x1f) | 0x00;break;
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;
}
}
//---------------------------系统初始化--------------------------
void Init_System(void)
{
Init_74HC138(4);
P0 = 0xff;
Init_74HC138(5);
P0 = 0x00;
Init_74HC138(0);
}
//--------------------------------数码管安位显示-----------------
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;
}
void SMG_Display_Volate(void)
{
SMG_DisplayBit(0,SMG_duama[10]);
Delay(200);
SMG_DisplayBit(1,0xff);
Delay(200);
SMG_DisplayBit(2,0xff);
Delay(200);
SMG_DisplayBit(3,0xff);
Delay(200);
SMG_DisplayBit(4,0xff);
Delay(200);
SMG_DisplayBit(5,SMG_DOT[voltage/100]);
Delay(200);
SMG_DisplayBit(6,SMG_duama[voltage/10%10]);
Delay(200);
SMG_DisplayBit(7,SMG_duama[voltage%10]);
Delay(200);
SMG_Close();
Delay(200);
}
void SMG_Display_Temperature(void)
{
SMG_DisplayBit(0,SMG_duama[12]);
Delay(200);
SMG_DisplayBit(1,0xff);
Delay(200);
SMG_DisplayBit(2,0xff);
Delay(200);
SMG_DisplayBit(3,0xff);
Delay(200);
SMG_DisplayBit(4,SMG_duama[Temperature*100/1000]);
Delay(200);
SMG_DisplayBit(5,SMG_DOT[Temperature*100/100%10]);
Delay(200);
SMG_DisplayBit(6,SMG_duama[Temperature*100/10%10]);
Delay(200);
SMG_DisplayBit(7,SMG_duama[Temperature*100/10%10]);
Delay(200);
SMG_Close();
Delay(200);
}
void SMG_Set_Temperature(void)
{
//P 0011 0001 0X8C
SMG_DisplayBit(0,0X8c);
Delay(200);
SMG_DisplayBit(1,0xff);
Delay(200);
SMG_DisplayBit(2,0xff);
Delay(200);
SMG_DisplayBit(3,0xff);
Delay(200);
SMG_DisplayBit(4,0xff);
Delay(200);
SMG_DisplayBit(5,0xff);
Delay(200);
SMG_DisplayBit(6,SMG_duama[Temperature_Param/10]);
Delay(200);
SMG_DisplayBit(7,SMG_duama[Temperature_Param%10]);
Delay(200);
SMG_Close();
Delay(200);
}
//--------------------------------DS18B20------------------------
void Read_Temperature(void)
{
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay(500);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
Temperature = (MSB << 8) | LSB;
if(Temperature & 0xf800 == 0x0000)
{
Temperature = Temperature >> 4;
Temperature *= 10;
Temperature = Temperature + (LSB & 0x0f)*0.625;
}
}
//---------------------------------PCF8591----------------------
void Read_Rd2_DAC(float dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
//----------------------------------矩阵键盘--------------------
void Matrix_Key(void)
{
H3 = 0;
H1 = H2 = H4 = 1;
L1 = L2 = L3 = L4 = 1;
//s9 在参数界面下按下S9按键,温度参数加1
if(L3 == 0)
{
Delay(20);
if(L3 == 0)
{
while(L3 == 0)
{
SMG_Set_Temperature(); //温度设置界面
}
if(interface_mode == 1) //在温度界面下进行温度加一
{
Temperature_Param++;
}
}
}
//S5 定义为“模式”切换按键。
/*
模式1:DAC输出电压与温度相关。
通过DS18B20采集到的实时温度小于温度参数时,DAC输出0V,
否则,DAC输出5V。 模式2:DAC按照图7给出的关系输出电压。
*/
if(L4 == 0)
{
Delay(20);
if(L4 == 0)
{
while(L4 == 0)
{
SMG_Display_Volate();
}
if(work_mode == 1)
{
if(Temperature < Temperature_Param)
{
Read_Rd2_DAC(0); //实时温度小于温度参数时,DAC输出0V,
voltage = 0;
}
else
{
Read_Rd2_DAC(255); //DAC输出5V
voltage = 500; //5v 扩大100 倍 方便计算
}
work_mode = 2;
}
else if(work_mode == 2)
{
work_mode = 0;
if(Temperature <= 20)
{
//5/255 = 1/x x->255/5
Read_Rd2_DAC(51);
voltage = 100; //1v
}
else if(Temperature > 40)
{
//5/255 = 4/x x-> 204
Read_Rd2_DAC(204);
voltage = 400; //4v
}
//关系式输出
else if(Temperature > 20 && Temperature < 40)
{
Read_Rd2_DAC((0.15*Temperature-2)*51.0);
voltage = (0.15*Temperature-2)*100; //扩大100倍方便计算
}
work_mode = 1;
}
}
}
H4 = 0;
H1 = H2 = H3 = 1;
L1 = L2 = L3 = L4 = 1;
//s8 定义为“减”按键 参数界面下按下S8按键,温度参数减1
if(L3 == 0)
{
Delay(20);
if(L3 == 0)
{
while(L3 == 0)
{
SMG_Set_Temperature(); //温度设置界面
}
if(interface_mode == 1) //在温度界面下进行温度减一
{
Temperature_Param--;
}
}
}
//S4 定义为“界面”按键,按下S4按键,切换温度显示界面、参数设置界面和DAC输出界面,
if(L4 == 0)
{
Delay(20);
if(L4 == 0)
{
while(L4 == 0)
{
if(interface_mode == 0)
{
interface_mode = 1;
SMG_Display_Temperature(); //温度显示界面
}
else if(interface_mode == 1)
{
interface_mode = 2;
SMG_Set_Temperature(); //温度设置界面
}
else if(interface_mode == 2)
{
interface_mode = 0;
SMG_Display_Volate(); //电压显示界面
}
}
}
}
}
//--------------------------------LED功能处理-------------------
void Led_Running(void)
{
//当前处于模式1状态,指示灯L1点亮,否则熄灭
Init_74HC138(4);
if(work_mode == 1)
{
P0 = 0x7f; //0111 1111
}
switch(interface_mode)
{
case 0:P0 = 0xfd;break;//当前处于温度显示界面,指示灯L2点亮,否则熄灭
case 1:P0 = 0xfb;break;//当前处于参数设置界面,指示灯L3点亮,否则熄灭。
case 2:P0 = 0xf7;break; //当前处于DAC输出界面,指示灯L4点亮,否则熄灭
}
/*
if(interface_mode == 0)
{
P0 = 0xfd; //1011 1111
}
//当前处于参数设置界面,指示灯L3点亮,否则熄灭。
if(interface_mode == 1)
{
P0 = 0xfb; //1101 1111
}
//当前处于DAC输出界面,指示灯L4点亮,否则熄灭
if(interface_mode == 2)
{
P0 = 0xf7; //1110 1111
}
*/
}
//--------------------------------定时器初始化-------------------
void Init_Timer(void)
{
TMOD = 0x01;
TH0 = (65535-50000)/256; //50MS
TL0 = (65535-50000)%256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
//----------------------------主函数-----------------------------
void main(void)
{
Init_System();
Init_Timer();
while(1)
{
Matrix_Key();
Read_Temperature();
switch(interface_mode)
{
case 0:SMG_Display_Temperature();break;
case 1:SMG_Set_Temperature();break;
case 2:SMG_Display_Volate(); break;
}
Led_Running();
}
}
//----------------------------------中断服务函数----------------
//温度数据刷新时间:≤1秒。
//DAC输出电压刷新时间:≤0.5秒
void Server_Timer0() interrupt 1
{
TH0 = (65535-50000)/256;
TL0 = (65535-50000)%256;
count++;
if(count == 10) //0.5s
{
if(DAC_start == 0 )//DAC刷新标志
{
DAC_start = 1;
}
else if(DAC_start == 1)
{
DAC_start = 0;
}
}
if(count == 20)// 1s
{
if(Temperature_start == 0) //温度刷新标志
{
Temperature_start = 1;
}
else if(Temperature_start == 1)
{
Temperature_start = 0;
}
count = 0;
}
}