蓝桥杯单片机——第十二届蓝桥杯单片机第一场省赛

蓝桥杯单片机——第十二届蓝桥杯单片机第一场省赛

一、赛题分析

前两天实验室的学妹把开发板还给我了,刚好今天没什么事做,就来做做今天的省赛题目。 在下是参加的去年的蓝桥杯单片机组,今年也刚参加的嵌入式组的省赛,已经好几个月没有摸单片机的板子了,以为会很生疏,看了一下之前的代码,然后做了一下今年的赛题,发现很快就找回感觉了。发现单片机组相对于嵌入式组确实要简单得多。 真的不难呀,大家一定要上手把几个基础模块过一遍,然后做两三套赛题,进决赛都挺容易的,相信我。

这一届的赛题也就中规中矩吧,已经完了前几届赛题的难度,总之这一届的还是偏简单。除了基础的数码管显示,矩阵键盘,LED之外,要是临近比赛,连这些都没有熟悉的画,自己去面壁思过吧。除此之外还考察了PCF8591的DAC功能和DS18B20。要说稍微有点难度的就是矩阵键盘和DS18B20的小数显示了吧,因为可能有些人偷懒根本就没有看过这两个部分。至于PCF8591的DAC相较于ADC简单得多,没有看过的,看一下程序应该就懂了,完整的程序可以参考第三部分。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、问题总结

发现没有什么问题可以总结的,都不难…

三、代码

#include "STC15F2K60S2.h"
#include "onewire.h"
#include "iic.h"

#define u8 unsigned char
#define u16 unsigned int
	
#define					TEMP_INTERFACE						0
#define					DAC_INTERFACE							1
#define					SETTING_INTERFACE					2
	
#define get() (P3 & 0X3F) | ((P4 & 0X10) << 3) | ((P4 & 0X04) << 4)
	
u8 code TAB[] = {
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88};
u8 disbuf[] = {
    
    0,1,2,3,4,5,6,7,8};

u8 smg_cnt = 0;

u8 key_buf = 0;

u16 sec_tick = 0;
u8 sec_cnt = 0;

u8 interface = 0;

u8 temperature_para = 25;
u8 temperature_para_temp = 25;

bit mode = 0;

float volt = 3.25;

float temperature = 0.0;

void write_pcf8591(unsigned char dat)
{
    
    
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

float read_temperature(void)
{
    
    
	unsigned char high,low;
	unsigned int temp;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	low = Read_DS18B20();
	high = Read_DS18B20();
	
	temp = high;
	temp <<= 8;
	temp |= low;
	
	return temp * 0.0625;
}

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

	i = 59;
	j = 90;
	do
	{
    
    
		while (--j);
	} while (--i);
}

void set_port(u8 p2,u8 p0)
{
    
    
	P2 = (P2 & 0x1F) | p2;	// 使能74HC573,与上0x1F是为了不影响其他的端口
	P0 = p0;
	P2 &= 0x1F;							// 将数据锁存
}

void allinit(void)
{
    
    
	set_port(0x80,0xFF);	// 关闭所有LED
	set_port(0xA0,0x00);	// 关闭继电器,蜂鸣器等外设
	set_port(0xC0,0x00);	// 关闭数码管位选
	set_port(0xE0,0x00);	// 关闭数码管段选
}

void display(void)
{
    
    
	if(interface == TEMP_INTERFACE)
	{
    
    
		disbuf[1] = 12;
		disbuf[2] = 11;
		disbuf[3] = 11;
		disbuf[4] = 11;
		disbuf[5] = (u16)(temperature * 100) / 1000;
		disbuf[6] = (u16)(temperature * 100) / 100 % 10;
		disbuf[7] = (u16)(temperature * 100) / 10 % 10;
		disbuf[8] = (u16)(temperature * 100) / 1000 % 10;
	}
	else if(interface == SETTING_INTERFACE)
	{
    
    
		disbuf[1] = 13;
		disbuf[2] = 11;
		disbuf[3] = 11;
		disbuf[4] = 11;
		disbuf[5] = 11;
		disbuf[6] = 11;
		disbuf[7] = temperature_para_temp / 10;
		disbuf[8] = temperature_para_temp % 10;
	}
	else if(interface == DAC_INTERFACE)
	{
    
    
		disbuf[1] = 14;
		disbuf[2] = 11;
		disbuf[3] = 11;
		disbuf[4] = 11;
		disbuf[5] = 11;
		disbuf[6] = (u16)(volt * 100) / 100;
		disbuf[7] = (u16)(volt * 100) / 10 % 10;
		disbuf[8] = (u16)(volt * 100) % 10;
	}
	
}

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

void KBD(void)
{
    
    
	u8 key_temp ;
	P3 = 0X0F; P44 = 0; P42 = 0;
	key_temp = get();
	P3 = 0XF0; P44 = 1; P42 = 1;
	key_temp |= get();
	
	if(key_temp != 0xff && !key_buf)
	{
    
    
		Delay5ms();
		P3 = 0X0F; P44 = 0; P42 = 0;
		key_temp = get();
		P3 = 0XF0; P44 = 1; P42 = 1;
		key_temp |= get();
		if(key_temp != 0xff && !key_buf)
		{
    
    	
			key_buf = key_temp;
		}
	}
	else if(key_temp == 0xff && key_buf)
	{
    
    
		Delay5ms();
		P3 = 0X0F; P44 = 0; P42 = 0;
		key_temp = get();
		P3 = 0XF0; P44 = 1; P42 = 1;
		key_temp |= get();
		if(key_temp == 0xff && key_buf)
		{
    
    	
			switch(key_buf)	// 这里要特别注意是key_buf,不要粗心写成了key_temp
			{
    
    
//				case 0x7e: disbuf[1] = 7; disbuf[2] = 10; disbuf[3] = 10; break;
//				case 0x7d: disbuf[1] = 6; disbuf[2] = 10; disbuf[3] = 10; break;
				case 0x7b: 				// s5
					mode = !mode;
				
				break;
				case 0x77:  			// s6
					switch(interface)
					{
    
    
						case TEMP_INTERFACE: 
							temperature_para_temp = temperature_para;
							interface = SETTING_INTERFACE; 
							
						break;
						case SETTING_INTERFACE:
							temperature_para = temperature_para_temp;
							interface = DAC_INTERFACE; 
						break;
						case DAC_INTERFACE: 
							interface = TEMP_INTERFACE; 
						break;
					}
				break;
				
//				case 0xbe: disbuf[1] = 1; disbuf[2] = 1; disbuf[3] = 10; break;
//				case 0xbd: disbuf[1] = 1; disbuf[2] = 0; disbuf[3] = 10; break;
				case 0xbb:   			// s9
					temperature_para_temp++;
				
				break;
				case 0xb7:   			// s8
					temperature_para_temp--;
				break;
				
//				case 0xde: disbuf[1] = 1; disbuf[2] = 5; disbuf[3] = 10; break;
//				case 0xdd: disbuf[1] = 1; disbuf[2] = 4; disbuf[3] = 10; break;
//				case 0xdb: disbuf[1] = 1; disbuf[2] = 3; disbuf[3] = 10; break;
//				case 0xd7: disbuf[1] = 1; disbuf[2] = 2; disbuf[3] = 10; break;
//				                       
//				case 0xee: disbuf[1] = 1; disbuf[2] = 9; disbuf[3] = 10; break;
//				case 0xed: disbuf[1] = 1; disbuf[2] = 8; disbuf[3] = 10; break;
//				case 0xeb: disbuf[1] = 1; disbuf[2] = 7; disbuf[3] = 10; break;
//				case 0xe7: disbuf[1] = 1; disbuf[2] = 6; disbuf[3] = 10; break;				
			}
			key_buf = 0;
		}
	}
	
	
}

void smg_proc(void)
{
    
    
	set_port(0xc0, 0x01 << smg_cnt);
	if((interface == TEMP_INTERFACE && smg_cnt == 5) || (interface == DAC_INTERFACE && smg_cnt == 5))
		set_port(0xe0, TAB[disbuf[smg_cnt + 1]]  & 0x7F);
	else
		set_port(0xe0, TAB[disbuf[smg_cnt + 1]]);
	if(++smg_cnt >= 8) smg_cnt = 0;
	
	if(++sec_tick == 1000)
	{
    
    
		sec_tick = 0;
		(sec_cnt != 59)?(sec_cnt++):(sec_cnt = 0);
	}
}

void dac_proc(void)
{
    
    
	if(mode == 0)
	{
    
    
		if(temperature < temperature_para)
			write_pcf8591(0);
		else
			write_pcf8591(255);
	}
	else
	{
    
    
		if(temperature < 20)
			write_pcf8591(0);
		else if(temperature > 40)
			write_pcf8591(255);
		else
			write_pcf8591((6.0 / 40 * temperature - 2) / 5.0 * 255);
	}
}

void led_proc(void)
{
    
    
	u8 led_state = 0xff;
	if(mode == 0)
		led_state &= 0xFE;
	if(interface == TEMP_INTERFACE)
		led_state &= 0xFD;
	else if(interface == SETTING_INTERFACE)
		led_state &= 0xFB;
	else if(interface == DAC_INTERFACE)
		led_state &= 0xF7;
	set_port(0x80,led_state);
}

/********************* Timer2中断函数************************/
void timer2_int (void) interrupt 12
{
    
    
	smg_proc();
	
	led_proc();
}


void main(void)
{
    
    
	allinit();											// 上电初始化
	Timer2Init();										// 定时器2初始化
	IE2 |= 0x04;                    // 开定时器2中断
	EA = 1;													// 开启总中断
	
	while(1)
	{
    
    
		temperature = read_temperature();
		
		dac_proc();
		
		display();
		
		KBD();
	}
}

完整工程下载点我

猜你喜欢

转载自blog.csdn.net/qq_43715171/article/details/116534291