第十五届单片机模拟考试IV

发布于:2025-04-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

题目 

 

 

 

 还是一道很常规的题目

按键功能

S4界面切换,s8s9修改参数,有上下限限制。

/*按键函数区域*/
void Key_Proc(){
	
	if(Key_Slow) return;
	Key_Slow = 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:
			if(++Seg_Mode == 3) Seg_Mode = 0;//显示界面切换
		break;
		case 8:
			if(Seg_Mode == 2){//参数界面有效-
				temp_limit = temp_limit==20?35:temp_limit-1;
			}
		break;
		case 9:
			if(Seg_Mode == 2){//参数界面有效+
				temp_limit = temp_limit==35?20:temp_limit+1;
			}
		break;
	}
}

显示功能 

界面1显示频率,高位熄灭,界面二度数ds18b20数据,高位熄灭,界面3显示设置的温度参数

都是常规的显示功能

DAC功能

DAC功能与ne555获取的频率有关,是常见的分段处理一次函数形式。

对于这些小数类型的电压, 我们直接对应的电压*51,再进行四舍五入来获取对应的char值,进行dac输出更加准确。让D_Volt直接就是char类型的值,不再外面进行额外操作。 

/*数码管显示函数区域*/
void Seg_Proc(){
	if(Seg_Slow) return;
	Seg_Slow = 1;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~数码管减速防止再次进入
	
	tempt = rd_temperature();
	
	if(freq<=200){
		D_Volt = 25;
	}
	else if(freq>=2000){
		D_Volt = 230;
	}
	else{
		D_Volt = (freq-200)*0.11 + 25;
	}
	Da_write(D_Volt);
	
	if(tempt>temp_limit){
		Relay_flag = 1;
	}
	else Relay_flag = 0;
	
	if(tempt>30){
		L8_start = 1;
	}
	else L8_start = 0;
	
	switch(Seg_Mode){
		case 0://信号界面
			Seg_Buf[0] = 11;//P
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = freq>10000?freq/10000:10;
			Seg_Buf[4] = freq>1000?freq%10000/1000:10;
			Seg_Buf[5] = freq>100?freq%1000/100:10;
			Seg_Buf[6] = freq>10?freq%100/10:10;
			Seg_Buf[7] = freq%10;
			Point[6] = 0;
		break;
		case 1:
			Seg_Buf[0] = 12;//C
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			Seg_Buf[4] = 10;
			Seg_Buf[5] = (unsigned char)tempt>10?(unsigned char)tempt/10:10;
			Seg_Buf[6] = (unsigned char)tempt%10;
			Point[6] = 1;
			Seg_Buf[7] = (unsigned int)(tempt*10)%10;
		break;
		case 2:
			Point[6] = 0;
			Seg_Buf[0] = 13;//U
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			Seg_Buf[4] = 10;
			Seg_Buf[5] = 10;
			Seg_Buf[6] = temp_limit/10;
			Seg_Buf[7] = temp_limit%10;
		break;
	}
	
}

继电器Led功能 

对于采集到的温度进行判断,就能完成继电器控制和L8闪烁控制,L12就是常规的界面指示灯。

/*Led函数区域*/
void Led_Proc(){
	Relay(Relay_flag);
	Led_Buf[0] = (Seg_Mode == 0);
	Led_Buf[1] = (Seg_Mode == 1);
	Led_Buf[7] = L8_flag;
}

 完整主函数

 

/*头文件区域*/
#include <STC15F2K60S2.H>
#include <Key.h>
#include <Seg.h>
#include <Led.h>
#include <Init.h>
#include <onewire.h>
#include <iic.h>
#include <intrins.h>
/*参数变量区域*/
unsigned char Seg_Slow,Key_Slow;
unsigned char Key_Up,Key_Down,Key_Val,Key_Old;
unsigned char Seg_Pos;
//数码管Led函数区域
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Led_Buf[8] = {0,0,0,0,0,0,0,0};
unsigned char Point[8] = {0,0,0,0,0,0,0,0};
//显示模式
unsigned char Seg_Mode;//0是信号,1温度,2参数
//数据变量区域
float tempt;//温度数据
unsigned char temp_limit = 25;//温度参数
unsigned char D_Volt;//DAC输出电压参数
unsigned int Time_1s;
unsigned int freq;//频率值
unsigned char Time_100ms;
bit L8_flag;
bit L8_start;
bit Relay_flag;
/*按键函数区域*/
void Key_Proc(){
	
	if(Key_Slow) return;
	Key_Slow = 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:
			if(++Seg_Mode == 3) Seg_Mode = 0;//显示界面切换
		break;
		case 8:
			if(Seg_Mode == 2){//参数界面有效-
				temp_limit = temp_limit==20?35:temp_limit-1;
			}
		break;
		case 9:
			if(Seg_Mode == 2){//参数界面有效+
				temp_limit = temp_limit==35?20:temp_limit+1;
			}
		break;
	}
}
/*数码管显示函数区域*/
void Seg_Proc(){
	if(Seg_Slow) return;
	Seg_Slow = 1;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~数码管减速防止再次进入
	
	tempt = rd_temperature();
	
	if(freq<=200){
		D_Volt = 25;
	}
	else if(freq>=2000){
		D_Volt = 230;
	}
	else{
		D_Volt = (freq-200)*0.11 + 25;
	}
	Da_write(D_Volt);
	
	if(tempt>temp_limit){
		Relay_flag = 1;
	}
	else Relay_flag = 0;
	
	if(tempt>30){
		L8_start = 1;
	}
	else L8_start = 0;
	
	switch(Seg_Mode){
		case 0://信号界面
			Seg_Buf[0] = 11;//P
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = freq>10000?freq/10000:10;
			Seg_Buf[4] = freq>1000?freq%10000/1000:10;
			Seg_Buf[5] = freq>100?freq%1000/100:10;
			Seg_Buf[6] = freq>10?freq%100/10:10;
			Seg_Buf[7] = freq%10;
			Point[6] = 0;
		break;
		case 1:
			Seg_Buf[0] = 12;//C
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			Seg_Buf[4] = 10;
			Seg_Buf[5] = (unsigned char)tempt>10?(unsigned char)tempt/10:10;
			Seg_Buf[6] = (unsigned char)tempt%10;
			Point[6] = 1;
			Seg_Buf[7] = (unsigned int)(tempt*10)%10;
		break;
		case 2:
			Point[6] = 0;
			Seg_Buf[0] = 13;//U
			Seg_Buf[1] = 10;
			Seg_Buf[2] = 10;
			Seg_Buf[3] = 10;
			Seg_Buf[4] = 10;
			Seg_Buf[5] = 10;
			Seg_Buf[6] = temp_limit/10;
			Seg_Buf[7] = temp_limit%10;
		break;
	}
	
}
/*Led函数区域*/
void Led_Proc(){
	Relay(Relay_flag);
	Led_Buf[0] = (Seg_Mode == 0);
	Led_Buf[1] = (Seg_Mode == 1);
	Led_Buf[7] = L8_flag;
}

/*定时器0初始化函数区域*/
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x05;
	TL0 = 0x00;				//设置定时初始值
	TH0 = 0x00;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
}
/*定时器1初始化函数*/
void Timer1_Init(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 Timer1_Service() interrupt 3
{
	if(++Seg_Slow == 100) Seg_Slow = 0;
	if(++Key_Slow == 20) Key_Slow = 0;
	
	if(++Seg_Pos == 8) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Point[Seg_Pos]);
	Led_Disp(Seg_Pos,Led_Buf[Seg_Pos]);
	
	if(++Time_1s == 1000){//获取频率值
		Time_1s = 0;
		freq = (TH0<<8)|TL0;
		TL0 = TH0 = 0;
	}
	
	if(L8_start){
		if(++Time_100ms == 100){
			Time_100ms = 0;
			L8_flag ^= 1;
		}
	}
	else{
		Time_100ms = 0;
		L8_flag = 0;
	}
	
}
//750ms延时保证温度数据正常显示
void Delay750ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;

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


/*主函数区域*/
void main(){
	Sys_Init();
	Timer1_Init();
	Timer0_Init();
	tempt = rd_temperature();//~~~~~~~~~~~~~~~~~~~~~~~~~~~温度上电读取一次
	Delay750ms();//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~配合延时750ms让温度显示没有系统默认值
	while(1){
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}