【蓝桥杯单片机第十届真题】

题目:


问题描述

拿到第一眼,我们应该先在脑海中想一想,如何编写代码,建议使用PDF来看题目,可以在上面做标记。

我们可以先开始写一套模板,包括(独立按键、数码管、LED灯、初始化)等,可以在模板的基础上写我们需要完成的程序。

接下来让我们看看基本的代码模板如何写吧

#include <STC15F2K60S2.H>

void choose(u8 channle)         //选择通道
{
	switch(channle)
	{
		case 4:	  //LED
			P2 |= 0x80;
		break;
		case 5:	   //蜂鸣器继电器
			P2 |= 0xa0;
		break;
		case 6:	   //数码管位选
			P2 |= 0xc0;
		break;
		case 7:	   //数码管段选
			P2 |= 0xe0;
		break;
	}
	P2 &= ~0xe0;
}

/*题目中需要独立按键,所以矩阵按键我就不列出来了,有需要的小伙伴可以关注我看矩阵按键的文章*/
u8 key_statue =0;     //独立按键
u8 KEY_scan()
{
	u8 temp =0;   //保存返回的值
	P3 |= 0x0f;     //选取P3,让它后四位拉高电阻输出高电平
	temp = ~P3 & 0x0f; //P3为低电平
	if(temp)
	{
		if(key_statue == 0)
		{
			key_statue = 1;
			return 0;
		}
		else if(key_statue == 1)
		{
			key_statue = 2;
			if(P30 == 0)
			{
				temp = 7;
			}
			if(P31 == 0)
			{
				temp = 6;
			}
			if(P32 == 0)
			{
				temp = 5;
			}
			if(P33 == 0)
			{
				temp = 4;
			}
			
			return temp;

		}
		else if(key_statue == 2)
		{
			 return 0;
		}	
	}
	else 
	{
		key_statue =0;
		return 0;
	}
	return 0;
}

/*************  本地常量声明    **************/
u8 code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //

u8 P_SMG = 0;   // 15是F,题目中要求第一个显示F
u8 SMGs1[8]={15,16,16,16,16,16,16,16};	//频率      通过题目要求,我们知道数码管有2种显示方式
//25显示U
u8 SMGs2[8]={25,16,16,16,16,16,16,16};  //电压  //16是不显示,为了不让数码管混乱,我们采取16  
u8 *SMGs = SMGs1;         //指针,用于数码管的切换,我们先默认为SMGs1        

void SMGs_show()
{

	
	P0 = 0x00;
	choose(6);
		
	P0 = ~t_display[SMGs[P_SMG]];
	choose(7);

    P0 = T_COM[P_SMG];
	choose(6);
	
	if(++P_SMG>=8)
	{
		P_SMG = 0;
	}
	
}

u8 led_statue = 0x00;   //定义一个变量,便于后面更改
void LED()
{
		
	P0 = ~led_statue;     //取返,LED灯全灭
	choose(4);            
}

/*****************接下来我们采用定时器的方式,用于读取LED、数码管************/

u16 cnt_1s =0;
u8 cnt_100ms =0;
void timer0isr() interrupt 3
{
	 LED();
	SMGs_show();
	cnt_1s++;
	cnt_100ms++;
}



进一步编写:

有了基本的代码,我们可以进一步的来写。

/***********8题目中有N555测频率,我们先来完成它**************/

void Timer0Init(void)		
{
	AUXR |= 0x80;		
	TMOD &= 0xF0;  
	TMOD |= 0x04;		
	TL0 = 0x00;		
	TH0 = 0x00;		
	TF0 = 0;		
	TR0 = 1;		

}
	u16 freq = 0;  //频率
/*根据之前写的,我们修改一下*/
void timer0isr() interrupt 3
{
	u16 temp;    //temp来保存频率的值
	 LED();
	SMGs_show();
	cnt_1s++;
	cnt_100ms++;

	if(cnt_1s >= 1000)   
	{
		cnt_1s = 0;
		TR0 = 0;           
		
		temp  = TH0;   //合成一个int的函数
		temp <<= 8;
		temp |= TL0;

		TL0 = 0x00;	
		TH0 = 0x00;
			
		TR0 = 1;
		freq = temp;    
	}
}

void main()	
{
	u8 key_vaule = 0;
	u8 temp = 0;
	u8 disp_mode = 1; // 0<- 频率 1<-电压


	P2 = 0x00;   //初始化(LED、蜂鸣器,继电器)

   P0 = 0x00;
	choose(5);
	
	P0 = 0xff;
	choose(4); 

	Timer1Init();
   Timer0Init();
   
    while(1)
	{
		if(cnt_100ms >=10)
		{
			cnt_100ms = 0;

			/*  输入 */
			key_vaule = KEY_scan();
			

			/*  处理 */
			if(key_vaule == 4)   //按键切换模式
			{
				disp_mode = !disp_mode;	
			}

			if(disp_mode == 0)    
			{
				SMGs = SMGs1;      

				if(freq >= 100000)       //未用到的数码管位将不显示
				SMGs1[2] = freq / 100000;
				else
					SMGs1[2] = 16;
				if(freq >= 10000)
					SMGs1[3] = freq / 10000 % 10;
				else
					SMGs1[3] = 16;
				if(freq >= 1000)
					SMGs1[4] = freq / 1000 % 10;
				else
					SMGs1[4] = 16;
				if(freq >= 100)
					SMGs1[5] = freq / 100 % 10;
				else
					SMGs1[5] = 16;
				if(freq >= 10)
					SMGs1[6] = freq / 10 %10;
				else
					SMGs1[6] = 16;
				SMGs1[7] = freq % 10;
			}

			else
			{
			   //暂时不写
			}

			
			
		}
	}
}
/**************************接下来我们写入电压**********************/
void main()	
{
	u8 key_vaule = 0;
	u16 volt = 0;  //保存100倍电压
	u8 temp = 0;
	u8 disp_mode = 1; // 0<- 频率 1<-电压
   	u8 out_mode = 0; // 0<- 固定 1<-可变

	P2 = 0x00;

   P0 = 0x00;
	choose(5);
	
	P0 = 0xff;
	choose(4); 

	Timer1Init();
   Timer0Init();
   
    while(1)
	{
		if(cnt_100ms >=10)
		{
			cnt_100ms = 0;

			/*  输入 */
			key_vaule = KEY_scan();
			temp = read_8591();               //temp来保存读取的值
			volt = (float)read_8591() / 255.0f * 500.0f;

			/*  处理 */
			if(key_vaule == 4)
			{
				disp_mode = !disp_mode;	
			}
			if(key_vaule == 5)
			{
				out_mode = !out_mode;	
			} 
			
			/*  输出 */
			if(out_mode == 0)       //测量电压值,0为固定,L1灭
			{
				write_8591(102);//2V
				led_statue &= ~0x10; 	
			}
			else
			{
				 write_8591(temp);  //测量电压值,1为随数码管的值变化,电压变化,L1亮
				 led_statue |= 0x10; 
			}
			//write_8591(temp);
			if(disp_mode == 0)
			{
				//上文频率
			}

			else
			{
			   	SMGs = SMGs2;         //电压显示
				SMGs2[5] = volt / 100 +32;
				SMGs2[6] = volt / 10 %10;
				SMGs2[7] = volt % 10;
			}

			if(disp_mode == 0)	//频率        //根据题意,我们知道LED灯的亮灭
			{
				led_statue |= 0x02;	   //L2亮    
				led_statue &= ~0x01;   //L1灭	  	
			}
			else      //电压
			{
				led_statue |= 0x01;	   //L1亮
				led_statue &= ~0x02;   //L2灭	
			}
			
		}
	}
}

/*********************************LED、数码管*****************/
u8 led_en = 1;
u8 smg_en = 1;

void SMGs_show()
{

	
	P0 = 0x00;
	choose(6);

	if(!smg_en)         //按键让LED
	{
		return;
	}
		
	P0 = ~t_display[SMGs[P_SMG]];
	choose(7);

    P0 = T_COM[P_SMG];
	choose(6);
	
	if(++P_SMG>=8)
	{
		P_SMG = 0;
	}
	
}

写到这里基本上快写完了,剩下的LED灯我们也快速完成它

if(volt <150 || (volt >= 250 && volt < 350)) 
			{
				led_statue &= ~0x04; 
			}
			else
			{
				led_statue |= 0x04; 
			}

			if(freq <1000 || (freq >= 5000 && freq < 10000))
			{
				led_statue &= ~0x08;	
			}
			else
			{
				led_statue |= 0x08; 
			}


最后我们写入IIC—8591的驱动文件

u8 read_8591()
{
	u8 temp = 0;

	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();

	IIC_SendByte(0x43);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();

	IIC_RecByte();
	IIC_SendAck(0);
	temp = IIC_RecByte();
	IIC_SendAck(1);

	IIC_Stop();
	return temp;
}

void write_8591(u8 level)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(0x40);
	IIC_WaitAck();
	
	IIC_SendByte(level);
	IIC_WaitAck();	

	IIC_Stop();
}

本文结束了,大家多看看,总的来说还是挺简单的,本题涉及到N555、PCF8591、数码管、独立按键主要的模块,大家还需要掌握最基础的LED,单个模块还算简单,组合一起就需要大家思考思考了。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值