[2022年蓝桥杯单片机]考前唯一一次练手,第十三届模拟题

1 赛题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 程序

2.1 main.c

#include "stc15f2k60s2.h"
#include "iic.h"

#define uint8_t 	unsigned char
#define uint16_t	unsigned int
	
//74HC138
#define Y4C P2 = (P2 & 0x1f) | 0x80
#define Y5C	P2 = (P2 & 0x1f) | 0xa0
#define Y6C P2 = (P2 & 0x1f) | 0xd0
#define Y7C P2 = (P2 & 0x1f) | 0xe0
#define OFF P2 = (P2 & 0x1f) | 0x00
//Key_Scan of statement
#define S1 0
#define S2 1
#define S3 2
#define S4 3
uint8_t state = 0;
uint8_t Key = 0;
bit flag_S7_1s = 0;//S7长按标志位
bit LED_model = 1;//0-禁用LED,1-启用LED

//数码管
uint8_t num[]={		//0-9,10-'OFF',11-'F',12-'N',13-'U',14-'-'
		0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0x8E,0xc8,0xc1,0xbf};
uint8_t DispBuff[8] = {10,10,10,10,10,10,10,10};

//UI界面
uint8_t UI_model = 0;//0-频率;1-周期;2-电压
bit UI_Volt = 0;//0-通道1;1-通道2
//NE555
long freq = 0;
long freq_buff = 0;//缓存
//adc
bit flag_AD = 0;
uint16_t Volt = 0;
uint16_t Volt_buff = 0;//电压缓存
uint8_t Rd_Rb = 1;//1-RD1,3-Rb3 

void All_Init(void);
void Timer0Init(void);		//计时器@12.000MHz
void Timer1Init(void);	//1毫秒@12.000MHz
void Display(void);
uint8_t Key_Scan(void);
void Fre_Show(void);
void Cycle_Show(void);
void Set_S4(void);
void AD_Show(void);
void Set_S5(void);
void Set_S5(void);
void Set_S6(void);
void Set_S5(void);
void Set_S7(void);
void Delay5us(void);		//@12.000MHz
void LED_Set(void);

void main(void)
{
	All_Init();
	Timer0Init();
	Timer1Init();
	Fre_Show();
	EA = 1;
	while(1)
	{
		switch(Key)
		{
			case 4:Key = 0;Set_S4();break;
			case 5:Key = 0;Set_S5();break;
			case 6:Key = 0;Set_S6();break;
			case 7:Key = 0;Set_S7();break;
			default:break;
		}
		
		
		if(UI_model == 0)
			Fre_Show();
		else if(UI_model == 1)
			Cycle_Show();
		else if(UI_model == 2)
		{
			if(Rd_Rb	 == 1)
			{
				if(flag_AD)
				{
					EA = 0;
					Volt = Read_Rd1();
					EA = 1;
					Volt = Volt * 10 / 51 *10;
					AD_Show();
				}
			}
			else
			{
				if(flag_AD)
				{
					EA = 0;
					Volt = Read_Rb3();
					EA = 1;
					Volt = Volt * 10 / 51 *10;
					AD_Show();
				}
			}
		}
		
		LED_Set();
	}
}
void LED_Set(void)
{
	uint8_t LED = 0xe0;
	uint16_t Volt_Rd3;
	
	if(LED_model)
	{
		EA = 0;
		Volt_Rd3 = Read_Rb3();
		EA = 1;
		Volt_Rd3 = Volt_Rd3 * 10 / 51 *10;
		if(Volt_Rd3 > Volt_buff)
			LED = (LED & 0xfe) | 0x00;
		else
			LED = (LED & 0xfe) | 0x01;
		
		if(freq > freq_buff)
			LED = (LED & 0xfd) | 0x00;
		else
			LED = (LED & 0xfd) | 0x02;
		
		switch(UI_model)
		{
			case 0:LED = (LED & 0xe3) | 0x18;break;
			case 1:LED = (LED & 0xe3) | 0x14;break;
			case 2:LED = (LED & 0xe3) | 0x0c;break;
		}
		
		Y4C;
		P0 = LED;
		OFF;
	}
	else
	{
		Y4C;
		P0 = 0xff;
		OFF;
	}
}
void Set_S7(void)//分别存在0x03和0x04
{
	static uint8_t index =0;
	while(state == S3);
	if(flag_S7_1s == 0)
	{
		freq_buff = freq;
	}
	else
	{
		flag_S7_1s = 0;
		LED_model = ~LED_model;
		Y4C;
		P0=1<<index;
		OFF;
		index++;
		index&=0x07;
	}
	
}
void Set_S6(void)
{
	EA = 0;
	Volt_buff = Read_Rb3();
	EA = 1;
}
void Set_S5(void)//分别存在0x01和0x02
{
	if(UI_model == 2)
	{
		if(Rd_Rb == 1)
			Rd_Rb = 3;
		else
			Rd_Rb = 1;
	}
}
void Set_S4(void)
{
	UI_model++;
	if(UI_model == 3)
		UI_model = 0;
	if(UI_model == 2)
		Rd_Rb = 1;
}
void AD_Show(void)
{
	DispBuff[0] = 13;
	DispBuff[1] = 14;
	DispBuff[2] = Rd_Rb;
	DispBuff[3] = 10;
	DispBuff[4] = 10;
	DispBuff[5] = Volt / 100;
	DispBuff[6] = Volt /10 % 10;
	DispBuff[7] = Volt % 10;
}
void Cycle_Show(void)
{
	uint8_t buff[7],i=7,j=0;
	long Freq_b,cycle;
	Freq_b = freq;
	cycle = 1000000 / Freq_b;
	for(;i != 0;i--)
	{
		buff[i-1] = cycle % 10;
		cycle = cycle / 10;
	}
	i = 0;
	while((buff[i] == 0)&&(i != 6))
	{
		i++;
	}
	DispBuff[0] = 12;
	for(j= 0;j != i;j++)
	{
		DispBuff[j+1] = 10;//灭零
	}
	for(;j<=6;j++)
	{
		DispBuff[j+1] = buff[j];
	}
}
void Fre_Show(void)
{
	uint8_t buff[7],i=7,j=0;
	long Freq_b;
	Freq_b = freq;
	for(;i != 0;i--)
	{
		buff[i-1] = Freq_b % 10;
		Freq_b = Freq_b / 10;
	}
	i = 0;
	while((buff[i] == 0)&&(i != 6))
	{
		i++;
	}
	DispBuff[0] = 11;
	for(j= 0;j != i;j++)
	{
		DispBuff[j+1] = 10;//灭零
	}
	for(;j<=6;j++)
	{
		DispBuff[j+1] = buff[j];
	}
}
void T1_Interrupt() interrupt 3
{
	static uint8_t Key_cnt = 0,AD_cnt = 0;
	static uint16_t freq_cnt = 0;//每0.5s返回一次频率值
	
	AD_cnt++;
	if(AD_cnt >= 200)
	{
		AD_cnt = 0;
		flag_AD = 1;
	}
	
	if(freq_cnt == 0)
	{
		freq_cnt ++;
		TR0 = 1;
	}
	else if(freq_cnt > 0 && freq_cnt < 1000)
	{
		freq_cnt ++;
	}
	else
	{
		freq_cnt = 0;
		TR0 = 0;
		freq = (long)TH0*256+(long)TL0;
		TH0 = 0;
		TL0 = 0;
	}
	
	//按键
	Key_cnt ++;
	if(Key_cnt == 10)
	{
		Key_cnt = 0;
		if(Key == 0)
			Key = Key_Scan();
	}
	//数码管
	Display();
}	
void Display(void)
{
	static uint8_t index = 0;
	
	Y7C;
	P0 = 0xff;
	OFF;
	
	Y6C;
	P0 = 1 << index;
	OFF;
	
	if(UI_model != 2)
	{
		Y7C;
		P0 = num[DispBuff[index]];
		OFF;
	}
	else
	{
		if(index != 5)
		{
			Y7C;
			P0 = num[DispBuff[index]];
			OFF;
		}
		else
		{
			Y7C;
			P0 = num[DispBuff[index]] & 0x7f;
			OFF;
		}
	}
	
	index++;
	index &= 0x07;
}
uint8_t Key_Scan(void)
{
	static uint8_t cnt_1s = 0;//长按键
	uint8_t locate;
	uint8_t num = 0;
	
	EA = 0;
	P3 &= 0xff;
	locate = P3 & 0x0f;
	EA = 1;
	
	switch(state)
	{
		case S1:{
			if(locate != 0x0f)
			{
				state = S2;
				break;
			}
			else
				break;
		}
		case S2:{
			if(locate != 0x0f)
			{
				state = S3;
				switch(locate)
				{
					case 0x0e:num = 7;break;
					case 0x0d:num = 6;break;
					case 0x0b:num = 5;break;
					case 0x07:num = 4;break;
					default:break;
				}
				break;
			}
			else
			{
				state = S1;
				break;
			}
		}
		case S3:{
			if((locate != 0x0f)&&(cnt_1s < 100))//进入长按扫描
			{
				cnt_1s ++;
				break;
			}
			else if((locate != 0x0f)&&(cnt_1s >= 100))
			{
				cnt_1s = 0;
				if(locate == 0x0e)
				{
					flag_S7_1s = 1;//S7长按标志位
					state = S4;
				}
				else
					state = S4;
				break;
			}
			else
			{
				cnt_1s = 0;
				state = S1;
				break;
			}
		}
		case S4:{
			if(locate != 0x0f)
				break;
			else
			{
				state = S1;
				break;
			}
		}
	}
	
	return num;
}
void Timer0Init(void)		//计时器@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x05;		//设置为计数器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x00;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	//TR0 = 1;		//计时器0开始计时
	//主动操控
}

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初值
	TH1 = 0xD1;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;		//定时器1中断启动
}

void All_Init(void)
{
	Y4C;
	P0 = 0xff;
	OFF;
	
	Y5C;
	P0 = 0xaf;
	OFF;
}
void Delay5us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 12;
	while (--i);
}

1.1 iic.c

#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 Read_Rd1(void)
{
	unsigned char dat;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x01);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat = IIC_RecByte();
	
	IIC_SendAck(1);
	IIC_Stop();
	
	return dat;
}
unsigned char Read_Rb3(void)
{
	unsigned char dat;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat = IIC_RecByte();
	
	IIC_SendAck(1);
	IIC_Stop();
	
	return dat;
}

2.3 iic.h

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

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

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
unsigned char Read_Rd1(void);
unsigned char Read_Rb3(void);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值