蓝桥杯单片机组第十届省赛代码参考

#include "reg51.h" 
#include "iic.h"

/*****************************独立按键部分************/
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned char keysta[] = {1,1,1,1};
void key_xiaodou();
void key_saomiao();
/*****************************独立按键部分************/

unsigned int count_f = 0; //用来计算NE555的频率  来一个脉冲+1
unsigned int count_out;   //count_f 1s测出来的数值给到count_out 去显示在数码管上

unsigned int res = 0;    //读出AD出来的值
unsigned int res1;   // res 在 state_res = 1时给到res1  不然就给数值2

unsigned char state_res = 0;  // 电压测量模式下 0:显示2v  1:显示测量的电压值

unsigned char state = 1;  //数码管显示状态位

unsigned char LED_on = 1; //LED 开关状态标志位
unsigned char LED_state = 0;  //LED 在开情况下的状态标志位

unsigned char SMG_on = 1; //数码管 开关状态标志位

unsigned char SMG_Value[17] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
                                    0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF}; //0到F到-

unsigned char SMG_buff[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
void close_all(void)
{
	P2 = 0x1f;
	P0 = 0xFF;P2 = (P2 & 0x1F) | 0x80;P2 &= 0x1F;  //关闭LED
	P0 = 0x00;P2 = (P2 & 0x1F) | 0xa0;P2 &= 0x1F;  //关闭蜂鸣器等Y5锁存对应的外设
	P0 = 0x00;P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;  //关闭数码管位选
	P0 = 0xFF;P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;  //关闭数码管段选
}

void Config_PCF8591()   //ADC读取滑动变阻器当前电压值的数字量
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	res = IIC_RecByte();
	IIC_WaitAck();
	IIC_SendAck(0); 
	                
	IIC_Stop();
}

void write_dac(unsigned char add)  //DAC转换
{
	EA=0;
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	IIC_SendByte(0X40);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();	
	IIC_Stop();		
	EA=1;
}

void Init_Timer()  //T0用作计数器  T1设置1ms定时器
{
	TH0 = 0xff;        
	TL0 = 0xff;
	
	TH1 = (65536 - 1000) / 256;        
	TL1 = (65536 - 1000) % 256;
	
	TMOD = 0x16;     //定时器1用方式1,定时;定时器0用方式2,计数
	
  ET0 = 1;
  ET1 = 1;
	EA = 1;
	
	TR0 = 1;
	TR1 = 1;
}

void SMG_shuaxin(void)  //放到中断里刷新去
{
	static unsigned char i = 0;
	P2 = 0x1F;
	switch(i)
	{
	  case 0:P0 = SMG_buff[0];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 1:P0 = SMG_buff[1];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 2:P0 = SMG_buff[2];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 3:P0 = SMG_buff[3];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 4:P0 = SMG_buff[4];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 5:P0 = SMG_buff[5];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 6:P0 = SMG_buff[6];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i++;break;
	  case 7:P0 = SMG_buff[7];P2 = (P2 & 0x1F) | 0xe0;P2 &= 0x1F;
	         P0 = 0x01 << i;  P2 = (P2 & 0x1F) | 0xc0;P2 &= 0x1F;i=0;break;
	}		
}
unsigned char buf[8] = 0;
void SMG_display()//数码管显示函数
{
	unsigned char j;
	if(SMG_on == 1) //数码管工作状态
	{
		if(state == 0)  //在频率测量状态
		{
			SMG_buff[0] = SMG_Value[15]; 
			SMG_buff[1] = 0xFF;
			SMG_buff[2] = 0xFF;
			
//******************** 高位零不显示  *************//		
			buf[7] = count_out%10;
			buf[6] = count_out/10%10;
			buf[5] = count_out/100%10;
			buf[4] = count_out/1000%10;
			buf[3] = count_out/10000%10;
				
								//从最高位开始,遇到0不显示,遇到非0退出循环
								for (j=3;j<=7;j++)
								{
										if (buf[j] == 0)
												SMG_buff[j] = 0xFF;
										else
												break;
								}
								//将剩余的有效数字位如实转换
								for ( ; j<=7; j++)  //for()起始未对j操作,j即保持上个循环结束时的值
								{
										SMG_buff[j] = SMG_Value[buf[j]];
								}
/*************************************************/
		}
		else if(state == 1) //在电压测量状态
		{
			SMG_buff[0] = ~0x3E;
			SMG_buff[1] = 0xFF;
			SMG_buff[2] = 0xFF;
			SMG_buff[3] = 0xFF;
			SMG_buff[4] = 0xFF;
			SMG_buff[5] = SMG_Value[(res1)/100%10]^0x80; //255:5 每一份占0.02v 
			SMG_buff[6] = SMG_Value[(res1)/10%10];
			SMG_buff[7] = SMG_Value[(res1)%10];
		}
  }
	else if(SMG_on == 0) //数码管不工作
	{
			SMG_buff[1] = 0xFF;
			SMG_buff[2] = 0xFF;
			SMG_buff[3] = 0xFF;
			SMG_buff[4] = 0xFF;
			SMG_buff[5] = 0xFF;
			SMG_buff[6] = 0xFF;
			SMG_buff[7] = 0xFF;
			SMG_buff[0] = 0xFF;		
	}
}

/*****************************独立按键部分************/

void key_saomiao() //独立按键扫描
{
	static unsigned char backup[] = {1,1,1,1};
	
	if(keysta[0] != backup[0])
	{
		if(backup[0] == 0)
		{
			//  S7按下弹起  执行代码
			SMG_on++;
			if(SMG_on >= 2)
			{
				SMG_on = 0;
			}
		}
		backup[0] = keysta[0];
	}
	
	if(keysta[1] != backup[1])
	{
		if(backup[1] == 0)
		{
			//  S6按下弹起  执行代码
			LED_on++;
			if(LED_on >= 2)
			{
				LED_on = 0;
			}
		}
		backup[1] = keysta[1];
	}
	
	if(keysta[2] != backup[2])
	{
		if(backup[2] == 0)
		{
			//  S5按下弹起  执行代码
			state_res++;
			if(state_res >= 2)
			{
				state_res = 0;
			}
		}
		backup[2] = keysta[2];
	}
	
	if(keysta[3] != backup[3])
	{
		if(backup[3] == 0)
		{
			//  S4按下弹起  执行代码
			state++;
			if(state >= 2)
			{
				state = 0;
			}
		}
		backup[3] = keysta[3];
	}		
}

void key_xiaodou() //独立按键消抖
{
	static unsigned char keybuf[] = {0xFF,0xFF,0xFF,0xFF};
	static unsigned char i;
	keybuf[0] = (keybuf[0] << 1) | S7;
	keybuf[1] = (keybuf[1] << 1) | S6;
	keybuf[2] = (keybuf[2] << 1) | S5;
	keybuf[3] = (keybuf[3] << 1) | S4;
	
	for(i=0;i<4;i++)
	{
		if((keybuf[i] & 0x0F) == 0x00)
		{
			keysta[i] = 0;
		}
		else if((keybuf[i] & 0x0F) == 0x0F)
		{
			keysta[i] = 1;
		}
	}
}

void LED_Display()  //LED显示
{
	
	if(LED_on == 0)  //LED不工作
	{
		P2 = 0x1F;P0 = 0xFF; P2 = 0x80; P2 = 0x1F;
	}
	else if(LED_on == 1) //LED工作
	{
		if(state == 0) //在频率测量状态下
		{
			if(LED_state == 2)  //处在L4灭的区间内
			{
					P2 = 0x1F;P0 = 0xFD;P2 = 0x80; P2 = 0x1F;
			}
			else if(LED_state == 3) //处在L4亮的区间内
			{
					P2 = 0x1F;P0 = 0xF5;P2 = 0x80; P2 = 0x1F;	
			}
	  }
		else if(state == 1) //在电压测量状态下
		{
			if(state_res == 1) //处在动态测量 L5要亮
			{
				if(LED_state == 0)//处在L3灭的区间
				{
					P2 = 0x1F;P0 = 0xEE;P2 = 0x80; P2 = 0x1F;
				}
				else if(LED_state == 1)//处在L3亮区间
				{
					P2 = 0x1F;P0 = 0xEA;P2 = 0x80; P2 = 0x1F;
				}
		  }
			else  //处在只显示2v的状态
			{
				P2 = 0x1F;P0 = 0xFE;P2 = 0x80; P2 = 0x1F;
			}
		}
	 }
}
/*****************************独立按键部分************/

void Service_T0() interrupt 1
{
	count_f++;
}
unsigned int dat = 0;
unsigned int dat1 = 0;
void Service_T1() interrupt 3
{
	TH1 = (65536 - 1000) / 256;        
	TL1 = (65536 - 1000) % 256;
	dat++;  //用于计1s
	dat1++; //用于计0.5s
	if(dat1 >= 500)
	{
		Config_PCF8591(); //每0.5s读ADC出来的值
		if(state_res == 0)
		{
			res1 = 200;  // 表示2v 数码管第三个显示为个位
		}
		else if(state_res == 1)
		{
			res1 = res*2;//8位ADC 255:5v  数字量没一份占电压为0.0196... 这里当做0.02 放大100倍 直接以整形显示在数码管上 因为数码管第三个显示为个位
		}
		dat1 = 0;
	}
	if(dat >= 1000)
	{
		count_out = count_f; //将1s计数的脉冲总数 给到count_out 用于后面数码管显示  说白了就是1s读一次频率值
		count_f = 0; //计数值置0 准备下一秒计脉冲数
		dat = 0;
		SMG_display(); //数码管数值刷新放到中断里 就是1s刷一次
	}
	SMG_shuaxin();
	key_xiaodou();
	LED_Display(); //LED的显示在放while(1)里会存在微亮的情况 放1ms中断里不会有
	
	write_dac(res);
	
	
	//判断部分 可以单独写一个函数
	if(state == 1) //在电压测量状态
	{
		if((res1 < 150) || ((res1 >= 250)&&(res1 <= 350)))
		{
			LED_state = 0;
		}
		else
		{
			LED_state = 1;
		}
	}
	else if(state == 0) //在频率显示状态
	{
		if((count_out < 1000) || ((count_out >= 5000)&&(count_out<10000)))
		{
			LED_state = 2;
		}
		else 
		{
			LED_state = 3;
		}
	}
		
}
void main()
{
	close_all();
	Init_Timer();
	while(1)
	{
		key_saomiao();
	}
}

以上代码,加上蓝桥官方2021提供的IIC底层文件编译应该没啥问题。bz编写习惯上可能有些陋习。如有错误,望指正。有看不懂的地方也可以提出来。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值