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

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

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

main.c程序

#include<stc15f2k60s2.h>
#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,0xbf,0xff};//数字0~9,“-”,“关”
uchar yi,er,san,si,wu,liu,qi,ba;   //定义字符型变量yi,er,san,si,wu,liu,qi,ba,当作数码管显示控制变量

uchar mode3[]={
    
    0x7e,0xbd,0xdb,0xe7};
uchar mode4[]={
    
    0xe7,0xdb,0xbd,0x7e};
uchar AD,mode,i=0,shezhi=0,qidong=0,Dj=0,dengji,LEDtime;
uint jiange,tt=0,shezhi_tt=0,LED_TT=0;
bit s4=0;

void delayms(int ms);          //延时函数
void allinit();                //初始化函数
void keyscan16();              //矩阵按键函数
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 Timer0Init(void);		//1毫秒@12.000MHz

void main()
{
    
    
	allinit();
	Timer0Init();
	yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
//	EEPROM_write(0x00,40);delayms(2);EEPROM_write(0x01,1);delayms(2);
	jiange=EEPROM_read(0x00)*10;
	mode=EEPROM_read(0x01);
	while(1)
	{
    
    
		AD=AD_read(0x03);                         //调用IIC驱动里的AD_read函数,利用RB2模拟电压值
		if(AD<64){
    
    dengji=1;LEDtime=2;}            //判断AD的值是否小于64,即小于1.25V,亮度等级位1级,PWM占空比设置为10%左右
		else if((AD>=64)&&(AD<128)){
    
    dengji=2;LEDtime=5;}   //判断AD的值是否大于等于64且小于128,即大于等于1.25V小于2.5V,亮度等级位2级,PWM占空比设置为25%左右
		else if((AD>=128)&&(AD<192)){
    
    dengji=3;LEDtime=10;} //判断AD的值是否大于等于128且小于192,即大于等于2.5V小于3.75V,亮度等级位3级,PWM占空比设置为50%左右
		else if(AD>=192){
    
    dengji=4;LEDtime=19;}             //判断AD的值是否大于等与192,即大于等于3.75V,亮度等级位4级,PWM占空比设置为100%左右
		if(shezhi==0)
		{
    
    
			yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;//数码管全灭
		}
		else if(shezhi==1)   //设置模式编号界面
		{
    
    
			if(jiange>=1000)    //判断流转间隔时间是否大于1000,目的是让流转间隔时间不足4位的让最高位数码管熄灭。
			{
    
    
				if(shezhi_tt<=800){
    
    yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;}
				else {
    
    yi=10;er=11;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;} 
			}
			else 
			{
    
    
				if(shezhi_tt<=800){
    
    yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;}
				else {
    
    yi=10;er=11;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;}
			}
		}
		else if(shezhi==2)   //设置流转间隔界面
		{
    
    
			if(jiange>=1000)    //判断流转间隔时间是否大于1000,目的是让流转间隔时间不足4位的让最高位数码管熄灭。
			{
    
    
				if(shezhi_tt<=800){
    
    yi=10;er=mode;san=10;si=11;wu=jiange/1000;liu=jiange%1000/100;qi=jiange%100/10;ba=jiange%10;}
				else {
    
    yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;} 
			}
			else 
			{
    
    
				if(shezhi_tt<=800){
    
    yi=10;er=mode;san=10;si=11;wu=11;liu=jiange/100;qi=jiange%100/10;ba=jiange%10;}
				else {
    
    yi=10;er=mode;san=10;si=11;wu=11;liu=11;qi=11;ba=11;}
			}
		}
		if(Dj==1)  //亮度等级显示页面
		{
    
    
			yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=10;ba=dengji;
		}
		
		keyscan();                //独立按键函数
		display1(yi,er);          //第一、二段数码管函数
		display2(san,si);         //第三、四段数码管函数
		display3(wu,liu);         //第五、六段数码管函数
		display4(qi,ba);          //第七、八段数码管函数
	}
}
void keyscan()//独立按键函数
{
    
    
	if(P30==0)       //判断P30是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P30==0)     //再次判断P30是否等于0 
		{
    
    
			if(qidong==0)qidong=1;     //判断是否为未启动状态,是的话按键按下后启动
			else if(qidong==1)qidong=0;//判断是否为启动状态,是的话按键按下后停止
		}
		while(!P30);   //如果按键不松开,则一直循环
	}
	else if(P31==0)  //判断P31是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P31==0)     //再次判断P31是否等于0 
		{
    
    
			if(shezhi==0)shezhi=1;        //判断是否在非设置页面,是的话按键按下后进入到设置模式页面
			else if(shezhi==1)shezhi=2;   //判断是否在设置模式页面,是的话按键按下后进入到设置流转间隔页面
			else if(shezhi==2)
			{
    
    
				shezhi=0;
				EEPROM_write(0x00,jiange/10);delayms(2);
				EEPROM_write(0x01,mode);delayms(2);
			}//判断是否在设置流转间隔页面,是的话按键按下后进入到非设置页面,保存模式和流转间隔到EEPROM中
		}
		while(!P31);   //如果按键不松开,则一直循环
	}
	else if(P32==0)  //判断P32是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P32==0)     //再次判断P32是否等于0 
		{
    
    
			if(shezhi==1)  //设置模式页面下按键
			{
    
    
				if(mode==4)mode=4;//判断模式是否等于4,是的话模式还等于4
				else mode=mode+1; //不是的话模式+1
			}
			else if(shezhi==2)  //设置流转间隔页面下按键
			{
    
    
				if(jiange==1200)jiange=1200;//判断流转间隔是否等于1200,是的话模式还等于1200
				else jiange=jiange+100;     //不是的话流转间隔+100
			}
		}
		while(!P32);   //如果按键不松开,则一直循环
	}
	else if(P33==0)  //判断P33是否等于0
	{
    
    
		delayms(5);    //延时5ms
		if(P33==0)     //再次判断P33是否等于0 
		{
    
    
			s4=1;             //s4标志位置1
			if(shezhi==0)Dj=1;//非设置状态下,按键按下进入到等级显示页面
		}
	}
	else if((s4==1)&&(P30==1))
	{
    
    
		s4=0;Dj=0;   		    //s4标志位清零,Dj标志位清零
		if(shezhi==1)       //设置模式页面下按键
		{
    
    
			if(mode==1)mode=1;//判断模式是否等于1,是的话模式还等于1
			else mode=mode-1; //不是的话模式-1
		}
		else if(shezhi==2)  //设置流转间隔页面下按键
		{
    
    
			if(jiange==400)jiange=400;//判断流转间隔是否等于400,是的话模式还等于400
			else jiange=jiange-100;     //不是的话流转间隔-100
		}
	}
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
    
    
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;ET0=1;
}
void time0() interrupt 1
{
    
    
	if(qidong==1)        //启动状态下
	{
    
    
		if(++tt==1)        //tt等于1时流水灯亮,但不开始流水
		{
    
    
			if(mode==1){
    
    P2=0X00;P0=0XFF;P2=0X80;P0=~(0x01<<i);P2=0X00;}        //模式一
			else if(mode==2){
    
    P2=0X00;P0=0XFF;P2=0X80;P0=~(0x80>>i);P2=0X00;}   //模式二
			else if(mode==3){
    
    P2=0X00;P0=0XFF;P2=0X80;P0=mode3[i];P2=0X00;}     //模式三
			else if(mode==4){
    
    P2=0X00;P0=0XFF;P2=0X80;P0=mode4[i];P2=0X00;}     //模式四
		}
		else if(tt==LEDtime)    //到达LEDtime时流水灯熄灭
		{
    
    
			P2=0X00;P0=0XFF;P2=0X80;P0=0XFF;P2=0X00;
		}
		else if(tt==20)       //20ms一个周期
		{
    
    
			tt=0;LED_TT++;      //tt清零,LED_TT++;
			if(LED_TT*20>=jiange) //因为20ms一个周期,所以LED_TT要乘以20到达流转间隔时间,LED灯开始流水
			{
    
    
				LED_TT=0;           //LED_TT清零
				if(mode==1){
    
    i++;if(i>=8)i=0;}       //模式一开始流水
				else if(mode==2){
    
    i++;if(i>=8)i=0;}  //模式二开始流水
				else if(mode==3){
    
    i++;if(i>=4)i=0;}  //模式三开始流水
				else if(mode==4){
    
    i++;if(i>=4)i=0;}  //模式四开始流水
			}
		}
	}
	if(++shezhi_tt==1600)    //定义一个以1600ms为周期的时间,为了实现设置状态下数码管闪烁
	{
    
    
		shezhi_tt=0;       //shezhi_tt清零
	}
}
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<stc15f2k60s2.h>
#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

在这里插入图片描述

第九届蓝桥杯单片机作品演示

猜你喜欢

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