2022年第十三届蓝桥杯单片机第二轮省赛_官方风格代码分享

1 引言

去年的省赛补赛及其离谱,竟然考了从来没考过的超声波……由于考前没有那么自信觉得自己一定能进决赛,所以超声波是一点也没碰呀,开考的时候打开试题,还以为发错题目了……怎么看着那么像决赛的风格呢……

于是在考场写完其他模块之后就开始罚坐,并感叹官方发的板子好好看(起码有跳帽可以制裁Beep哈哈哈,旋钮也比买的板子高级)……没提前看过驱动程序,再聪明也编不出来吧……

不过其实归根到底还是自己准备不充分,毕竟人家也没有明确说明什么知识只在什么阶段考。所以啊,想要当狮子,就要有狮子的自觉,命运的礼物是赠送给有准备的人的。

2 程序

本文作者在去年的省赛中获得了省二较靠前的名次,应该是差一道客观题的分数进决赛,分享一下考场上自己写的代码,供各位赛友们参考。

2.1 试题

2022年第十三届蓝桥杯单片机第二轮省赛_官方风格代码分享_第1张图片
2022年第十三届蓝桥杯单片机第二轮省赛_官方风格代码分享_第2张图片
2022年第十三届蓝桥杯单片机第二轮省赛_官方风格代码分享_第3张图片
2022年第十三届蓝桥杯单片机第二轮省赛_官方风格代码分享_第4张图片

2.2 主程序

#include "reg52.h"
#include "stdio.h"
#include "iic.h"
#include "ul.h"

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
	
sfr AUXR=0x8e;

ulong ulms;
uint uiSeg_Dly;
uchar pucSeg_Buf[10],pucSeg_Code[8],ucSeg_Pos;
uchar ucLed;
uchar ucKey_Old,ucKey_Dly;
uchar ucVol;
uint uiVolH,uiVolL,uiVolH_Real,uiVolL_Real;
uchar ucMode,ucSet;
uchar ucSur,ucSur_Flag,ucSur_Led;
	
void HC(uchar channel)
{
	switch(channel)
	{
		case 4:P2=(P2&0x1f)|0x80;break;
		case 5:P2=(P2&0x1f)|0xa0;break;
		case 6:P2=(P2&0x1f)|0xc0;break;
		case 7:P2=(P2&0x1f)|0xe0;break;
		case 0:P2=(P2&0x1f)|0x00;break;
		default:break;
	}
}

void Init_Sys()
{
	P0=0x00;HC(5);HC(0);
	P0=0xff;HC(4);HC(0);
	ucMode=0;ucSet=0;uiVolH=459;uiVolL=51,uiVolH_Real=459,uiVolL_Real=51;
}

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x18;		//设置定时初始值
	TH1 = 0xFC;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1=1;
	EA=1;
}

void Led_Disp(uchar ucLed)
{
	P0=~ucLed;HC(4);HC(0);
}

void Seg_Tran(uchar *pucSeg_Buf,uchar *pucSeg_Code)
{
	uchar i,j=0,temp;
	
	for(i=0;i<8;i++,j++)
	{
		switch(pucSeg_Buf[j])
		{
			case '0':temp=0xc0;break;
			case '1':temp=0xf9;break;
			case '2':temp=0xa4;break;
			case '3':temp=0xb0;break;
			case '4':temp=0x99;break;
			case '5':temp=0x92;break;
			case '6':temp=0x82;break;
			case '7':temp=0xf8;break;
			case '8':temp=0x80;break;
			case '9':temp=0x90;break;
			case 'U':temp=0xc1;break;
			case 'L':temp=0xc3;break;
			case 'A':temp=0x88;break;
			case 'P':temp=0x8c;break;
			default:temp=0xff;
		}
		if(pucSeg_Buf[j+1]=='.')
		{
			temp&=0x7f;
			j++;
		}
		pucSeg_Code[i]=temp;
	}
}

void Seg_Disp(uchar *pucSeg_Code,uchar ucSeg_Pos)
{
	P0=0xff;HC(7);HC(0);
	P0=0x01<<ucSeg_Pos;HC(6);HC(0);
	P0=pucSeg_Code[ucSeg_Pos];HC(7);HC(0);
}

uchar Key_Read()
{
	uchar Key_Val,Key_New;
	Key_New=P3&0x0f;
	switch(~Key_New)
	{
		case 0xf8:Key_Val=4;break;
		case 0xf4:Key_Val=5;break;
		case 0xf2:Key_Val=6;break;
		case 0xf1:Key_Val=7;break;
		default:Key_Val=0;
	}
	return Key_Val;
}

void Key_Proc();
void Seg_Proc();
void Led_Proc();

void main()
{
	Init_Sys();
	Timer1Init();
	while(1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

void Key_Proc()
{
	unsigned char ucKey_Val,ucKey_Down;
	
	if(ucKey_Dly)return;
	ucKey_Dly=1;
	
	ucKey_Val=Key_Read();
	ucKey_Down=ucKey_Val&(ucKey_Val^ucKey_Old);
	ucKey_Old=ucKey_Val;
	
	switch(ucKey_Down)
	{
		case 4:
			ucMode++;ucMode%=3;break;
		case 5:
			if(ucMode==2)
			{
				ucSet++;ucSet%=2;break;           //检查
			}
			else break;
		case 6:
			if(ucMode==2)
			{
				if(ucSet==0)
				{
					if(uiVolH==510)uiVolH=51;
					else uiVolH+=51;
					break;
				}
				if(ucSet==1)
				{
					if(uiVolL==510)uiVolL=51;
					else uiVolL+=51;
					break;
				}
			}
			else break;
		case 7:
			if(ucMode==2)
			{
				if(ucSet==0)
				{
					if(uiVolH==51)uiVolH=510;
					else uiVolH-=51;
					break;
				}
				if(ucSet==1)
				{
					if(uiVolL==51)uiVolL=510;
					else uiVolL-=51;
					break;
				}
			}
			else break;
	}
	if(ucMode!=2)
	{
		ucSet=0;
		uiVolH_Real=uiVolH;
		uiVolL_Real=uiVolL;
	}
}

void Seg_Proc()
{
	if(uiSeg_Dly)return;
	uiSeg_Dly=1;
	ucVol=PCF8591_Adc();
	ucSur=Wav_Rec();
	if(((ucVol*2)>=uiVolL_Real)&&((ucVol*2)<=uiVolH_Real))
	{
		ucSur_Flag=1;
	}
	else
	{
		ucSur_Flag=0;
	}
	
	switch(ucMode)
	{
		case 0:
			sprintf(pucSeg_Buf,"U    %3.2f",(float)ucVol/51.0);break;
		case 1:
			if(ucSur_Flag)
			{sprintf(pucSeg_Buf,"L    %3d",(uint)ucSur);break;}
			else 
				sprintf(pucSeg_Buf,"L    AAA");break;
		case 2:
			sprintf(pucSeg_Buf,"P  %2.1f %2.1f",(float)uiVolH/102.0,(float)uiVolL/102.0);break;
	}
	
	switch(ucSur_Flag)
	{
		case 0:PCF8591_Dac(0);break;
		case 1:
			if((ucSur>=0)&&(ucSur<=20))PCF8591_Dac(51);
			if((ucSur>=20)&&(ucSur<=80))PCF8591_Dac(((ucSur-15)*51)/15.0);
			if(ucSur>=80)PCF8591_Dac(255);
	}
	
	Seg_Tran(pucSeg_Buf,pucSeg_Code);
}

void Led_Proc()
{
	switch(ucMode)
	{
		case 0:
			ucLed=0x01;break;
		case 1:
			ucLed=0x02;break;
		case 2:
			ucLed=0x04;break;
	}
}

void Service() interrupt 3
{
	ulms++;
	if(++ucKey_Dly==10)ucKey_Dly=0;
	if(++uiSeg_Dly==100)uiSeg_Dly=0;
	Seg_Disp(pucSeg_Code,ucSeg_Pos);
	if(++ucSeg_Pos==8)ucSeg_Pos=0;
	if(ucSur_Flag)
	{
		if(!(ulms%100))
		{
			ucLed^=0x80;
		}
	}
	else
		ucLed&=(~0x80);
	Led_Disp(ucLed);
}

2.2 驱动程序

#include "iic.h"

#define DELAY_TIME 5

//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//I2C总线启动信号
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//I2C总线停止信号
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答或非应答信号
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    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;
}

//I2C总线发送一个字节数据
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;  
}

//I2C总线接收一个字节数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

unsigned char PCF8591_Adc()
{
	unsigned char temp;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(0x43);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	
	temp=IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return temp;
}	

void PCF8591_Dac(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	
	IIC_SendByte(0x43);
	IIC_WaitAck();
	
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

以上是除了超声波之外的驱动程序。
下面是我考场上凭借看过一眼的印象胡编乱造的超声波驱动……最后怎么试示数都是255,过段时间复习看看到底如何编写。

#include "ul.h"


sbit AUXR=0x8e;

	
sbit TX=P1^0;
sbit RX=P1^1;

void Timer0Init(void)		//12微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xF4;		//设置定时初始值
	TH0 = 0xFF;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0开始计时
}

unsigned char Wav_Rec()
{
	unsigned char ucDist,ucNum=10;
	
	TL0=0xF4;
	TH0=0xFF;
	TR0=1;
	
	while(ucNum--)
	{
		while(TF0)
		{
			TX^=1;
			TF0=0;
		}
		TR0=0;
		TF0=0;
		TH0=0;
		TR0=1;
	}
	while(RX&&(!TF0));
	TR0=1;
	
	if(TF0)
	{
		TF0=0;
		ucDist=255;
	}
	else
		ucDist=((TH0<<4)+TL0)*0.017;
	
	return ucDist;
}

3 结语

其实题目真的不难,但是还是败于自己的疏忽大意。想要进决赛,就要有一颗决赛的心。
诸赛友,舞台广阔,共勉。

你可能感兴趣的:(蓝桥杯,单片机,嵌入式硬件,51单片机,mcu)