《蓝桥杯真题》:2017年单片机省赛(第八届)(内附两种代码实现风格)

有关题目

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

实现代码

注意:①注意修改驱动代码时要留意一下onewire.c中单总线延时函数,是STC89C52RC,还是15系列的,15系列的单片机速度比51快8~12倍,需要修改对应的延时函数。②实现pwm控制电机实现不同的转动速度,通过调占空比实现的。需要结合点击转动的频率。③剩余时间为零时,需要停止pwm信号的输出。

onewire.c中具体修改如下

//单总线延时函数
void Delay_OneWire(unsigned int t) 
{
	while(t--)
	{
		signed char i = 0;
			for (i = 0; i < 12; i++);
	}
}

实现风格①main.c

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

#define uchar unsigned char
#define uint unsigned int

sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

uchar temp;//实时温度
uchar time;//倒计时时间
uchar mod = 1;//模式
code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf, 0xc6}; 
//-, C  11 12

uchar pwm_val, pwm_cnt = 0;

bit flag_s7 = 0;//初始化0为显示剩余工作时间

void sys_init();//系统初始化
uchar rd_temp();
void key_handle();
void led();

//显示模块
void dsp_smg_bit(uchar pos, val);//位显示数码管
void display();
void dsp_time();
void dsp_temp();
void delay_k(uchar t);
void Delay1ms();		//@12.000MHz


void main()
{
	sys_init();
	while(1)
	{
		temp = rd_temp();//实时读取温度
		key_handle();//按键处理
		display();//界面显示
		if (!time)
		{
			ET1 = 0;
			P34 = 0;
		}
		else 
		{
			ET1 = 1;
		}
		led();//led显示
	}

}

void led()
{
	if (time > 0)
	{
		if (mod == 1)
		{
			P2 = (P2 & 0x1f) | 0x80;
			L1 = 0;
		}
		else if (mod == 2)
		{
			P2 = (P2 & 0x1f) | 0x80;
			L2 = 0;
		}
		else if (mod == 3)
		{
			P2 = (P2 & 0x1f) | 0x80;
			L3 = 0;
		}
	}
	else 
	{
		P2 = (P2 & 0x1f) | 0x80;
		P0 = 0xff;
	}
	
}


void display()
{
	if (!flag_s7)
	{
		dsp_time();
	}
	else 
	{
		dsp_temp();
	}
}


void dsp_time()
{
	dsp_smg_bit(1, 11);
	dsp_smg_bit(2, mod);
	dsp_smg_bit(3, 11);
	dsp_smg_bit(4, 10);
	
	dsp_smg_bit(5, 0);
	dsp_smg_bit(6, time / 100);
	dsp_smg_bit(7, time / 10 % 10);
	dsp_smg_bit(8, time % 10);
}
void dsp_temp()
{
	dsp_smg_bit(1, 11);
	dsp_smg_bit(2, 4);
	dsp_smg_bit(3, 11);
	dsp_smg_bit(4, 10);
	dsp_smg_bit(5, 10);
	
	dsp_smg_bit(6, temp / 10);
	dsp_smg_bit(7, temp % 10);
	dsp_smg_bit(8, 12);
}

void key_handle()
{
	if (!S4)
	{
		delay_k(20);
		if (!S4)
		{
			while(!S4)
			{
				display();
			}
			mod++;
			if (mod >= 4)
				mod = 1;
			
			//不同模式,对应转机速度不同
			if (mod == 1)
				pwm_val = 2;
			else if (mod == 2)
				pwm_val = 3;
			else if (mod == 3)
				pwm_val = 7;
		}
	}
	
	if (!S5)
	{
		delay_k(20);
		if (!S5)
		{
			while(!S5)
			{
				display();
			}
			time += 60;
			if (time >= 180)
				time = 0;
		}
	}
	
	if (!S6)
	{
		delay_k(20);
		if (!S6)
		{
			while(!S6)
			{
				display();
			}
			time = 0;	
		}
	}
	if (!S7)
	{
		delay_k(20);
		if (!S7)
		{
			while(!S7)
			{
				display();
			}
			flag_s7 = !flag_s7;
		}
	}

}

void dsp_smg_bit(uchar pos, val)
{
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 1 << (pos - 1);
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = tab[val];
	Delay1ms();
	P0 = 0xff;
	P2 &= 0x1f;
}
uchar rd_temp()
{	
	uchar t = 0, l, h;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	l = Read_DS18B20();
	h = Read_DS18B20();
	
	t = (h << 4);
	t |= (l >> 4);
	
	return t;
	
}
void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
}

void delay_k(uchar t)//大约延时t * 10 us,用于消抖
{
	while(t--)
		display();
}

//100us * 10
void timer1() interrupt 3
{
	if (++pwm_cnt <= pwm_val)
	{
		P34 = 1;
	}
	else
	{
		P34 = 0;
		if (pwm_cnt == 10)
			pwm_cnt = 0;
	}
}
void timer0() interrupt 1
{
	static uint i1 = 0;
	
	if (++i1 == 500)
	{
		i1 = 0;
		if (time > 0)
			--time;	
	}
}
void sys_init()
{
	P2 = (P2 & 0x1f) | 0xa0;
	P0 = 0xaf;
	
	P2 = (P2 & 0x1f) | 0x80;
	P0 = 0xff;
	P2 &= 0x1f;
	
	
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD = 0x00;		//设置定时器模式
	
	//2ms
	TL0 = 0x30;		//设置定时初值
	TH0 = 0xF8;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	//100us
	TL1 = 0x9C;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET0 = 1;
	ET1 = 0;//由time 决定是否打开
	EA = 1;
}

实现风格②main.c

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

#define uchar unsigned char
#define uint unsigned int

//PWM
unsigned char pwm_value  = 2;
unsigned char pwm_count = 0;


uchar key_val = 20;

uchar wind = 1;
uchar time = 0;

uchar flag =  0;
uchar flag_temp = 0;
uchar temp = 0;

unsigned char dspcom = 0;//位选线
unsigned char dspbuf[8] = {11,10,11,10,10,10,10,10};//显示缓冲区
code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6}; 
//11 - 12 C
void sys_init(void);		

void key_scanf(void);
void key_proc();
void display();
uchar read_temputerature();
void led_control();

void main()
{
	sys_init();
	while(1)
	{
		key_proc();
		if (flag_temp)
		{
			flag_temp = 0;
			temp = read_temputerature();
		}
		
		//实时显示
		if (flag == 1)
		{
			dspbuf[1] = 4;
			dspbuf[4] = 10;
			dspbuf[5] = temp / 10;
			dspbuf[6] = temp % 10;
			dspbuf[7] = 12;
		}
		else 
		{
			dspbuf[1] = wind;
			dspbuf[4] = 0;
			dspbuf[5] = time / 100;
			dspbuf[6] = time / 10 % 10;
			dspbuf[7] = time % 10;
		}
		
		led_control();
		
		if (!time)
		{
			ET1 = 0;
			P34 = 0;
		}
		else 
		{
			ET1 = 1;
		}
		
		if (wind == 1) pwm_value = 2;
		else if (wind == 2) pwm_value = 3;
		else if (wind == 3) pwm_value = 7;
	}
}
void led_control()
{
	if (time != 0)
	{
			if (wind == 1)
		{
			P2 = (P2 & 0x1f) | 0x80;
			P0 = 0xfe;
			P2 &= 0x1f; 
		}
		else if (wind == 2)
		{
			P2 = (P2 & 0x1f) | 0x80;
			P0 = 0xfd;
			P2 &= 0x1f;
		}
		else if (wind == 3)
		{
			P2 = (P2 & 0x1f) | 0x80;
			P0 = 0xfb;
			P2 &= 0x1f;
		
		}
	}
	else
	{
		P2 = (P2 & 0x1f) | 0x80;
		P0 = 0xff;
		P2 &= 0x1f;
	}

}
uchar read_temputerature()
{
	uchar l, h, t = 0;
	
	 init_ds18b20();
	 Write_DS18B20(0xCC);
	 Write_DS18B20(0x44);
	 //这边看情况延时
	 //while (!DQ);  //Delay200us();
	
	 
	 init_ds18b20();
	 Write_DS18B20(0xCC);
	 Write_DS18B20(0xbe);
	 
	 l = Read_DS18B20();
	 h = Read_DS18B20();

	t |= h;
	t <<= 4;
	t |= (l >> 4);
	
	return t;
	
}
void sys_init()
{
	P2 = (P2 & 0x1f) | 0x80;
	P0 = 0xff;
	P2 &= 0x1f;
	
	P2 = (P2 & 0x1f) | 0xa0;
	P0 = 0xaf;
	P2 &= 0x1f;
	
	
	//2ms
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x30;		//设置定时初值
	TH0 = 0xF8;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;
	
	//100us
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x9C;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET0 = 1;
	ET1 = 0;
	EA = 1;
}

//显示函数
void display(void)
{   
	//消隐
	P2 = (P2&0x1f) | 0xe0; 
	P0 = 0xff;
	P2 &= 0x1f;

	//位选
	P2 = (P2&0x1f) | 0xc0; 
	P0 = 1<<dspcom;
	P2 &= 0x1f;

	//段选
  	P2 = ((P2&0x1f)|0xE0); 
	P0 = tab[dspbuf[dspcom]];
	P2 &= 0x1f;
	 
  if(++dspcom == 8)
	{
		dspcom = 0;
	} 		
}	
 
void key_proc()
{
	switch(key_val)
	{
		case 7:
		{
			flag = !flag;
			key_val = 20;
			break;
		}
		case 6:
		{
			time = 0;
			key_val = 20;
			break;
		}
		case 5:
		{
			time += 60;
			if (time >= 180)
			{
				time = 0;
			}		
			key_val = 20;
			break;
		}
		case 4:
		{
			wind++;
			if (wind >= 4)
				wind = 1;
			key_val = 20;
			break;
		}
	
	}

}

//按键扫描
void key_scanf(void)
{
	static unsigned char key_st = 0;
	
	switch(key_st){
		case 0:
			if((P3&0x0F) != 0x0F){
				key_st = 1;
			}
			break;
		case 1:
			if((P3&0x0F) != 0x0F){
				key_st = 2;
				if((P3&0x0F) == 0x0E) key_val = 7;
				else if((P3&0x0F) == 0x0D) key_val = 6;
				else if((P3&0x0F) == 0x0B) key_val = 5;
				else if((P3&0x0F) == 0x07) key_val = 4;
			}
			else{
				key_st = 0;	//按键抖动
			}
			break;
		case 2:
			if((P3&0x0F) == 0x0F){
				key_st = 0;
			}
			else{
				;
			}
			break;
	}
}

void timer0() interrupt 1
{
	static uint intr1 = 0, intr2 = 0, intr3 = 0;
	display();//2ms
	
	if (++intr1 == 500)//1s
	{
		intr1 = 0;
		if (time > 0)
			time--;
	}
	//300ms温度扫描
	if (++intr2 == 150)
	{
		intr2 = 0;
		flag_temp = 1;
	}
	
	//30ms检测按键状态
	if (++intr3 == 15)
	{
		intr3 = 0;
		key_scanf();
	}
}


//100us * 10 = 1s
void timer1(void) interrupt 3
{	
	if (++pwm_count <= pwm_value)
	{
		P34 = 1;
	}
	else 
	{
		P34 = 0;
		if (++pwm_count == 10)
			pwm_count = 0;
	}
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H


void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);

#endif

onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--)
	{
		signed char i = 0;
			for (i = 0; i < 12; i++);
	}
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
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;
}

//DS18B20设备初始化
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;
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值