【蓝桥杯单片机】第十四届模拟二

该代码段展示了一个基于REGX52微控制器的程序,主要功能包括初始化定时器2用于参数定时,设置键盘扫描函数KeyScan来检测按键输入,使用串口通信UartInit进行数据发送和接收,以及显示和控制LED。定时器中断处理函数Timer2_Isr中更新了显示和按键状态。程序还实现了超声波测距功能Dis_measure。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c4b8f1a65b8b4c338060cb6a9c786d2a.png

881ae176cebf4fff83c90123d92799c3.png

e835c38ef6ae4b599eb4dcbda67cd055.png

69da4538c0c7493abc1f1b4419f122dd.png

main.c(这次模拟题无其他驱动函数) 

#include <REGX52.H>
#include <intrins.H>
#include <stdio.H>

#define u8 unsigned char 
#define u16 unsigned int
#define LED(X) {hc573(0);P0 = X;hc573(4);hc573(0);}
#define BUZ(X) {hc573(0);P0 = X;hc573(5);hc573(0);}
#define COM(X) {hc573(0);P0 = X;hc573(6);hc573(0);}
#define SMG(X) {hc573(0);P0 = X;hc573(7);hc573(0);}

sfr  P4 = 0xc0;
sfr AUXR = 0x8e;
sfr T2H=0xD6;
sfr T2L=0xD7;
sfr IE2=0xaf;
sbit R1 = P4^4;
sbit R2 = P4^2;
sbit C1 = P3^0;
sbit C2 = P3^1;
sbit C3 = P3^2;
sbit TX = P1^0;
sbit RX = P1^1;
code u8 Seg_Table[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc1};
u16 cs=30,flag_s,flag_L3,s;
u8 flag_key,flag_tab,a,flag_led,tab[8]={10},ui,flag_taskkey,keystatus,keyvalue,dat,led=0xff;
//================================函数声明区=============================
void Delay12us();		//@12.000MHz
void hc573(u8 channel);
void Timer2_Init(void);
void display();
char putchar(char c);
void SendByte(u8 date);
//======================================================================
void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);

}

void hc573(u8 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;
	}
}
void Timer2_Isr(void) interrupt 12  //定时器2用作参数定时
{
	display();
	if(flag_key<20) ++flag_key;
	if(flag_tab<20) ++flag_tab;
	if(flag_taskkey<20) ++flag_taskkey;
	if(flag_s<500) ++flag_s;
	if(flag_led<30) ++flag_led;
	if(flag_L3<200) ++flag_L3;
}

void KeyScan()
{
	if(flag_key<20) return;
	flag_key = 0;
	TR1 = 0;
	switch(keystatus)
	{
		case 0:
			R1=0;R2=C1=C2=C3=1;
			if(C1==0||C2==0||C3==0) 
			{
				keystatus = 1;
				return;
			}
			R2=0;R1=C2=C3=C1=1;
			if(C1==0||C2==0) 
			{
				keystatus = 2;
				return;
			}
			break;
		case 1:
			if(C1 == 0)	keyvalue = 7;
			if(C2 == 0)	keyvalue = 6;
			if(C3 == 0)	keyvalue = 5;
		  keystatus = 3;
		break;
		case 2:
			if(C1 == 0)	keyvalue = 11;
			if(C2 == 0)	keyvalue = 10;
		  keystatus = 3;
		break;
		case 3:
			if(C1==1&&C2==1&&C3==1)
				keystatus = 0;
			break;
	 }
	TR1 = 1;
	 P3 = 0xff;
}

void taskKey()
{
	switch(keyvalue)
	{
		case 7: ui = (ui+1)%2;keyvalue=0;break;
		case 11:if(ui == 0)cs=s;keyvalue=0;break;
		case 6:if(ui==1)cs+=10;keyvalue=0;break;
		case 10:if(cs>0&&ui==1) cs-=10;keyvalue=0;break;
		case 5:ES=1;printf("Distance:%ucm",s);ES=0;keyvalue=0;break;
		default :keyvalue=0;break;
	}
}
void Settab()
{
	if(flag_tab<20) return;
	flag_tab = 0;
	switch(ui)
	{
		case 0:
			tab[0] = 11;
			tab[1] = 1;
			tab[2] = 10;
			tab[3] = 10;
			tab[4] = 10;
			tab[5] = s/100;
			tab[6] = s%100/10;
			tab[7] = s%10;
		break;
		case 1:
			tab[0] = 11;
			tab[1] = 2;
			tab[2] = 10;
			tab[3] = 10;
			tab[4] = 10;
			tab[5] = cs/100;
			tab[6] = cs%100/10;
			tab[7] = cs%10;
		break;
	}
}
void display()
{
	static u8 i;
	SMG(0xff);
	COM(0x01<<i);
	SMG(Seg_Table[tab[i]]);
	i = (i+1)%8;
}
void Timer2_Init(void)//定时器2用作参数定时
{
	AUXR &= 0xFB;			//定时器时钟12T模式
	T2L = 0x18;				//设置定时初始值
	T2H = 0xFC;				//设置定时初始值
	AUXR |= 0x10;			//定时器2开始计时
	IE2 |= 0x04;			//使能定时器2中断
	EA = 1;
}
void SendWave()
{
	u8 i;
	for(i=0;i<=7;i++)
	{
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}
void Dis_measure()
{
	if(flag_s<500) return;
	flag_s = 0;
	TMOD &= 0xF0;			//定时器0用作测距
	TL0 = 0x00;				//设置定时初始值
	TH0 = 0x00;				//设置定时初始值
	TF0 = 0;				//清除TF1标志
	TR0 = 0;			
	
	SendWave();
	TR0 = 1;
	while(RX==1&&TF0==0);
	TR0 = 0;
	if(TF0==1) 
	{
		s = 255;
	}
	if(RX==0)
	{
		s = (TH0<<8|TL0)*0.017;
	}
}


void UartInit(void)		//定时器1用作串口
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器时钟1T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xC7;			//设置定时初始值
	TH1 = 0xFE;			//设置定时初始值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}

void Receive() interrupt 4
{
	if(RI == 1)
	{
		RI = 0;
		dat = SBUF;
	}
}

void SendByte(u8 date)
{
	SBUF = date;
	while(TI == 0);
	TI = 0;
}

char putchar(char c)
{
	SendByte(c);
	return c;
}


void LED_control()
{
	if(flag_led<30) return;
	flag_led=0;
 	if(ui == 0) led&=~1;
	else led|=1;
	if(ui == 1) led&=~2;
	else led|=2;
	LED(led)
}
void L3()
{
	if(flag_L3<200) return;
	else flag_L3=0;
	if(s>cs) 
		led^=4;
	else led |= 4;
	LED(led);
}
void main()
{
	BUZ(0x00);
	LED(0xff);
	Timer2_Init();
	UartInit();
	while(1)
	{
		Settab();
		taskKey();
		KeyScan();
		Dis_measure();
		LED_control();
		L3();
	}
}

### 关于蓝桥杯单片机第十四届模拟赛的试题与解题思路 #### 背景介绍 蓝桥杯大赛作为一项面向全国高校学生的科技竞赛活动,其嵌入式方向尤其注重考察参赛者在硬件设计、软件编程以及综合应用能力方面的水平。对于第十四届蓝桥杯嵌入式比赛而言,无论是省赛还是国赛阶段,都涉及到了大量的实际工程问题解决能力和算法优化技巧[^1]。 #### 题目概述 根据以往的比赛经验及公开资源分析,可以推测出第十四届蓝桥杯嵌入式省赛中的部分典型题目可能包括但不限于以下几个方面: - **定时器中断控制LED闪烁频率调整** - 此类题目通常要求选手能够熟练掌握微控制器内部定时器模块的工作原理及其配置方法,并通过改变预分频系数或者计数值来实现不同周期下的信号输出。 ```c void TIM2_Init(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟 TIM_TimeBaseStructure.TIM_Period = 999; //自动重装载值ARR=999 TIM_TimeBaseStructure.TIM_Prescaler = 7199; //预分频数PSC=7199(即系统时钟8MHz/(7200+1)=1KHz) TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;//抢占优先级设为最低 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; //子优先级也设为最低 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //允许更新事件产生中断请求 TIM_Cmd(TIM2,ENABLE); //启动定时器 } ``` - **串口通信协议解析与数据帧处理** - 这一类型的考题旨在测试学生是否具备构建稳定可靠的数据传输链路的能力,同时还需要考虑如何高效地对接收到的信息包进行校验和提取有效负载等功能。 - **ADC采样电压计算并显示到LCD屏上** - ADC(模数转换器)的应用场景非常广泛,在工业自动化领域尤为常见。因此该知识点成为了历年真题的重点覆盖区域之一。它不仅考验了考生对传感器接口电路的理解程度,还进一步延伸至图形界面开发层面的知识迁移运用之上。 #### 解题策略建议 针对上述提到的各种类型挑战项目,这里给出一些通用性的应对措施供参考学习之用: - 对于涉及到外设初始化的部分,务必仔细阅读官方手册文档说明,确保每一个寄存器位域设置准确无误; - 当面临复杂逻辑运算需求的时候,则应该尝试采用结构化程序设计理念将其拆分成若干个小功能单元分别予以实现后再组合起来形成最终解决方案; - 如果遇到需要长时间运行的任务调度情况的话,那么引入RTOS操作系统将会是一个不错的选择方案,这样既可以提高代码可维护性又能保障实时响应性能指标达成预期目标值范围之内。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值