蓝桥杯单片机第14届模拟题二(基于西风大模板)

题目要求:

程序实现:

main.c
/*头文件声明区*/
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Key.h>
#include <Led.h>
#include <Seg.h>
#include <Uart.h>
#include <Stdio.h>
#include <onewire.h>
#include <iic.h>
#include <String.h>

/*头文件变量声明区*/
unsigned char Key_Val,Key_Down,Key_Up,Key_Old;
unsigned char Key_Slow_Down;
idata unsigned char Seg_Buf[8] = {16,16,16,16,16,16,16,16};
idata unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};
unsigned char Seg_Pos;
unsigned int Seg_Slow_Down;
idata unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};
idata unsigned char Uart_Recv[10];
unsigned char Uart_Recv_Index;
bit Uart_flag;
unsigned char Sys_Tick;
bit Lock;//0-解锁 1-锁定
unsigned char Timer_100ms;
bit Timer_100ms_flag;
unsigned char Seg_Disp_Mode;//0-温度显示界面 1-电压显示界面
float T;
float dac;

void Delay750ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 35;
	j = 51;
	k = 182;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


/*键盘处理函数*/
void Key_Proc()
{
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;
	
	Key_Val = Key_Read();
	Key_Down = Key_Val & (Key_Val ^ Key_Old);
	Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
	Key_Old = Key_Val;
	
	switch(Key_Down)
	{
		case 4:
			Lock = 1;
		break;
		case 5:
			if(Lock == 1)
			  Lock = 0;
		break;
		case 12://发送按键
			if(Seg_Disp_Mode == 0)
				printf("TEMP:%.1f℃\r\n",T);
			else
				printf("Voltage:%.2fV\r\n",dac);
		break;
	}
}
/*信息处理函数*/
void Seg_Proc()
{
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;
	
	/*信息获取区域*/
	T = rd_wendu();
	dac = Ad_read(0x43) / 51.0;
	if(Seg_Disp_Mode == 0)//温度显示界面
	{
		Seg_Buf[0] = 18;
		Seg_Buf[1] = 1;
		Seg_Buf[5] = (unsigned int)(T * 10) / 100 % 10;
		Seg_Point[5] = 0;
		Seg_Buf[6] = (unsigned int)(T * 10) / 10 % 10;
		Seg_Point[6] = 1;
		Seg_Buf[7] = (unsigned int)(T * 10) % 10;
	}
	if(Seg_Disp_Mode == 1)//电压显示界面
	{
		Seg_Buf[0] = 18;
		Seg_Buf[1] = 2;
		Seg_Buf[5] = (unsigned int)(dac * 100) / 100 % 10;		
		Seg_Point[5] = 1;
		Seg_Buf[6] = (unsigned int)(dac * 100) / 10 % 10;	
		Seg_Point[6] = 0;
		Seg_Buf[7] = (unsigned int)(dac * 100) % 10;	
	}
	
}
/*其他显示函数*/
void Led_Proc()
{
	ucLed[0] = (Seg_Disp_Mode == 0);
	ucLed[1] = (Seg_Disp_Mode == 1);	  
	if(Lock == 1)
	{
		ucLed[2] = Timer_100ms_flag;
	}
	else
		ucLed[2] = 0;
	
	Relay(T >= 28.0);
	Beep(dac > 3.60);
}
/*串口处理函数*/
void Uart_Proc()
{
	if(Uart_Recv_Index == 0) return;
	if(Sys_Tick >= 10)
	{
		Sys_Tick = Uart_flag = 0;
		if(Lock == 0)
		{
			if(Uart_Recv_Index == 1)
		{
			if(Uart_Recv[0] == 'A')
			{
				Seg_Disp_Mode = 0;
			}			
			if(Uart_Recv[0] == 'B')
			{
				Seg_Disp_Mode = 1;
			}			
		}
		}	
		memset(Uart_Recv,0,Uart_Recv_Index);
		Uart_Recv_Index = 0;
	}
}
/*定时器1初始化*/
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;
}

/*定时器1中断服务函数*/
void Timer1server() interrupt 3
{
	if(++Key_Slow_Down==10) Key_Slow_Down = 0;
	if(++Seg_Slow_Down==500) Seg_Slow_Down = 0;
	if(Uart_flag) Sys_Tick++;
	if(++Seg_Pos==8) Seg_Pos = 0;
	
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
	
	
	if(Lock == 1)
	{
		if(++Timer_100ms == 100)
		{
			Timer_100ms = 0;
			Timer_100ms_flag ^= 1; 
		}
	}		
	
}
/*串口1中断服务函数*/
void Uart1server() interrupt 4
{
	if(RI == 1)
	{
		Sys_Tick = 0;
		Uart_flag = 1;
		Uart_Recv[Uart_Recv_Index] = SBUF;
		Uart_Recv_Index ++;
		RI = 0;
	}
	if(Uart_Recv_Index > 10)
	  Uart_Recv_Index = 0;
	
}
/*主函数*/
void main()
{
	System_Init();
	Timer1Init();
	UartInit();
	T = rd_wendu();
	Delay750ms();
	while(1)
	{
	  Key_Proc();
		Seg_Proc();
		Led_Proc();
		Uart_Proc();
	}
}
uart.c
#include <Uart.h>

void UartInit(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0xC7;		//设定定时初值
	T2H = 0xFE;		//设定定时初值
	AUXR |= 0x10;		//启动定时器2
	
	ES = 1;
	EA = 1;
}

extern char putchar (char ch)
{
	SBUF = ch;
	while(TI == 0);
	TI = 0;
	return ch;
}
onewire.c
#include <onewire.h>
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}


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;
}

float rd_wendu()
{
	unsigned char low,high;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	low = Read_DS18B20();
	high = Read_DS18B20();
	return (high << 8 | low) / 16.0;
}
iic.c
#include <iic.h>
#define DELAY_TIME	10


static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}


void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}


void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}


void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}


unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}


unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}


void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

unsigned char Ad_read(unsigned char addr)
{
	unsigned char temp;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return temp;
}

测试结果:

<think>嗯,用户问的是蓝桥杯单片机第十一模拟题的智能门锁程序设计,还提到要用西风老师的模板。首先,我需要回忆一下蓝桥杯单片机的常见考点和西风老师的编程风格。通常这类题目会涉及按键输入、显示模块、锁的控制以及可能的传感器,比如红外或者矩阵键盘的应用。 用户可能已经看过题目,但需要具体的设计思路。首先得确定题目要求的功能,比如是否要密码输入、LCD显示、开锁电机控制、报警功能等。可能还需要考虑状态切换,比如管理员模式和用户模式,或者密码错误次数限制。 接下来,按照西风老师的模板,程序结构可能会分为系统初始化、按键扫描、显示处理、状态机控制等模块。需要确认各个模块之间的协调,比如按键处理如何触发显示更新,以及如何控制锁的状态。 可能用户对如何组织代码结构不太清楚,比如如何分层处理各个功能模块。需要分步骤说明,比如初始化部分配置IO口、定时器,然后进入主循环,处理按键、显示、状态判断等。 另外,可能涉及到EEPROM存储密码,这需要IIC通信的代码,这部分在西风模板里可能有现成的函数,但需要正确调用。同时,要注意消抖处理,确保按键输入的稳定性。 显示部分可能用LCD1602或者数码管,需要根据题目要求来调整显示内容,比如输入密码时的星号显示,或者错误提示。电机控制可能用PWM信号,或者简单的IO高低电平驱动继电器模拟开锁动作。 状态机设计是关键,比如待机状态、输入密码状态、验证状态、开锁状态、报警状态等。每个状态之间的转换条件需要明确,比如输入正确密码后进入开锁状态,错误次数超过限制触发报警。 可能还需要处理中断,比如定时器中断用于扫描按键或者处理动态显示。需要确保中断服务函数简洁,避免长时间占用导致其他功能延迟。 最后,测试和调试部分可能也是用户关心的,比如如何分段测试各个功能模块,确保按键、显示、锁控制都能正常工作后再整合。可能还需要注意资源的合理分配,避免变量冲突或内存溢出。 总之,用户需要的是一个基于西风模板的结构化程序设计思路,涵盖各个功能模块的实现方法,以及状态机控制流程。需要分步骤解释,并强调关键点,比如密码存储、状态转换、错误处理等,确保代码的稳定性和可靠性。</think>好的!关于蓝桥杯单片机第十一模拟题智能门锁程序的设计,结合西风老师的模板,我将分步骤为你解析设计思路和关键代码实现。 --- ### **一、题目核心需求分析** 根据模拟题要求,智能门锁需要实现以下功能: 1. **矩阵键盘输入**(密码输入) 2. **LCD1602显示**(密码显示、状态提示) 3. **蜂鸣器报警**(密码错误次数超限) 4. **LED指示灯**(门锁状态指示) 5. **继电器控制**(模拟门锁开关) 6. **EEPROM存储**(密码保存与读取) --- ### **西风模板框架适配** 西风老师的模板通常包含以下模块: ```c void main() { SysInit(); // 系统初始化 while(1) { KeyProc(); // 按键处理 LcdProc(); // 显示处理 StateProc(); // 状态处理 OutputProc(); // 输出控制 } } ``` --- ### **三、关键代码实现** #### **1. 系统初始化** ```c void SysInit() { P2 = 0xA0; P0 = 0x00; // 关闭蜂鸣器、继电器 P2 = 0x80; P0 = 0xFF; // 关闭LED Timer0Init(); // 定时器0初始化(用于按键扫描) LcdInit(); // LCD1602初始化 ReadPasswordFromEEPROM(); // 从EEPROM读取预设密码 } ``` #### **2. 按键处理** ```c void KeyProc() { u8 key = MatrixKeyScan(); // 矩阵键盘扫描 if(key != 0xFF) { if(key < 10) // 数字键0-9 { input_pw[input_cnt++] = key + '0'; ShowStar(); // LCD显示* } else if(key == 14) // 确认键 { CheckPassword(); } else if(key == 15) // 删除键 { if(input_cnt > 0) input_cnt--; UpdateDisplay(); } } } ``` #### **3. 密码验证逻辑** ```c void CheckPassword() { if(strcmp(input_pw, saved_pw) == 0) { OpenDoor(); // 开锁 error_cnt = 0; // 重置错误计数 } else { error_cnt++; if(error_cnt >= 3) Alarm(); // 报警 } ClearInput(); // 清空输入缓存 } ``` #### **4. 输出控制** ```c void OpenDoor() { P2 = 0xA0; P0 = 0x10; // 继电器吸合(开锁) Delay(2000); // 保持2秒 P0 = 0x00; // 关闭继电器 } void Alarm() { P2 = 0xA0; P0 = 0x40; // 蜂鸣器报警 P2 = 0x80; P0 = 0x00; // LED全亮 Delay(5000); P0 = 0xFF; // 关闭报警 } ``` #### **5. EEPROM读写** ```c void SavePasswordToEEPROM() { IIC_Start(); IIC_SendByte(0xA0); // 器件地址 // 写入密码到指定地址... IIC_Stop(); } void ReadPasswordFromEEPROM() { IIC_Start(); IIC_SendByte(0xA1); // 从指定地址读取密码... IIC_Stop(); } ``` --- ### **四、设计要点** 1. **状态机设计**:建议使用`switch-case`实现状态机(如:输入状态、验证状态、报警状态) 2. **消抖处理**:矩阵键盘扫描必须包含硬件/软件消抖 3. **显示优化**:输入密码时显示`*`,错误提示使用闪烁效果 4. **低功耗**:未操作时进入休眠模式(可选) 5. **安全机制**:密码加密存储(如异或加密) --- ### **五、调试技巧** 1. 使用**虚拟调试工具**验证按键响应 2. 单独测试EEPROM读写功能 3. 用LED模拟继电器动作(避免频繁开关硬件) 4. 通过串口打印调试信息(若题目允许) --- 如果需要更具体的代码片段(如矩阵键盘扫描、LCD驱动)或状态机实现细节,可以进一步说明!建议结合开发板原理图核对IO口分配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值