蓝桥杯单片机14届模拟赛1

有帮助的话点个赞吧~

main.c 

#include <STC15F2K60S2.H>
#include <intrins.h>
unsigned char code smg_duanma[10]={0xc0,0xf9,	0xa4,	0xb0,	0x99,	0x92,	0x82,	0xf8,	0x80,	0x90};
unsigned char smg[8];
unsigned int set_dist=30;  //距离参数
bit busy;

typedef struct
{
	unsigned char b1:1;
	unsigned char b2:1;
	unsigned char b3:1;
	unsigned char b4:1;
	unsigned char b5:1;
	unsigned char b6:1;
	unsigned char b7:1;
	unsigned char b8:1;
}Bits;

typedef union
{
	unsigned char Hex;
	Bits B;
}HexToBit;

HexToBit led_ctrl;

//译码器选择
void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
	P0 = p0dat;
	P2 = (P2&0x1f)|p2dat;
	P2 = P2&0x1f;
}

void Timer2Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x20;		//设置定时初值
	T2H = 0xD1;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	
	EA=1;
	IE2=0x04;
}

void Timer0Init(void)		//65535微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL1 = 0x00;		//设置定时初值
	TH1 = 0x00;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1=1;
}

void UartInit(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xC7;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	
	ES=1;
	EA=1;
}



//超声波测量

//发送超声波
void vSend_Wave()
{
	unsigned char i,j;
	for (i=0;i<8;i++)
	{
		P10=1;
		for(j=0;j<25;j++)
		_nop_();
		P10=0;
		for(j=0;j<25;j++)
		_nop_();
	}
}

//获取距离
unsigned int vGet_distance()
{
	unsigned int distance;
	TL0=0;
	TH0=0;
	vSend_Wave();
	TR0=1;
	while((P11==1)&&(TF0==0));
	TR0=0;
	TF0=0;
	distance = ((TH0<<8)|TL0)*0.017;
	
	return distance;
}

//测量
unsigned int cnt_sonic;
unsigned int Distance;
void vSnoic_Process()
{
	if(cnt_sonic>=100)
	{
		cnt_sonic=0;
		Distance = vGet_distance();
	}
}




//数码管操作
unsigned char mode_smg=0;
void vSMG_Process()
{
	if(mode_smg==0)
	{
		smg[0] = 0xc1;
		smg[1] = smg_duanma[1];
		smg[2] = 0xff;
		smg[3] = 0xff;
		smg[4] = 0xff;
		smg[5] = smg_duanma[Distance/100];
		smg[6] = smg_duanma[Distance/10%10];
		smg[7] = smg_duanma[Distance%10];
	}
	if(mode_smg==1)
	{
		smg[0] = 0xc1;
		smg[1] = smg_duanma[2];
		smg[2] = 0xff;
		smg[3] = 0xff;
		smg[4] = 0xff;
		smg[5] = smg_duanma[set_dist/100];
		smg[6] = smg_duanma[set_dist/10%10];
		smg[7] = smg_duanma[set_dist%10];
	}
}

//数码管显示
void vSMG_Show()
{
	static unsigned char i;
	vDevice_Process(0xc0, 0x00);
	vDevice_Process(0xe0, smg[i]);
	vDevice_Process(0xc0, 0x01<<i);
	i = (i+1)%8;
}

//KBD扫描
unsigned char vScan_Keys()
{
	unsigned char key_io=0xff;
	P32=0;P33=0;
	P34=1;P35=1;P42=1;P44=1;
	if(P44==0) key_io = 0x70;
	if(P42==0) key_io = 0xb0;
	if(P35==0) key_io = 0xd0;
	if(P34==0) key_io = 0xe0;
	
	P32=1;P33=1;
	P34=0;P35=0;P42=0;P44=0;
	if(P33==0) key_io = key_io|0x07;
	if(P32==0) key_io = key_io|0x0b;
	
	return key_io;	
}

//三行按键处理
unsigned char Trg, Cont;
void vThreeLins_Key()
{
	unsigned char key_io;	
	unsigned char ReadData;
	key_io=vScan_Keys();
	ReadData=key_io^0xff;
	Trg = ReadData&(ReadData^Cont);
	Cont = ReadData;
}

//按键处理
unsigned int cnt_key;
bit flag_send=0;  //串口发送标志位
void vKeys_Process()
{
	if(cnt_key>=20)
	{
		cnt_key=0;
		vThreeLins_Key();
		if(Trg==0x88) //S4
		{
			mode_smg = (mode_smg+1)%2;
		}
		if(Trg==0x48) //S8
		{
			if(mode_smg==0)
			{
				set_dist = Distance;
			}
		}
		if(Trg==0x28) //S12
		{
			if(mode_smg==1)
			{
				if(set_dist<=990) //判断 防止越界
				set_dist = set_dist+10;
				
			}
		}
		if(Trg==0x18) //S16
		{
			if(mode_smg==1)
			{
				if(set_dist>=10)
				set_dist = set_dist-10;
			}
		}
		if(Trg==0x44) //S9
		{
			flag_send=1;
		}
	}
}


/*----------------------------
发送串口数据
----------------------------*/
void SendData(unsigned char dat)
{
    while (busy);               //等待前面的数据发送完成
    busy = 1;
    SBUF = dat;                 //写数据到UART数据寄存器
}

/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
    while (*s)                  //检测字符串结束标志
    {
        SendData(*s++);         //发送当前字符
    }
}

//发送距离参数
void Send_dist()
{
	if(flag_send==1)
	{
		flag_send=0;
		SendString("Distance:");
		SendData(Distance/100+'0');
		SendData(Distance/10%10+'0');
		SendData(Distance%10+'0');
		SendString("cm");
	}
}

//LED指示灯
bit flag_led=0;
void vLED_Process()
{
	if(mode_smg==0)
	{
		led_ctrl.B.b1=0;
		led_ctrl.B.b2=1;
	}
	if(mode_smg==1)
	{
		led_ctrl.B.b1=1;
		led_ctrl.B.b2=0;
	}
	if(Distance>set_dist)
	{
		flag_led=1;
	}
	else
	{
		flag_led=0;
		led_ctrl.B.b3=1;
	}
	vDevice_Process(0x80,led_ctrl.Hex);
}

//初始化
void System_init()
{
	led_ctrl.Hex=0xff;
	vDevice_Process(0x80,led_ctrl.Hex);
	vDevice_Process(0xa0,0x00);
}


void main()
{
	Timer2Init();	
	Timer0Init();
	UartInit();
	System_init();
	while(1)
	{
		vSMG_Process();
		vSnoic_Process();
		vKeys_Process();
		Send_dist();
	}
}

unsigned int pwm_dat;
void Timer2() interrupt 12
{
	cnt_sonic++;cnt_key++;pwm_dat++;
	vSMG_Show();
	vLED_Process();
	if(flag_led==1)//闪烁
	{
		if(pwm_dat<200)
		{
			led_ctrl.B.b3=0;
		}
		else if(pwm_dat<400)
		{
			led_ctrl.B.b3=1;
		}
		else
		{
			pwm_dat=0;
		}
		vDevice_Process(0x80,led_ctrl.Hex);
	}
}

/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 1
{
    if (RI)
    {
        RI = 0;                 //清除RI位
    }
    if (TI)
    {
        TI = 0;                 //清除TI位
        busy = 0;               //清忙标志
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值