一、题目
二、题目分析
1、难点(笔者个人认为)
(1)s17按键短按和长按的设置不同,界面不同
s17短按在参数界面需要把温度参数-1;
s17长按在时间界面需要显示分,秒界面;
所以笔者这里把两个数码管显示分两个函数
void Nixie_Show()//数码管显示函数
{
Nixie_pos_num(1,16);
Nixie_pos_num(3,17);
if(flag_s12 == 0)//温度显示界面
{
Temp = Read_DS18B20_Temp();
Nixie_pos_num(2,1);
Nixie_pos_num(4,17);
Nixie_pos_num(5,17);
Nixie_pos_num(6,Temp/1000);
Nixie_Dian_pos_num(7,Temp/100%10);
Nixie_pos_num(8,Temp/10%10);
}
if(flag_s12 == 1)//时间显示界面
{
Nixie_pos_num(2,2);
Nixie_pos_num(4,Time[2]/16);
Nixie_pos_num(5,Time[2]%16);
Nixie_pos_num(6,18);
Nixie_pos_num(7,Time[1]/16);
Nixie_pos_num(8,Time[1]%16);
}
if(flag_s12 == 2)//参数显示界面
{
Nixie_pos_num(2,3);
Nixie_pos_num(4,17);
Nixie_pos_num(5,17);
Nixie_pos_num(6,17);
Nixie_pos_num(7,Temp_C/10);
Nixie_pos_num(8,Temp_C%10);
}
}
void Nixie_Time_S17()//在时间显示界面下,长按s17显示界面
{
if(flag_s12 == 1)
{
Read_Ds1302_Time(Time);
Nixie_pos_num(1,16);
Nixie_pos_num(2,2);
Nixie_pos_num(3,17);
Nixie_pos_num(4,Time[1]/16);
Nixie_pos_num(5,Time[1]%16);
Nixie_pos_num(6,18);
Nixie_pos_num(7,Time[0]/16);
Nixie_pos_num(8,Time[0]%16);
}
}
分别显示不同的界面,避免界面冲突。当然这里也可以通过switch语句进行界面选择,读者可以自己调整
(2)出现两个不同时间产生不同状态,L1点亮,5秒熄灭,L3要0.1秒交替闪烁
这里直接使用Delay是有问题的,LED灯和数码管显示会频闪。笔者这里用到是定时器
void Timer0Init(void) //50毫秒@12MHz
{
TMOD = 0x01;
TL0 = (65535 - 50000) % 256; //设置定时初值
TH0 = (65535 - 50000) / 256; //设置定时初值
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
void Timer0Init_Time() interrupt 1
{
TL0 = (65535 - 50000) % 256; //设置定时初值
TH0 = (65535 - 50000) / 256; //设置定时初值
count++;
if(count % 5 == 0)//计时100ms
{
flag_L3 = ~flag_L3;
}
if(count == 100)//计时5s
{
flag_timer_relay = 0;
flag_L1 = 0;
count = 0;
}
}
让定时器到点发起中断,产生效果
(3)、温度浮点数处理
在上一篇笔记笔者已经提到,有兴趣的读者可以到这里的四、2、第十五届蓝桥杯单片机模拟II(IAP15F2K61S2)-CSDN博客
这里就不过多阐述
三、代码(仅供参考)
1、头文件
#include <STC15F2K60S2.H>
#include <ds1302.H>
#include <onewire.H>
2、变量声明
sbit K1 = P3^5;
sbit K2 = P3^4;
sbit K3 = P3^3;
sbit K4 = P3^2;
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
//==================数组定义===================
code unsigned char Seg_Table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xc1,0xff,0xbf};//数码管不带小数点 16:0xc1:U 18:0xbf:-
code unsigned char Seg_Dian_Table[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};//数码管带小数点
unsigned char Time[3]={0x55,0x59,0x07};//秒,分,时
//==================变量定义===================
unsigned char flag_s12;//按键s12按下三种状态
unsigned char flag_s13;//按键s13按下两种状态
unsigned char flag_relay = 0;//继电器两种状态
unsigned char Temp_C = 23;//温度参数
unsigned char count;//定时器计时参数
unsigned char flag_L3;//L3灯状态
unsigned char flag_L1;//L1灯状态
unsigned char flag_timer_relay;//时间控制模式下继电器状态
unsigned int Temp;//温度变量
3、函数声明
//==================函数声明===================
void Nixie_Show();//数码管显示函数
void Scan_Key();//按键控制函数
void Nixie_Time_S17();//在时间显示界面下,长按s17显示
void Relay();//继电器控制函数
void LED();//LED灯控制函数
//=============================================
四、函数模块
1、其他函数
void delay(unsigned char i)
{
while(i--);
}
void hc(unsigned char n)//通道选择
{
switch(n)
{
case 0:
P2 = P2 & 0x1f;
break;
case 4:
P2 = (P2 & 0x1f) | 0x80;//LED
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;//蜂鸣器,继电器
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;//数码管位选
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;//数码管段选
break;
}
}
void System_Init()//系统初始化
{
hc(4);
P0 = 0xFF;
hc(5);
P0 = 0x00;
hc(0);
}
2、数码管
void Nixie_pos_num(unsigned char pos,num)//数码管(不带小数点)位置,显示数字
{
hc(6);
P0 = 0x01 << (pos-1);
hc(7);
P0 = Seg_Table[num];
delay(500);
P0 = 0xFF;
hc(0);
}
void Nixie_Dian_pos_num(unsigned char pos,num)//数码管(带小数点)位置,显示数字
{
hc(6);
P0 = 0x01 << (pos-1);
hc(7);
P0 = Seg_Dian_Table[num];
delay(500);
P0 = 0xFF;
hc(0);
}
void Nixie_Show()//数码管显示函数
{
Nixie_pos_num(1,16);
Nixie_pos_num(3,17);
if(flag_s12 == 0)//温度显示界面
{
Temp = Read_DS18B20_Temp();
Nixie_pos_num(2,1);
Nixie_pos_num(4,17);
Nixie_pos_num(5,17);
Nixie_pos_num(6,Temp/1000);
Nixie_Dian_pos_num(7,Temp/100%10);
Nixie_pos_num(8,Temp/10%10);
}
if(flag_s12 == 1)//时间显示界面
{
Nixie_pos_num(2,2);
Nixie_pos_num(4,Time[2]/16);
Nixie_pos_num(5,Time[2]%16);
Nixie_pos_num(6,18);
Nixie_pos_num(7,Time[1]/16);
Nixie_pos_num(8,Time[1]%16);
}
if(flag_s12 == 2)//参数显示界面
{
Nixie_pos_num(2,3);
Nixie_pos_num(4,17);
Nixie_pos_num(5,17);
Nixie_pos_num(6,17);
Nixie_pos_num(7,Temp_C/10);
Nixie_pos_num(8,Temp_C%10);
}
}
void Nixie_Time_S17()//在时间显示界面下,长按s17显示界面
{
if(flag_s12 == 1)
{
Read_Ds1302_Time(Time);
Nixie_pos_num(1,16);
Nixie_pos_num(2,2);
Nixie_pos_num(3,17);
Nixie_pos_num(4,Time[1]/16);
Nixie_pos_num(5,Time[1]%16);
Nixie_pos_num(6,18);
Nixie_pos_num(7,Time[0]/16);
Nixie_pos_num(8,Time[0]%16);
}
}
3、按键
void Scan_Key()//按键控制函数
{
K2 = K3 = K4 = 1;K1 = 0;
if(K3 == 0 || K4 == 0)
{
delay(100);
if(K3 == 0)//s12按键按下
{
flag_s12 = (flag_s12 + 1) % 3;
while(K3 == 0)
{
Nixie_Show();
}
}
if(K4 == 0)//s13按键按下
{
flag_s13 = (flag_s13 + 1) % 2;
while(K4 == 0)
{
Nixie_Show();
LED();
}
}
}
if(flag_s12 == 2)//在参数设置界面关于s16,s17控制
{
K1 = K3 = K4 = 1;K2 = 0;
if(K3 == 0 || K4 == 0)
{
delay(100);
if(K3 == 0)//s16按键按下
{
Temp_C++;
if(Temp_C >= 90)
{
Temp_C = 90;
}
while(K3 == 0)
{
Nixie_Show();
}
}
if(K4 == 0)//s17按键按下
{
Temp_C--;
if(Temp_C <= 10)
{
Temp_C = 10;
}
while(K4 == 0)
{
Nixie_Show();
}
}
}
}
if(flag_s12 == 1)//在时间显示界面关于s17控制
{
K1 = K3 = K4 = 1;K2 = 0;
if(K4 == 0)
{
delay(100);
if(K4 == 0)
{
while(K4 == 0)
{
Nixie_Time_S17();
}
}
}
}
}
4、LED
void LED()//LED灯控制函数
{
//L1灯控制
if(Time[0]==0x00&&Time[1]==0x00)
{
if(flag_L1 == 0)
{
hc(4);
L1 = 0;
hc(0);
}
else
{
hc(4);
L1 = 1;
hc(0);
}
}
else
{
hc(4);
L1 = 1;
hc(0);
}
//L2灯控制
if(flag_s13 == 0)
{
hc(4);
L2 = 0;
hc(0);
}
else
{
hc(4);
L2 = 1;
hc(0);
}
//L3灯控制
if(flag_relay == 1)//在继电器吸合状态
{
if(flag_L3 == 0)
{
hc(4);
L3 = 0;
hc(0);
}
else
{
hc(4);
L3 = 1;
hc(0);
}
}
else
{
hc(4);
L3 = 1;
hc(0);
}
}
5、继电器
void Relay()//继电器控制函数
{
if(flag_s13 == 0)//温度控制模式
{
if(Temp>Temp_C*100)
{
hc(5);
P0 = 0x10;
hc(0);
flag_relay = 1;
}
else
{
hc(5);
P0 = 0x00;
hc(0);
flag_relay = 0;
}
}
if(flag_s13 == 1)//时间控制模式
{
if(Time[0]==0x00&&Time[1]==0x00)
{
hc(5);
P0 = 0x10;
hc(0);
flag_relay = 1;
flag_timer_relay = 1;
}
else
{
hc(5);
P0 = 0x00;
hc(0);
flag_relay = 0;
}
}
}
6、main
void main()
{
System_Init();
Timer0Init();
Temp = Read_DS18B20_Temp();
Write_Ds1302_Time(Time);
while(1)
{
Read_Ds1302_Time(Time);
Temp = Read_DS18B20_Temp();
Nixie_Show();
Scan_Key();
LED();
Relay();
}
}
7、onewrie
unsigned int Read_DS18B20_Temp()
{
unsigned char LSB,MSB;
unsigned int Temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
Temp = (MSB << 8) | LSB;
Temp = Temp >> 4;
Temp = Temp * 100;
Temp = Temp + (LSB & 0x0f) * 0.0625 * 100;
return Temp;
}
8、ds1302
code unsigned char Write_Time[3]={0x80,0x82,0x84};
code unsigned char Read_Time[3]={0x81,0x83,0x85};
void Write_Ds1302_Time(unsigned char *time)
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i = 0;i < 3;i++)
{
Write_Ds1302_Byte(Write_Time[i],time[i]);
}
Write_Ds1302_Byte(0x8e,0x00);
}
void Read_Ds1302_Time(unsigned char *time)
{
unsigned char i;
for(i = 0;i < 3;i++)
time[i]=Read_Ds1302_Byte(Read_Time[i]);
}
五、演示
六、总结
注意:本代码只是提供读者参考,给读者提供一个方法。
蓝桥杯第十三届单片机省赛的题难度不大,但是要处理的细节比较多,需要细心看题,认真思考。
标签:真题,pos,Nixie,蓝桥,单片机,flag,num,Time,hc From: https://blog.csdn.net/2201_75616203/article/details/137384295