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

也是刚刚把这个题目做完,让我们一起来看看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
#define kbd_io P3

u8 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,11,11,11};
extern u8 mode,value;
static u8 segadder=0;

void close()    //关闭无关外设
{
	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()     //数码管显示函数
{
	static u8 kbd_state=0,key_num=0;
	u8 kbd_press;
	u8 row;
	switch(kbd_state)
	{
		case state_0:
			kbd_io=0x0f; P42=0; P44=0;
			kbd_press =kbd_io;
            
			if(kbd_press != 0x0f)
				kbd_state = state_1;
			break;
		case state_1:
			kbd_press =kbd_io;
			if(kbd_press != 0x0f)
			{
				if((kbd_io&0x08)==0)  row=4;
				if((kbd_io&0x04)==0)  row=5;
				if((kbd_io&0x02)==0)  row=6;
				if((kbd_io&0x01)==0)  row=7;
				
				kbd_io=0xf0; P42=1;P44=1; 
				if(P44==0) key_num=row;
				if(P42==0) key_num=row+4;
				if((kbd_io&0x20)==0) key_num=row+8;
				if((kbd_io&0x10)==0) key_num=row+12;
				kbd_state = state_2;
			}
			else
				kbd_state = state_0;
			break;
		case state_2:
			kbd_io=0x0f; P42=0; P44=0;
			kbd_press =kbd_io;
			if(kbd_press == 0x0f)	kbd_state = state_0;
			break;
	}
	value=key_num;
	key_num=0;
	return value;
}

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

init.h

#ifndef _INIT_H_
#define _INIT_H_

#include<stc15f2k60s2.h>

void close();
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

extern u8 mode,seg[];   // extern表示此变量是在别处定义的,要在此处引用
extern u16 TT,TF,temp,RB;
extern bit MS;

void jm4()
{
	if(mode==0)               //温度显示界面
	{
		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==1)          //参数设置界面
	{
		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==2)        //DA输出界面
	{
		seg[0]=14;
		seg[1]=11;
	    seg[2]=11;
		seg[3]=11;
		seg[4]=11;
		seg[5]=RB/100;
		seg[6]=RB/10%10;
		seg[7]=RB%10;
	}
}

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

void jm8()
{
	if(mode==1)TT-=100;
}

void jm9()
{
	if(mode==1)TT+=100;
}

void LED()    //LED显示函数
{
	if(mode==0){
		if(MS==0){
			P2=(P2&0x1f)|0x80;P0=0xfc;P2&=0x1f;
		}
		else{
			P2=(P2&0x1f)|0x80;P0=0xfd;P2&=0x1f;
		}
	}
	else if(mode==1){
		if(MS==0){
		P2=(P2&0x1f)|0x80;P0=0xfa;P2&=0x1f;
		}
		else{
			P2=(P2&0x1f)|0x80;P0=0xfb;P2&=0x1f;
		}
	}
	else if(mode==2){
		if(MS==0){
		P2=(P2&0x1f)|0x80;P0=0xf6;P2&=0x1f;
		}
		else{
			P2=(P2&0x1f)|0x80;P0=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"jm.h"
#include"onewire.h"
#include"IIC.h"
#include"init.h"

#define u8 unsigned char
#define u16 unsigned int

u8 value=0,num=0,mode=0;
u8 temp_count=0;
u16 temp,TT=2500,TF=2500,RB=0;
bit temp_flag=0,MS=0;

void main()
{
	close();
	Timer0Init();
	while(1)
	{
		if(temp_flag==1)    //每200ms读取一次温度的值
		{
			temp_flag=0;
			temp=Get_Temp();
		}
		
		num=read_key();
		switch(num)
		{
			case 4:
				if(++mode==3)mode=0;
				break;
			
			case 5:
				MS^=1;
				break;
			
			case 8:
				jm8();
				TF=TT;
				break;
			
			case 9:
				jm9();
				TF=TT;
				break;
		}
		jm4();
		jm5();
		LED();
	}
}

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值