第五届蓝桥杯单片机省赛----程序题

在这里插入图片描述
在这里插入图片描述
注:第六届模拟题即第五届蓝桥杯单片机省赛试题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
功能不多,逻辑也非常简单,相信大家一看便很清楚了,直接上程序,里面包含有注释。

在这里插入图片描述

main.c程序

#include<stc15f2k60s2.h>
#include "ds18b20.h"

#define uchar unsigned char   //定义无符号字符类型uchar
#define uint unsigned int     //定义无符号整型类型uint

uchar code tab[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//数字0~9,“-”,“关”
uchar yi,er,san,si,wu,liu,qi,ba;   //定义字符型变量yi,er,san,si,wu,liu,qi,ba,当作数码管显示控制变量

uchar wendu,qujian=0,num=0,bz=0;
uchar min=20,max=30,tt=0,flog=0,shezhi=0,qingchu=0;

void delayms(int ms);          //延时函数
void allinit();                //初始化函数
void keyscan16();              //矩阵按键函数
void display1(uchar yi,uchar er);   //第一、二段数码管函数
void display2(uchar san,uchar si);  //第三、四段数码管函数
void display3(uchar wu,uchar liu);  //第五、六段数码管函数
void display4(uchar qi,uchar ba);   //第七、八段数码管函数
void Timer0Init(void);		//5毫秒@11.0592MHz

void main()//主函数
{
    
    
	allinit();                  //初始化函数
	Timer0Init();
	yi=1;er=2;san=3;si=4;wu=5;liu=6;qi=7;ba=8;//让数码管依次显示1~8,用来检验数码管显示函数程序是否有误
	while(1)
	{
    
    
		if(shezhi==0)          //非设置状态下
		{
    
    
			wendu=Tempget();       //获取温度
			if(wendu<min){
    
    qujian=0;P2=0XA0;P0=0X00;}   //温度小于设定最小值时在区间0,关继电器
			else if((wendu>=min)&&(wendu<=max)){
    
    qujian=1;P2=0XA0;P0=0X00;}   //温度大于等于设定最小值且小于等于设定最大值时在区间1,关继电器
			if(wendu>max){
    
    qujian=2;P2=0XA0;P0=0X10;}   //温度大于设定最大值时在区间2,开继电器
			
			yi=10;er=qujian;san=10;si=11;wu=11;liu=11;qi=wendu/10;ba=wendu%10;   //温度显示页面
		}
		else if(shezhi==1)              //判断是否在设置状态下
		{
    
    
			if((er==11)&&(bz==1))         //有按键按下且第二个数码管无显示
			{
    
    
				bz=0;er=num;                //把按键标志位清零,然后把按键的值赋给第二个数码管
			}
			else if((san==11)&&(bz==1))   //有按键按下且第三个数码管无显示
			{
    
    
				bz=0;san=num;               //把按键标志位清零,然后把按键的值赋给第三个数码管
			}
			else if((qi==11)&&(bz==1))    //有按键按下且第七个数码管无显示
			{
    
    
				bz=0;qi=num;                //把按键标志位清零,然后把按键的值赋给第七个数码管
			}
			else if((ba==11)&&(bz==1))    //有按键按下且第八个数码管无显示
			{
    
    
				bz=0;ba=num;                //把按键标志位清零,然后把按键的值赋给第八个数码管
				if((er*10+san)<(qi*10+ba)){
    
    P2=0X80;P0=0XFD;}    //判断设定最大值是否小于设定最小值,是的话L2点亮
				else if((er*10+san)>=(qi*10+ba)){
    
    max=er*10+san;min=qi*10+ba;}    //判断设定最大值是否大于或等于设定最小值,是的话赋值
			}
		}
		keyscan16();              //矩阵按键函数
		display1(yi,er);          //第一、二段数码管函数
		display2(san,si);         //第三、四段数码管函数
		display3(wu,liu);         //第五、六段数码管函数
		display4(qi,ba);          //第七、八段数码管函数
	}
}
void keyscan16()//矩阵按键函数
{
    
    
	uchar temp;                 //定义一个无符号变量temp
	P44=0;P42=1;P3=0x7f;        //让第一列按键为低电平
	temp=P3;                    //把P3的值赋给temp
	temp=temp&0x0f;             //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
	if(temp!=0x0f)              //判断第一列是否有按键按下
	{
    
    
		delayms(5);               //延时5ms,用来按键消抖
		temp=P3;                  //把P3的值重新赋给temp
		temp=temp&0x0f;           //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
		if(temp!=0x0f)            //再次判断第一列是否有按键按下
		{
    
    
			temp=P3;                //把P3的值重新赋给temp
			switch(temp)
			{
    
    
				case 0x7e:num=0;bz=1;break;      //第一列第一个按键按下
				case 0x7d:num=3;bz=1;break;      //第一列第二个按键按下
				case 0x7b:num=6;bz=1;break;      //第一列第三个按键按下
				case 0x77:num=9;bz=1;break;      //第一列第四个按键按下
			}
			while(temp!=0x0f)       //无按键按下则进入循环
			{
    
    
				temp=P3;              //把P3的值重新赋给temp
				temp=temp&0x0f;       //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
			}
		}
	}
	P44=1;P42=0;P3=0xbf;        //让第二列按键为低电平
	temp=P3;                    //把P3的值赋给temp
	temp=temp&0x0f;             //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
	if(temp!=0x0f)              //判断第一列是否有按键按下
	{
    
    
		delayms(5);               //延时5ms,用来按键消抖
		temp=P3;                  //把P3的值重新赋给temp
		temp=temp&0x0f;           //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
		if(temp!=0x0f)            //再次判断第一列是否有按键按下
		{
    
    
			temp=P3;                //把P3的值重新赋给temp
			switch(temp)
			{
    
    
				case 0xbe:num=1;bz=1;break;      //第二列第一个按键按下
				case 0xbd:num=4;bz=1;break;      //第二列第二个按键按下
				case 0xbb:num=7;bz=1;break;      //第二列第三个按键按下
				case 0xb7:
					if(shezhi==0)
					{
    
    
						shezhi=1;             //按键按下进入温度设置页面
						EA=0;ET0=0;P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;            //设置状态下关闭继电器和LED灯
						yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11;     //显示设置状态页面
					}	
					else if(shezhi==1)
					{
    
    
						shezhi=0;             //按键按下进入温度显示页面
						EA=1;ET0=1;	          //开定时器中断
					}
					break;      //第二列第四个按键按下
			}
			while(temp!=0x0f)       //无按键按下则进入循环
			{
    
    
				temp=P3;              //把P3的值重新赋给temp
				temp=temp&0x0f;       //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
			}
		}
	}
	P44=1;P42=1;P3=0xdf;        //让第三列按键为低电平
	temp=P3;                    //把P3的值赋给temp
	temp=temp&0x0f;             //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
	if(temp!=0x0f)              //判断第一列是否有按键按下
	{
    
    
		delayms(5);               //延时5ms,用来按键消抖
		temp=P3;                  //把P3的值重新赋给temp
		temp=temp&0x0f;           //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
		if(temp!=0x0f)            //再次判断第一列是否有按键按下
		{
    
    
			temp=P3;                //把P3的值重新赋给temp
			switch(temp)
			{
    
    
				case 0xde:num=2;bz=1;break;      //第三列第一个按键按下
				case 0xdd:num=5;bz=1;break;      //第三列第二个按键按下
				case 0xdb:num=8;bz=1;break;      //第三列第三个按键按下
				case 0xd7:
					if(qingchu==0)
					{
    
    
						qingchu=1;
						yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11;
					}
					else if(qingchu==1)
					{
    
    
						qingchu=0;
						yi=10;er=11;san=11;si=11;wu=11;liu=10;qi=11;ba=11;  
					}
					break;      //第三列第四个按键按下
			}
			while(temp!=0x0f)       //无按键按下则进入循环
			{
    
    
				temp=P3;              //把P3的值重新赋给temp
				temp=temp&0x0f;       //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
			}
		}
	}
}
void Timer0Init(void)		//5毫秒@11.0592MHz
{
    
    
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA=1;ET0=1;   //开定时器中断
}
void time0 () interrupt 1
{
    
    
	tt++;
	if((tt==160)&&(qujian==0))  //判断当前温度是否在区间0,是的话L1以0.8秒为间隔闪烁
	{
    
    
		tt=0;
		if(flog==0){
    
    flog=1;P2=0X80;P0=0XFE;}   
		else if(flog==1){
    
    flog=0;P2=0X80;P0=0XFF;}
	}
	else if((tt==80)&&(qujian==1))  //判断当前温度是否在区间0,是的话L1以0.4秒为间隔闪烁
	{
    
    
		tt=0;
		if(flog==0){
    
    flog=1;P2=0X80;P0=0XFE;}
		else if(flog==1){
    
    flog=0;P2=0X80;P0=0XFF;}
	}
	else if((tt==40)&&(qujian==2))  //判断当前温度是否在区间0,是的话L1以0.2秒为间隔闪烁
	{
    
    
		tt=0;
		if(flog==0){
    
    flog=1;P2=0X80;P0=0XFE;}
		else if(flog==1){
    
    flog=0;P2=0X80;P0=0XFF;}
	}
}
void delayms(int ms)//延时函数
{
    
    
	uint i,j;
	for(i=ms;i>0;i--)
		for(j=845;j>0;j--);
}
void allinit()//初始化函数
{
    
    
	P2=0XA0;P0=0X00;      //关闭蜂鸣器继电器
	P2=0X80;P0=0XFF;      //关闭所有LED灯
	
	P2=0XC0;P0=0XFF;      //选中所有数码管段选
	P2=0XFF;P0=0XFF;      //关闭所有数码管
}
void display1(uchar yi,uchar er)//第一、二段数码管函数
{
    
    
	P2=0XC0;P0=0X01;               //选中第一个数码管位选
	P2=0XFF;P0=tab[yi];            //让第一个数码管显示yi指向的值
	delayms(1);                    //延时1ms
	
	P2=0XC0;P0=0X02;               //选中第二个数码管位选
	P2=0XFF;P0=tab[er];            //让第一个数码管显示er指向的值
	delayms(1);	                   //延时1ms
}
void display2(uchar san,uchar si)//第三、四段数码管函数
{
    
    
	P2=0XC0;P0=0X04;               //选中第s三个数码管位选
	P2=0XFF;P0=tab[san];           //让第一个数码管显示san指向的值
	delayms(1);                    //延时1ms
	
	P2=0XC0;P0=0X08;               //选中第四个数码管位选
	P2=0XFF;P0=tab[si];            //让第一个数码管显示si指向的值
	delayms(1);	                   //延时1ms
}
void display3(uchar wu,uchar liu)//第五、六段数码管函数
{
    
    
	P2=0XC0;P0=0X10;               //选中第五个数码管位选
	P2=0XFF;P0=tab[wu];            //让第一个数码管显示wu指向的值
	delayms(1);                    //延时1ms
	
	P2=0XC0;P0=0X20;               //选中第六个数码管位选
	P2=0XFF;P0=tab[liu];           //让第一个数码管显示liu指向的值
	delayms(1);	                   //延时1ms
}
void display4(uchar qi,uchar ba)//第七、八段数码管函数
{
    
    
	P2=0XC0;P0=0X40;               //选中第七个数码管位选
	P2=0XFF;P0=tab[qi];            //让第一个数码管显示qi指向的值
	delayms(1);                    //延时1ms
	
	P2=0XC0;P0=0X80;               //选中第八个数码管位选
	P2=0XFF;P0=tab[ba];            //让第一个数码管显示ba指向的值
	delayms(1);                    //延时1ms
	P2=0XC0;P0=0X80;               //选中第八个数码管位选
	P2=0XFF;P0=0XFF;               //让第八个数码管熄灭             
}

ds18b20.c程序

#include<stc15f2k60s2.h>
#include "ds18b20.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  
{
    
    
	while(t--);
}


//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
    
    
	unsigned char i;
	for(i=0;i<8;i++)
	{
    
    
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(50);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(50);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
    
    
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
    
    
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
    
    
			dat |= 0x80;
		}	    
		Delay_OneWire(50);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
    
    
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(120);
  	DQ = 0;
  	Delay_OneWire(800);
  	DQ = 1;
  	Delay_OneWire(100); 
    	initflag = DQ;     
  	Delay_OneWire(50);
  
  	return initflag;
}

unsigned char Tempget()
{
    
    
	unsigned char low,high,temp;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=(high<<4);
	temp|=(low>>4);
	
	return temp;
}

ds18b20.h程序

#ifndef __DS18B20_H
#define __DS18B20_H

//单总线延时函数
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned char Tempget();
#endif

在这里插入图片描述

第五届蓝桥杯单片机省赛作品演示

猜你喜欢

转载自blog.csdn.net/qq_45385706/article/details/115175314