第十一届蓝桥杯单片机组省赛赛题

题目在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

程序

官方已给出的底层驱动代码就不再陈列,其中iic.c文件的IIC_Delay函数以及iic.h文件需要做一些更改,已经给出。

iic.h

这里由于工程用不到IIC_SendAck函数,就将其注释掉,这样编译器就不会报warning。

#ifndef __IIC_H_
#define __IIC_H_

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
//void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

unsigned char adc_pcf(void);
void eeprom_wr(unsigned char adr,unsigned char date);
unsigned char eeprom_re(unsigned char adr);

#endif

iic.c

#include "intrins.h"

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

unsigned char adc_pcf(void)
{
	unsigned char date;
	
	IIC_Start();
	
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x43);
	IIC_WaitAck();
	
	IIC_Start();
	
	IIC_SendByte(0x91);
	IIC_WaitAck();
	date = IIC_RecByte();
	IIC_WaitAck();
	
	IIC_Stop();
	
	return date;
}

void eeprom_wr(unsigned char adr,unsigned char date) 
{
	EA = 0;
	
	IIC_Start();
	
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(adr);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	
	IIC_Stop();
	
	EA = 1;
}

unsigned char eeprom_re(unsigned char adr)
{
	unsigned char date;
	
	EA = 0;
	
	IIC_Start();
	
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(adr);
	IIC_WaitAck();
	
	IIC_Start();
	
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	date = IIC_RecByte();
	IIC_WaitAck();
	
	IIC_Stop();
	
	EA = 1;
	
	return date;
}

other.h

主要存放了关闭外设,数码管驱动,定时器初始化,按键扫描,延时函数。

#ifndef __OTHER_H_
#define __OTHER_H_

#include <stc15f2k60s2.h>

void Delay2ms(void);
unsigned char seg_tran(int number);
void seg_disp(int adr,int number);
void seg_disp_f(int adr,int number);
int key_scan(void);
void close_perl(void);
void Timer0Init(void);

#endif

other.c

#include <other.h>

void Delay2ms(void)		//@11.0592MHz
{
	unsigned char i, j;

	i = 22;
	j = 128;
	do
	{
		while (--j);
	} while (--i);
}

unsigned char seg_tran(int number)
{
	unsigned char date;
	switch(number)
	{
		case	0	:	date = 	0xc0	;	break;
		case	1	:	date = 	0xf9	;	break;
		case	2	:	date = 	0xa4	;	break;
		case	3	:	date = 	0xb0	;	break;
		case	4	:	date = 	0x99	;	break;
		case	5	:	date = 	0x92	;	break;
		case	6	:	date = 	0x82	;	break;
		case	7	:	date = 	0xf8	;	break;
		case	8	:	date = 	0x80	;	break;
		case	9	:	date = 	0x90	;	break;
		case	10	:	date = 	0xbf	;	break;//-
		case	11	:	date = 	0xc6	;	break;//c
		case	12	:	date = 	0x8c	;	break;//p
		case	13	:	date = 	0x86	;	break;//e
		case	14	:	date = 	0xc7	;	break;//L
		case 	15	:	date = 	0xc8	;	break;//a
		case 	16	:	date = 	0xc1	;	break;//U
	}
	return date;
}

void seg_disp(int adr,int number)
{
    unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

    P2 = P2&0x1f|0xe0;
    P2 = P2&0x1f;
    P0 = seg_adr[adr];

    P2 = P2&0x1f|0xc0;
    P2 = P2&0x1f;
    P0 = seg_tran(number);

    P2 = P2&0x1f|0xe0;
    P2 = P2&0x1f;
}

void seg_disp_f(int adr,int number)
{
	unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
	P0 = seg_adr[adr];
	
	P2 = P2&0x1f|0xc0;
	P2 = P2&0x1f;
	P0 = seg_tran(number)&0x7f;
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
}	

int key_scan(void)
{
	int key,key_mark;
	P3 = 0x0f;
	
	P44 = 0;P42 = 1;P35 = 1;P34 = 1;
	key = P3;
	P44 = 1;P42 = 0;
	key = (key<<4)|(P3&0x0f);
	P42 = 1;P35 = 0;
	key = (key<<4)|(P3&0x0f);
	P35 = 1;P34 = 0;
	key = (key<<4)|(P3&0x0f);
	
	switch(~key)
	{
		case 0x8000: key_mark = 4;break; 
		case 0x4000: key_mark = 5;break; 
		case 0x2000: key_mark = 6;break; 
		case 0x1000: key_mark = 7;break; 
		case 0x0800: key_mark = 8;break; 
		case 0x0400: key_mark = 9;break; 
		case 0x0200: key_mark = 10;break; 
		case 0x0100: key_mark = 11;break; 
		case 0x0080: key_mark = 12;break; 
		case 0x0040: key_mark = 13;break; 
		case 0x0020: key_mark = 14;break; 
		case 0x0010: key_mark = 15;break; 
		case 0x0008: key_mark = 16;break; 
		case 0x0004: key_mark = 17;break; 
		case 0x0002: key_mark = 18;break; 
		case 0x0001: key_mark = 19;break; 
		default    : key_mark = 0 ;break;//这句很重要,必须有!
	}
	return key_mark;
}

void close_perl(void)
{
	P0 = 0xff;
	P2 = P2&0x1f|0x80;
	P2 = P2&0x1f;
	
	P0 = 0x00;
	P2 = P2&0x1f|0xa0;
	P2 = P2&0x1f;
}

void Timer0Init(void)		//10毫秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}

main.c

#include <other.h>
#include <iic.h>

#define Led1 0x01
#define Led2 0x02
#define Led3 0x04

unsigned int key_nosymbol = 0;
unsigned int count;
unsigned int p_bigger_times;

unsigned char key_old;

unsigned char show_mode;

int c_vol_100 = 0;
int c_vol_10;
int vol_100;
float vol_f;
unsigned char adc;
bit count_on;
bit led1_ok;

void key_pro(void)
{
	unsigned char key_down,key_vol;
	
	key_vol = key_scan();
	key_down = key_vol&(key_vol^key_old);
	key_old = key_vol;
	
	switch(key_down)
	{
		case 12:
			show_mode ++;
			if(show_mode == 3)	
			{
				show_mode = 0;
				eeprom_wr(0x00,c_vol_10);
			}
			key_nosymbol = 0;
		break;
		
		case 13:
			if(show_mode == 2)	
			{
				count = 0;
				key_nosymbol = 0;
			}
			else key_nosymbol ++;
		break;
		
		case 16:
			if(show_mode == 1)	
			{
				c_vol_100 = c_vol_100 + 50;
				if(c_vol_100 == 550)	c_vol_100 = 0;
				key_nosymbol = 0;
			}
			else
				key_nosymbol ++;
		break;
		
		case 17:
			if(show_mode == 1)	
			{
				c_vol_100 = c_vol_100 - 50;
				if(c_vol_100 < 0)	c_vol_100 = 500;
				key_nosymbol = 0;
			}
			else
				key_nosymbol ++;
		break;
	}
}

void seg_pro(void)
{
	adc = adc_pcf();
	vol_f = (float)adc/255*5.00;
	vol_100 = vol_f*100;
	c_vol_10 = c_vol_100/10;
	
	if((count_on == 1)&&(vol_100 <= c_vol_100))
	{
		count = count + 1;
		count_on = 0;
	}
	else count_on = 0;
	
	if(vol_100 > c_vol_100)
	{
		count_on = 1;
	}
	seg_disp(1,count_on);Delay2ms();
	switch(show_mode)
	{
		case 0:
			seg_disp(0,16);	Delay2ms();
			seg_disp_f(5,vol_100/100);	Delay2ms();
			seg_disp(6,vol_100%100/10);	Delay2ms();
			seg_disp(7,vol_100%10);	Delay2ms();
		break;
		
		case 1:
			seg_disp(0,12);	Delay2ms();
			seg_disp_f(5,c_vol_100/100);	Delay2ms();
			seg_disp(6,c_vol_100%100/10);	Delay2ms();
			seg_disp(7,c_vol_100%10);	Delay2ms();
		break;
		
		case 2:
			seg_disp(0,15);	Delay2ms();
			if(count > 1000)	seg_disp(4,count/1000);	Delay2ms();
			if(count > 100)	seg_disp(5,count%1000/100);	Delay2ms();
			if(count > 10)	seg_disp(6,count%100/10);	Delay2ms();
			seg_disp(7,count%10);	Delay2ms();
		break;
	}
}

void led_pro(void)
{
	P0 = 0xff;
	
	if(count%2 != 0)	//计数值为奇数时,L2亮
	{
		P0 = P0&(~Led2);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
	}
	else
	{
		P0 = P0|(Led2);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
	}
	
	if(led1_ok == 1)	//p > can 超过5s led1亮
	{
		P0 = P0&(~Led1);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
		p_bigger_times = 0; 
	}
	else
	{
		P0 = P0|(Led1);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
	}
	
	if(key_nosymbol == 3)
	{
		P0 = P0&(~Led3);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
	}
	else
	{
		P0 = P0|(Led3);
		P2 = P2&0x1f|0x80;
		P2 = P2&0x1f;
	}
}

void main(void)
{
	Timer0Init();
	close_perl();
	c_vol_100 = eeprom_re(0x00)*10;
	while(1)
	{
		key_pro();
		seg_pro();
		led_pro();
	}
}

void timer0(void) interrupt 1
{
	if(vol_100 > c_vol_100)
	{
		p_bigger_times ++;
		if(p_bigger_times >= 500)
		{
			led1_ok = 1;
		}
	}
	else	
	{
		led1_ok = 0;
		p_bigger_times = 0;
	}
}

由于图快,就没有写注释,有问题或者觉得哪里写的不完美可以在评论区直接提出或私信,本小白csdn常在线。

  • 8
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值