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

在这里插入图片描述
在这里插入图片描述
注:第五届模拟题即第四届蓝桥杯单片机省赛试题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对赛题没什么好分析的,跟第三届相比难度差不多,都挺简单的,直接上程序吧,注释也都在程序里标明了。

在这里插入图片描述

main.c程序

#include<stc15f2k60s2.h>
#include "iic.h"
#include "ds1302.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,当作数码管显示控制变量
extern unsigned char shijian[];  //调用DS1302定义时间数组

bit S7=0,S6=0,kai=0,relay=0,jia=0,jian=0;
uchar shidu,fazhi;

void delayms(int ms);          //延时函数
void allinit();                //初始化函数
void keyscan();                //独立按键函数
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 main()//主函数
{
    
    
	allinit();                  //初始化函数
	DS_int();                   //初始化DS1302
	P2=0X80;P0=0XFE;            //打开L1
	fazhi=EEPROM_read(0x20);    //从EEPROM里读取阈值
	while(1)
	{
    
    
		DS_get();                 //调用时钟读取函数
		shidu=AD_read(0x03);      //读取湿度
		if(S7==0)                 //判断是否在自动状态下
		{
    
    
			if(shidu<fazhi){
    
    P2=0XA0;P0=0X10;}   //湿度小于阈值的话继电器打开
			else{
    
    P2=0XA0;P0=0X00;}    //湿度大于或等于阈值的话继电器关闭
			
			if(S6==1){
    
    			        //判断是否在湿度阈值调整页面
				if(jia==1){
    
    jia=0;fazhi=fazhi+1;}    //判断S5按键是否按下,如果是阈值加一
				else if(jian==1){
    
    jian=0;fazhi=fazhi-1;}    //判断S5按键是否按下,如果是阈值减一
				yi=10;er=10;san=11;si=11;wu=11;liu=11;qi=fazhi/10;ba=fazhi%10;    //显示阈值调整页面
			}
			else if(S6==0){
    
            //判断是否在时间与湿度数据显示页面
				yi=shijian[2]/10;er=shijian[2]%10;san=10;si=shijian[1]/10;wu=shijian[1]%10;liu=11;qi=shidu/10;ba=shidu%10;   //显示时间与湿度数据
			}
		}	
		else if(S7==1)            //判断是否在手动状态下         
		{
    
    
			if((shidu<fazhi)&&(kai==0)){
    
           //判断湿度是否小于阈值且蜂鸣器关状态
				if(relay==0){
    
    P2=0XA0;P0=0X00;}    //如果此时继电器关闭,则继电器和蜂鸣器都不工作
				else if(relay==1){
    
    P2=0XA0;P0=0X10;}    //如果此时继电器打开,则打开继电器,蜂鸣器则不工作
			}
			if((shidu<fazhi)&&(kai==1)){
    
           //判断湿度是否小于阈值且蜂鸣器开状态
				if(relay==0){
    
    P2=0XA0;P0=0X40;}    //如果此时继电器关闭,则只打开蜂鸣器
				else if(relay==1){
    
    P2=0XA0;P0=0X50;}    //如果此时继电器打开,则打开继电器和蜂鸣器
			}
			if(shidu>fazhi){
    
           //判断湿度是否大于阈值
				if(relay==0){
    
    P2=0XA0;P0=0X00;}    //判断继电器是否为关状态,如果是关状态,则关闭继电器
				else if(relay==1){
    
    P2=0XA0;P0=0X10;}    //判断继电器是否为开状态,如果是开状态,则开启继电器
			}
			yi=shijian[2]/10;er=shijian[2]%10;san=10;si=shijian[1]/10;wu=shijian[1]%10;liu=11;	qi=shidu/10;ba=shidu%10;   //显示时间与湿度数据
		}
		keyscan();                //独立按键函数
		display1(yi,er);          //第一、二段数码管函数
		display2(san,si);         //第三、四段数码管函数
		display3(wu,liu);         //第五、六段数码管函数
		display4(qi,ba);          //第七、八段数码管函数
	}
}
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;               //让第八个数码管熄灭             
}
void keyscan()//独立按键函数
{
    
    
	if(P30==0)       //判断P30是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P30==0)
		{
    
    
			if(S7==0){
    
    S7=1;P2=0X80;P0=0XFD;}	
			else if(S7==1){
    
    S7=0;P2=0X80;P0=0XFE;}	
		}
		while(!P30);   //如果按键不松开,则一直循环
	}
	else if(P31==0)  //判断P31是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P31==0)
		{
    
    
			if(S7==0){
    
         //判断是否在自动状态下
				if(S6==0){
    
    S6=1;}   //调整状态下按键按下切换为数据显示状态
				else if(S6==1){
    
    S6=0;EEPROM_write(0x20,fazhi);}  //数据显示状态下按键按下切换为调整状态并把阈值保存在EEPROM中
			}	
			else if(S7==1){
    
    kai=~kai;}		//在手动状态下,蜂鸣器状态取反
		}
		while(!P31);   //如果按键不松开,则一直循环
	}
	else if(P32==0)  //判断P32是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P32==0)
		{
    
    
			if(S7==0){
    
    jia=1;}	 //判断是否在自动状态下按键,如果是按键功能为加
			else if(S7==1){
    
    relay=1;}	 //判断是否在手动状态下按键,如果是按键功能为打开继电器
		}
		while(!P32);   //如果按键不松开,则一直循环
	}
	else if(P33==0)  //判断P33是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P33==0)     //再次判断P33是否等于0 
		{
    
    
			if(S7==0){
    
    jian=1;}		 //判断是否在自动状态下按键,如果是按键功能为减
			else if(S7==1){
    
    relay=0;}	 //判断是否在手动状态下按键,如果是按键功能为关闭继电器
		}
		while(!P33);   //如果按键不松开,则一直循环
	}
}

iic.c程序

#include<stc15f2k60s2.h>
#include "intrins.h"
#include "iic.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */


//总线启动条件
void IIC_Start(void)
{
    
    
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    
    
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

//等待应答
bit IIC_WaitAck(void)
{
    
    
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{
    
       
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{
    
     
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    
    
	unsigned char i;
	for(i=0;i<8;i++)
	{
    
       
		if(byt&0x80) 
		{
    
    	
			SDA = 1;
		}
		else 
		{
    
    
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    
    
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{
    
       
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}
unsigned char AD_read(unsigned char add)
{
    
    
	unsigned char temp;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	temp=IIC_RecByte();
	IIC_Stop();
	
	temp=temp*0.39;
	
	return temp;
}
unsigned char EEPROM_read(unsigned char add)
{
    
    
	unsigned char temp;
	
	IIC_Start();
	IIC_SendByte(0xA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0xA1);
	IIC_WaitAck();
	temp=IIC_RecByte();
	IIC_Stop();
	
	return temp;
}
void EEPROM_write(unsigned char add,unsigned char dat)
{
    
    
	IIC_Start();
	IIC_SendByte(0xA0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

ds1302.c程序

#include<STC15F2K60S2.H>
#include <intrins.h>
#include <ds1302.h>

sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302¸´Î»	

unsigned char shijian[]={
    
    0,30,8,0,0,0,0};

void Write_Ds1302_Byte(unsigned  char temp) 
{
    
    
	unsigned char i;
	for (i=0;i<8;i++)     	
	{
    
     
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302( unsigned char address,unsigned char dat )     
{
    
    
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=1;	
   	_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); 
 	Write_Ds1302_Byte(address);	
 	Write_Ds1302_Byte((dat/10<<4)|(dat%10));	/	
 	RST=0; 
}

unsigned char Read_Ds1302 ( unsigned char address )
{
    
    
 	unsigned char i,temp=0x00,dat1,dat2;/
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	Write_Ds1302_Byte(address);
 	for (i=0;i<8;i++) 	
 	{
    
    		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
 	RST=0;
	SCK=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SCK=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SDA=0;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	SDA=1;
	_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	
	dat1=temp/16;
	dat2=temp%16;
	temp=dat1*10+dat2;/
	
	return (temp);			
}

void DS_int(void)
{
    
    
	unsigned char i,add;
	add=0x80;
	Write_Ds1302(0x8e,0x00);
	for(i=0;i<7;i++)
	{
    
    
		Write_Ds1302(add,shijian[i]);
		add=add+2;
	}
	Write_Ds1302(0x8e,0x80);
}

void DS_get(void)
{
    
    
	unsigned char i,add;
	add=0x81;
	Write_Ds1302(0x8e,0x00);
	for(i=0;i<7;i++)
	{
    
    
		shijian[i]=Read_Ds1302(add);
		add=add+2;
	}
	Write_Ds1302(0x8e,0x80);
}

iic.h程序

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 
unsigned char AD_read(unsigned char add);
unsigned char EEPROM_read(unsigned char add);
void EEPROM_write(unsigned char add,unsigned char dat);

#endif

ds1302.h程序

#ifndef __DS1302_H
#define __DS1302_H

void Write_Ds1302_Byte(unsigned  char temp);
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void DS_int();
void DS_get();

#endif

在这里插入图片描述

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

猜你喜欢

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