第十一届蓝桥杯单片机省赛(第一场)----程序题

在这里插入图片描述
在这里插入图片描述

第十一届蓝桥杯单片机省赛(第一场)----程序题_第1张图片
第十一届蓝桥杯单片机省赛(第一场)----程序题_第2张图片
第十一届蓝桥杯单片机省赛(第一场)----程序题_第3张图片
第十一届蓝桥杯单片机省赛(第一场)----程序题_第4张图片
在这里插入图片描述
main.c程序

#include
#include "iic.h"

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

uchar code tab[]={
     0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,//0~9数字
                  0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10,//0~9数字带小数点
                  0XBF,0XFF,0XC1,0X8C,0XC8};//“-”“关”“U”“P”“N”
uchar temp,L1=0;
uchar yi,er,san,si,wu,liu,qi,ba;

uint dianya,Vp,trie=0,jishu=0,dianya_tt=0;
uchar yemian=0,key_no=0;
bit bz=0,L1_kai=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毫秒@12.000MHz
									
void main()
{
     
	allinit();                  //初始化函数
	Timer0Init();               //初始化定时器0
	Vp=EEPROM_read(0x00)*10;    //从EEPROM中读取电压参数
	while(1)
	{
     
		if((dianya_tt==10)||(dianya_tt==20))  //电压采样
		{
     
			dianya=AD_read(0x03)*1.961;
		}
		if(yemian==0)       //数据界面
		{
     
			yi=22;er=21;san=21;si=21;wu=21;liu=dianya/100+10;qi=dianya%100/10;ba=dianya%10;
		}
		else if(yemian==1)  //参数界面
		{
     
			yi=23;er=21;san=21;si=21;wu=21;liu=Vp/100+10;qi=Vp%100/10;ba=Vp%10;
		}
		else if(yemian==2)  //计数界面
		{
     
			if(jishu>=1000000){
     yi=24;er=jishu/1000000;san=jishu%1000000/100000;si=jishu%100000/10000;wu=jishu%10000/1000;liu=jishu%1000/100;qi=jishu%100/10;ba=jishu%10;}
			else if(jishu>=100000){
     yi=24;er=21;san=jishu/100000;si=jishu%100000/1000;wu=jishu%10000/1000;liu=jishu%1000/100;qi=jishu%100/10;ba=jishu%10;}
			else if(jishu>=10000){
     yi=24;er=21;san=21;si=jishu/10000;wu=jishu%10000/1000;liu=jishu%1000/100;qi=jishu%100/10;ba=jishu%10;}
			else if(jishu>=1000){
     yi=24;er=21;san=21;si=21;wu=jishu/1000;liu=jishu%1000/100;qi=jishu%100/10;ba=jishu%10;}
			else if(jishu>=100){
     yi=24;er=21;san=21;si=21;wu=21;liu=jishu/100;qi=jishu%100/10;ba=jishu%10;}
			else if(jishu>=10){
     yi=24;er=21;san=21;si=21;wu=21;liu=21;qi=jishu/10;ba=jishu%10;}
			else if(jishu>=0){
     yi=24;er=21;san=21;si=21;wu=21;liu=21;qi=21;ba=jishu;}
		}
		
		if(dianya<Vp){
     L1=1;}   //判断什么时候L1灯亮
		else {
     L1=0;trie=0;}
		
		if(L1_kai==1){
     P2=0X80;P0&=0XFE;}   //控制L1熄灭/亮起状态
		else if(L1_kai==0){
     P2=0X80;P0|=0X01;}
		
		if(dianya>Vp)bz=1;   //下降沿计数
		if(bz==1){
     if(dianya<=Vp){
     bz=0;jishu=jishu+1;}}
		
		if(jishu%2==1){
     P2=0X80;P0&=0XFD;} //奇数时L2灯亮,否则熄灭
		else {
     P2=0X80;P0|=0X02;}
		
		if(key_no>=3){
     P2=0X80;P0&=0XFB;}   //无效按键判断次数,控制L3灯熄灭/亮起状态
		else {
     P2=0X80;P0|=0X04;}
		
		keyscan16();              //矩阵按键函数
		display1(yi,er);          //第一、二段数码管函数
		display2(san,si);         //第三、四段数码管函数
		display3(wu,liu);         //第五、六段数码管函数
		display4(qi,ba);          //第七、八段数码管函数
	}
}
void Timer0Init(void)		//5毫秒@12.000MHz
{
     
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xA0;		//设置定时初值
	TH0 = 0x15;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA = 1;ET0 = 1;
}
void time0() interrupt 1
{
     
	if(L1==1)                //L1灯亮起标志
	{
     
		if(++trie==1000)       //延时5秒钟
		{
     
			trie=0;L1_kai=1;
		}
	}
	else if(L1==0)          //L1灯关闭标志
	{
     
		L1_kai=0;
	}
	if(++dianya_tt==20)  //电压采样时间
	{
     
		dianya_tt=0;
	}
}
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:key_no=key_no+1;break;      //第一列第一个按键按下,无效按键次数加1
				case 0x7d:key_no=key_no+1;break;      //第一列第二个按键按下,无效按键次数加1
				case 0x7b:key_no=key_no+1;break;      //第一列第三个按键按下,无效按键次数加1
				case 0x77:key_no=key_no+1;break;      //第一列第四个按键按下,无效按键次数加1
			}
			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:key_no=key_no+1;break;      //第二列第一个按键按下,无效按键次数加1
				case 0xbd:key_no=key_no+1;break;      //第二列第二个按键按下,无效按键次数加1
				case 0xbb:key_no=key_no+1;break;      //第二列第三个按键按下,无效按键次数加1
				case 0xb7:key_no=key_no+1;break;      //第二列第四个按键按下,无效按键次数加1
			}
			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:key_no=key_no+1;break;      //第三列第一个按键按下,无效按键次数加1
				case 0xdd:key_no=key_no+1;break;      //第三列第二个按键按下,无效按键次数加1
				case 0xdb:
					key_no=0;jishu=0;         //无效按键次数清零,计数清零
				break;
				case 0xd7:
					key_no=0;    //数据界面进入到参数界面
					if(yemian==0)yemian=1;    //数据界面进入到参数界面
					else if(yemian==1){
     yemian=2;EEPROM_write(0x00,Vp/10);delayms(2);}    //参数界面进入到计数界面,把电压参数保存到EEPROM中
					else if(yemian==2){
     yemian=0;}  //计数界面进入到数据界面
				break;
			}
			while(temp!=0x0f)       //无按键按下则进入循环
			{
     
				temp=P3;              //把P3的值重新赋给temp
				temp=temp&0x0f;       //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
			}
		}
	}
	P44=1;P42=1;P3=0xef;        //让第四列按键为低电平
	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 0xee:key_no=key_no+1;break;      //第四列第一个按键按下,无效按键次数加1
				case 0xed:key_no=key_no+1;break;      //第四列第二个按键按下,无效按键次数加1
				case 0xeb:
					key_no=0;                //数据界面进入到参数界面
					if(yemian==1)
					{
     
						if(Vp<=0)Vp=500;
						else Vp=Vp-50;       //每次按键后电压参数-0.5V
					}
				break;
				case 0xe7:
					key_no=0;                //数据界面进入到参数界面
					if(yemian==1)
					{
     
						if(Vp>=500)Vp=0;
						else Vp=Vp+50;       //每次按键后电压参数+0.5V
					}
				break;
			}
			while(temp!=0x0f)       //无按键按下则进入循环
			{
     
				temp=P3;              //把P3的值重新赋给temp
				temp=temp&0x0f;       //把temp的值和0x0f相与,得到的值再赋给temp,依次来判断第一列是否有按键按下
			}
		}
	}
}
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;               //让第八个数码管熄灭             
}

iic.c程序

#include
#include "iic.h"
#include "intrins.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();
	
	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();
}

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

在这里插入图片描述

第十一届蓝桥杯单片机(第一场)作品演示

你可能感兴趣的:(《蓝桥杯》系列,蓝桥杯,单片机)