第十二届蓝桥杯单片机省赛题目解析

也是刚刚把这个题目做完,让我们一起来看看2021年的题目吧,有什么不对的地方,还希望大家指正。

题目

首先依旧还是三大模块(数码管、LED、按键) ,还有DS18B20,DA输出。写了有一些省赛题了,每次考的都是这些东西,只要平常每个模块都有练习过,应该是不难的。我发现从2020年开始,虽然还是用四个按键,但是变成了矩阵按键,之前都是独立按键。

1 数码管显示

数码管有温度显示,参数设置和DA输出三个界面,通过s4来切换。

2 LED

当在模式1状态时L1亮,数码管处于温度显示界面时L2亮,参数设置界面时L3亮,DA输出界面时L4亮。

3 按键模块

使用的是矩阵键盘,s4是三个界面的切换,s8,s9是温度参数加减1,这里有个小坑就是设定的温度参数只有在退出参数设置界面时才生效,这就要定义两个温度参数的变量,一个是用来在温度参数加减的,在退出温度参数界面时赋值给另一个变量,另一个是用来和实时温度比较大小的。s5有两个模式,模式一 实时温度小于温度参数DA输出0v,否则输出5v。模式二 按照图所给的关系输出电压。

4 DS18B20

就是改写底层驱动代码部分(onewire),然后放在定时器中,每隔一段时间读取一次。

5 DAC

就是改写底层驱动代码部分(IIC)。

onewire.c

#include"onewire.h"

sbit DQ = P1^4;  

void Delay_OneWire(unsigned int t)  
{
	t*=12;
	while(t--);
}

void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

unsigned int Get_temp()
{
	unsigned int result;
	unsigned char high,low;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	result=(high<<8)|low;
	result*=6.25;
	return result;
}

onewire.h

#ifndef _ONEWIRE_H_
#define _ONEWIRE_H_

#include<stc15f2k60s2.h>

void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
unsigned int Get_temp();

#endif

IIC.c

#include"IIC.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

sbit SDA = P2^1;  
sbit SCL = P2^0; 

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

void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

void DA_out(unsigned char date)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(date);
	IIC_WaitAck();
	IIC_Stop();
}

IIC.h

#ifndef _IIC_H_
#define _IIC_H_

#include<stc15f2k60s2.h>
#include<intrins.h>

void IIC_Delay(unsigned char i);
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendByte(unsigned char byt);
void DA_out(unsigned char date);

#endif

init.c

#include"init.h"

#define u8 unsigned char 
#define u16 unsigned int
#define state_0 0
#define state_1 1
#define state_2 2
	
u8 code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88};
u8 seg[]={11,11,11,11,11,11,11,11};
static u8 segaddr=0;
u8 value=0;
extern u8 mode;

void all_init()    //关闭无关外设
{
	P2=(P2&0x1f)|0x80;P0=0xff;P2&=0x1f;
	
	P2=(P2&0x1f)|0xa0;P04=0;P06=0;P2&=0x1f;
	
	P2=(P2&0x1f)|0xc0;P0=0x00;P2&=0x1f;
	
	P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
}

void display()     //数码管显示函数
{
	P2=(P2&0x1f)|0xe0;P0=0xff;P2&=0x1f;
	
	P2=(P2&0x1f)|0xc0;P0=1<<segaddr;P2&=0x1f;
	
	if(mode!=2&&segaddr==5)
	{
		P2=(P2&0x1f)|0xe0;P0=tab[seg[segaddr]]&0x7f;P2&=0x1f;
	}
	else
	{
		P2=(P2&0x1f)|0xe0;P0=tab[seg[segaddr]];P2&=0x1f;
	}
	if(++segaddr==8)segaddr=0;
}

u8 Read_key()    //矩阵键盘
{
	static u8 key_press,key_num=0,key_state=0;
	key_press=P3&0x0f;
	switch(key_state)
	{
		case state_0:
			if(key_press!=0x0f)
				key_state=state_1;
		break;
		case state_1:
			if(key_press!=0x0f)
			{
				if((key_press & 0x08)==0) key_num=4;
				if((key_press & 0x04)==0) key_num=5;
				if((key_press & 0x02)==0) key_num=6;
				if((key_press & 0x01)==0) key_num=7;
				key_state=state_2;
			}
			else
				key_state=state_0;
		break;
		case state_2:
			if(key_press==0x0f)
				key_state=state_0;
		break;
	}
	value=key_num;
	key_num=0;
	return value;
}

void Timer0Init(void)		
{
	AUXR |= 0x80;		
	TMOD &= 0xF0;		
	TL0 = 0xCD;		
	TH0 = 0xD4;		
	TF0 = 0;		
	TR0 = 1;
  ET0 = 1;
  EA = 1;	
}

init.h

#ifndef _INIT_H_
#define _INIT_H_

#include<stc15f2k60s2.h>

void all_init();
void display();
unsigned char Read_key();
void Timer0Init(void);

#endif

jm.c

#include"jm.h"
#include"IIC.h"

#define u8 unsigned char 
#define u16 unsigned int
	
u16 TT=2500,TF=2500;
	
extern u8 mode,seg[];             // extern表示此变量是在别处定义的,要在此处引用
extern u16 temp,RB2;
extern bit MS;

void jm4()
{
	if(mode==1)               //温度显示界面
	{
		seg[0]=12;
		seg[1]=11;
		seg[2]=11;
		seg[3]=11;
		seg[4]=temp/1000;
		seg[5]=temp/100%10;
		seg[6]=temp/10%10;
		seg[7]=temp%10;
	}
	else if(mode==2)          //参数设置界面
	{
		seg[0]=13;
		seg[1]=11;
		seg[2]=11;
		seg[3]=11;
		seg[4]=11;
		seg[5]=11;
		seg[6]=TF/1000;
		seg[7]=TF/100%10;
	}
	else if(mode==3)        //DA输出界面
	{
		seg[0]=14;
		seg[1]=11;
	  seg[2]=11;
		seg[3]=11;
		seg[4]=11;
		seg[5]=RB2/100;
		seg[6]=RB2/10%10;
		seg[7]=RB2%10;
	}
}

void jm5()            //模式切换函数
{
	if(MS==0)
	{
		if(temp<TT)
		{
			DA_out(0);
			RB2=0;
		}
		else
		{
			DA_out(255);
			RB2=500;
		}
	}
	else
	{
		if(temp<=2000)
		{
			DA_out(51);
			RB2=100;
		}
		else if(temp>2000&&temp<=4000)
		{
			DA_out((0.15*temp-200)*0.51);
			RB2=(u16)(0.15*temp-200);
		}
		else
		{
			DA_out(204);
			RB2=400;
		}
	}
}

void jm8()
{
	if(mode==2)TF-=100;
}

void jm9()
{
	if(mode==2)TF+=100;
}

void LED()           //LED显示函数
{
	u8 i=0xff;
	if(MS==0)
	{
		P2=(P2&0x1f)|0x80;P0=i&0xfe;P2&=0x1f;
	}
	else
	{
		P2=(P2&0x1f)|0x80;P0=i|0x01;P2&=0x1f;
	}
	if(mode==1)
	{
		P2=(P2&0x1f)|0x80;P0=i&0xfd;P2&=0x1f;
	}
	else if(mode==2)
	{
		P2=(P2&0x1f)|0x80;P0=i&0xfb;P2&=0x1f;
	}
	else if(mode==3)
	{
		P2=(P2&0x1f)|0x80;P0=i&0xf7;P2&=0x1f;
	}
}

jm.h

#ifndef _JM_H_
#define _JM_H_

#include<stc15f2k60s2.h>

void jm4();
void jm5();
void jm8();
void jm9();
void LED();

#endif

main.c

#include"init.h"
#include"jm.h"
#include"onewire.h"
#include"IIC.h"

#define u8 unsigned char 
#define u16 unsigned int
	
u8 num=0,temp_count=0;
u8 mode=1;
u16 temp,RB2=325;
bit MS=0,temp_flag=0;
extern TT,TF;
	
void main()
{
	all_init();
	Timer0Init();
	while(1)
	{
		if(temp_flag==1)      //每200ms读取一次温度的值
		{
			temp_flag=0;
			temp=Get_temp();
		}
		num=Read_key();
		switch(num)
		{
			case  4:
				if(++mode==4)mode=1;
			break;
			case  5:
				MS^=1;
			break;
		  case  6:
				jm8();
				TT=TF;
			break;
			case  7:
				jm9();
				TT=TF;
			break;
		}
		jm4();
		jm5();
		LED();
	}
}

void Timer0() interrupt 1
{
	display();
	if(++temp_count==200)
	{
		temp_count=0;
		temp_flag=1;
	}
}

最后再说一次,每个模块都是比较简单的,最重要的编程逻辑。

版权声明:本文为CSDN博主「start field」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_53221728/article/details/120068846

生成海报
点赞 0

start field

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

蓝桥杯单片机第十二届省赛

如果有用请点赞,还会继续更新的 题目: 思路: 还是千篇一律的定时器中断,简直就是yyds。这届和第十一届的题可以说是有很多相似的地方,我感觉难点可能还是LED的那个部分

PCA9555详细学习

2022.01.27 控制寄存器和命令寄存器,及英文理解 一般8位作为地址,其中前四位时固定的,中间三位为地址配置,最后一位是读写位,即读是1,写是0 当地址