蓝桥杯之单片机设计与开发(25)——2016_第七届_蓝桥杯_省赛——“模拟风扇控制系统”

版权声明:让结局不留遗憾,让过程更加完美。 https://blog.csdn.net/Xiaomo_haa/article/details/88227539

现在的蓝桥杯单片机组已经不考电路设计了,所以这个题的编程部分就比较简单,一般来说在DS18B20驱动写好的情况下,两个多小时就可以写好。

1、题目

一看题目,这个题需要用到DS18B20测温度,数码管和LED显示,以及独立按键进行设置等等。

有难度的一点在PWM输出,要求PWM频率在1Kz,由于我们在DS18B20的程序中有关中断的操作,所以想要完美的输出相应占空比的PWM,需要更改DS18B20中的开关总中断的位置。

2、代码

代码下载链接:https://download.csdn.net/download/xiaomo_haa/11002294

在第一次调试的时候,我是将DS18B20中的关中断 EA = 0 改为了禁止定时器0中断 ET0 = 0。这时使用逻辑分析仪观察波形,输出完美PWM波,但是我改为控制 EA 后,观察占空比20%时候的波形,有的部分占空比不是20%。

附上占空比为20%时候的波形图

控制ET0

控制EA

扫描二维码关注公众号,回复: 5498371 查看本文章

可以看到这个时候由于关总中断的影响,造成这个高电平时间减少,占空比小于20%

main.c 

#include <stc15.h>
#include "sys.h"

bit flag_2ms = 0, flag_500ms = 0;
bit flag_fan = 0, flag_temper = 0;
u8 mode = 1, modebackup = 1;
signed char min = 2, sec = 0;		//time
int temper_int = 0;				//temperture

void main(void)
{
	int temper = 0;
	bit res;
	
	AllInit();
	Timer0Init();
	Start18B20();
	EA = 1;
	while(1)
	{
		TubeShow();
		KeyPress();
		
    	if((sec == 0) && (min == 0))
			flag_fan = 0;
		else
			flag_fan = 1;

		if(flag_2ms)
		{
			flag_2ms = 0;
			KeyScan();
		}
		
		if(flag_500ms)		//show temperture
		{
			flag_500ms = 0;
			res = Get18B20Temp(&temper);
			if(res)
			{
				temper >>= 4;
				if((temper > 0) && (temper < 75))
					temper_int = temper;
			}
			Start18B20();
		}
	}
}

sys.c

#include "sys.h"

void AllInit(void)
{
	P2 = (P2 & 0x1f) | 0x80;	//open Y4C
	P0 = 0xff;
	P2 = (P2 & 0x1f) | 0xc0;	//open Y6C
	P0 = 0x00;
	P2 = (P2 & 0x1f) | 0xa0;	//open Y5C
	P0 = 0x00;
	P2 = P2 & 0x1f;
}

void Timer0Init(void)		//100微秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xAE;		//设置定时初值
	TH0 = 0xFB;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
}

void Timer0(void) interrupt 1
{
	static u8 T0count1 = 0, T0count3 = 0;
	static u16 T0count2 = 0, T0count4 = 0;
	u8 temp;
	
	T0count1 ++;
	
	if(flag_temper)
		T0count4 ++;
	else
		T0count4 = 0;
	
	if(flag_fan)
	{
		T0count2 ++;
		T0count3 ++;
	}
		
	if(T0count1 >= 20)		//2ms
	{
		T0count1 = 0;
		flag_2ms = 1;
	}
	
	if(T0count4 >= 2000)	//500ms	show temperture
	{
		T0count4 = 0;
		flag_500ms = 1;
	}
	
	if(flag_fan)
	{
		switch(modebackup)
		{
			case 1: temp = 2; break;
			case 2: temp = 3; break;
			case 3: temp = 7; break;
		}
		
		if(T0count3 <= temp)
			PWM = 1;
		else
		{
			PWM = 0;
			if(T0count3 >= 10)
				T0count3 = 0;
		}
	}
	else
		T0count3 = 0;
	
	if(T0count2 >= 10000)								//1s
	{
		T0count2 = 0;
		sec --;
		if(sec < 0)				//sec
		{
			sec = 59;
			min --;
			if(min < 0)			//min
			{
				min = 0;			//stop
				min = 0;			//stop
				flag_fan = 0;
			}
		}
	}
	LEDWork();
	TubeScan();
}

sys.h

#ifndef _SYS_H_
#define _SYS_H_

#include <stc15.h>
#include <intrins.h>
#include "ds18B20.h"

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

//External variables
extern bit flag_2ms, flag_500ms;
extern bit flag_fan, flag_temper;
extern u8 mode, modebackup;
extern signed char min, sec;
extern int temper_int;

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

sbit PWM = P3^4;

//Function
void AllInit(void);
void Timer0Init(void);

void TubeScan(void);
void TubeShow(void);
void LEDWork(void);

void KeyScan(void);
void KeyAction(unsigned char key);
void KeyPress(void);

#endif

display.c

#include "sys.h"

unsigned char code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 
                            0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,
														0xff, 0xbf};
u8 TubeBuff[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 smg1, smg2, smg3, smg4, smg5, smg6, smg7, smg8;

void TubeScan(void)
{
	static u8 index = 0;
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = 0xff;
	
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 0x01 << index;
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = TubeBuff[index];
	
	P2 = P2 & 0x1f;
	
	index ++;
	index &= 0x07;
}

void TubeShow(void)
{
	if((mode >= 1) && (mode <= 3))
	{
		smg1 = smg3 = 17;		//-
		smg2 = mode;
		smg4 = 16;					//shut down
		smg5 = min / 10;		//min
		smg6 = min % 10;
		smg7 = sec / 10;				//sec
		smg8 = sec % 10;
	}
	else if(mode == 4)
	{
		smg1 = smg3 = 17;		//-
		smg2 = mode;
		smg4 = smg5 = 16;		//shut down
		smg6 = temper_int / 10;
		smg7 = temper_int % 10;
		smg8 = 12;					//c
	}
	
	TubeBuff[0] = table[smg1];
	TubeBuff[1] = table[smg2];
	TubeBuff[2] = table[smg3];
	TubeBuff[3] = table[smg4];
	TubeBuff[4] = table[smg5];
	TubeBuff[5] = table[smg6];
	if(mode != 4)
		TubeBuff[5] &= 0x7f;

	TubeBuff[6] = table[smg7];
	TubeBuff[7] = table[smg8];
}


void LEDWork(void)
{
	u8 dat;
	
	dat = _crol_(0x7f, modebackup);
	P0 = 0xff;
	P2 = (P2 & 0x1f) | 0x80;
	if((sec != 0) || (min != 0))
		P0 = dat;

	P2 = P2 & 0x1f;
}

key.c

#include "sys.h"

u8 KeySta[] = {1, 1, 1, 1};
u8 KeyBackup[] = {1, 1, 1, 1};
u8 KeyBuff[] = {0xff, 0xff, 0xff, 0xff};

void KeyScan(void)
{
	u8 i;
	
	KeyBuff[0] = (KeyBuff[0] << 1) | S7;
	KeyBuff[1] = (KeyBuff[1] << 1) | S6;
	KeyBuff[2] = (KeyBuff[2] << 1) | S5;
	KeyBuff[3] = (KeyBuff[3] << 1) | S4;
	
	for(i = 0; i < 4; i ++)
	{
		if(KeyBuff[i] == 0xff)				//Key release
			KeySta[i] = 1;
		else if(KeyBuff[i] == 0x00)		//Key press
			KeySta[i] = 0;
		else
		{}
	}
}

void KeyAction(unsigned char key)
{
	if(key == 0)					//S7 temperture
	{		
		if(mode != 4)
		{
			mode = 4;
			flag_500ms = 1;
			flag_temper = 1;
		}
		else
		{
			flag_temper = 0;
			mode = modebackup;
		}
	}
	else if(key == 1)			//S6 stop
	{
		sec = 0;
		min = 0;
		flag_fan = 0;
	}
	else if(key == 2)			//S5 minter plus
	{
		min ++;
		if(min > 99)
			min = 99;
	}
	else if(key == 3)			//S4	mode change
	{
		if(mode == 4)
		{
			modebackup ++;
			if(modebackup == 4)
				modebackup = 1;
		}
		else
		{
			mode ++;
			if(mode == 4)
				mode = 1;
			modebackup = mode;	//backup mode
		}
	}
}

void KeyPress(void)
{
	u8 i;
	
	for(i = 0; i < 4; i ++)
	{
		if(KeySta[i] != KeyBackup[i])
		{
			if(KeySta[i] == 0)					//action when key press
				KeyAction(i);
			KeyBackup[i] = KeySta[i];
		}
	}
}

ds18b20.c

 #include "sys.h"

sbit DS18B20_IO = P1^4;

/*******************************************************************************
* 函数名	:Delayus
* 输入值	:unsigned int us
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月17日
* 功能描述:1T单片机延时指定us
* 备注		:最大形参65535,即最大延时65ms
*******************************************************************************/
void Delayus(unsigned int us)
{
	do{
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
	}while(--us);
}

/*******************************************************************************
* 函数名	:Get18B20Ack
* 输入值	:none
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月27日
* 功能描述:复位总线,获取18B20存在脉冲,以启动一次读写操作
* 备注		:
*******************************************************************************/
bit Get18B20Ack(void)
{
	bit ack;
	
	DS18B20_IO = 0;			//产生500us的复位脉冲
	Delayus(500);
	DS18B20_IO = 1;			//延时60us
//	EA = 0;							//禁止总中断
	ET0 = 0;
	Delayus(60);
	ack = DS18B20_IO;		//读取存在脉冲
	while(!DS18B20_IO);	//等待存在脉冲结束
	
//	EA = 1;							//重新使能总中断
	ET0 = 1;
	
	return ack; 	
}

/*******************************************************************************
* 函数名	:DS18B20Write
* 输入值	:unsigned char dat
* 返回值	:none
* 作者		:小默haa
* 时间		:2019年2月27日
* 功能描述:向18B20写入一个字节
* 备注		:dat为待写入字节
*******************************************************************************/
void DS18B20Write(unsigned char dat)
{
 	unsigned char mask;
						
	for(mask = 0x01; mask != 0; mask <<= 1)	//低位在先,依次移出8个bit
	{
//		EA = 0;
		ET0 = 0;
		DS18B20_IO = 0;				//产生2us低电平脉冲
		Delayus(2);
	 	if(dat & mask)				//输出该bit值
		 	DS18B20_IO = 1;
		else
		 	DS18B20_IO = 0;
//		EA = 1;
		ET0 = 1;
		Delayus(60);					//延时60us
		DS18B20_IO = 1;				//拉高通信引脚
	}
}

/*******************************************************************************
* 函数名	:DS18B20Read
* 输入值	:none
* 返回值	:unsigend char dat
* 作者		:小默haa
* 时间		:2019年2月27日
* 功能描述:从18B20读取一个字节
* 备注		:返回值为读取到的字节
*******************************************************************************/
unsigned char DS18B20Read(void)
{
 	unsigned char mask, dat = 0;
	
	for(mask = 0x01; mask != 0; mask <<= 1)	//低位在先,依次采集8个bit
	{
//		EA = 0;
		ET0 = 0;
		DS18B20_IO = 0;				//产生2us低电平脉冲
		Delayus(2);
		DS18B20_IO = 1;				//结束低电平脉冲,等待18B20输出数据
		Delayus(2);						//延时2us

	 	if(DS18B20_IO)				//读取通信引脚上的值
		 	dat |= mask;
//		EA = 1;
		ET0 = 1;
		Delayus(60);					//再延时60us
	}
	
	return dat;	
}

/*******************************************************************************
* 函数名	:Start18B20
* 输入值	:none
* 返回值	:bit ~ack
* 作者		:小默haa
* 时间		:2019年2月27日
* 功能描述:启动一次18B20温度转换
* 备注		:返回值为是否启动成功
*******************************************************************************/
bit Start18B20()
{
 	bit ack;
	static bit flag = 1;

	ack = Get18B20Ack();		//执行总线复位,并获取18B20应答
	if(ack == 0)						//如18B20正确应答,则启动一次转换
	{
		DS18B20Write(0xCC);		//跳过ROM操作
		
		if(flag)
		{
			flag = 0;
			DS18B20Write(0x4e);			//写暂存器指令4E
			DS18B20Write(0x4b);			//写高速缓存器TH高温限值75度
			DS18B20Write(0x00);			//写高速缓存器TL低温限值0度
			DS18B20Write(0x1f);			//写配置寄存器4
															//0x1f : 0.5000°C  转换时间93.75ms
															//0x3f : 0.2000°C  转换时间187.5ms
															//0x5f : 0.1250°C  转换时间375ms
															//0x7f : 0.0625°C  转换时间750ms
		}
		
		ack = Get18B20Ack();		//执行总线复位,并获取18B20应答
		if(ack == 0)						//如18B20正确应答,则启动一次转换
		{
			DS18B20Write(0xCC);		//跳过ROM操作
			DS18B20Write(0x44);		//启动一次温度转换
		}
	}

	return ~ack;						//ack == 0 表示操作成功,所以返回值对其取反
}

/*******************************************************************************
* 函数名	:Get18B20Temp
* 输入值	:int *temp
* 返回值	:bit ~ack
* 作者		:小默haa
* 时间		:2019年2月27日
* 功能描述:读取18B20转换的温度值
* 备注		:返回值为是否读取成功
*******************************************************************************/
bit Get18B20Temp(int *temp)
{
 	bit ack;
	unsigned char LSB, MSB;			//16bit温度值的低字节和高字节

	ack = Get18B20Ack();				//执行总线复位,并获取18B20应答
	if(ack == 0)								//如18B20正确应答,则读取温度值
	{
	 	DS18B20Write(0xCC);				//跳过ROM操作
		DS18B20Write(0xBE);				//发送读命令
		LSB = DS18B20Read();			//读温度值的低字节
		MSB = DS18B20Read();			//读温度值的高字节
		*temp = ( MSB << 8) + LSB;	//合成16bit的整数
	}

	return ~ack;								//ack == 0 表示操作应答,所以返回值为1其取反值
} 

ds18b20.h

#ifndef __DS18B20_H
#define __DS18B20_H


//单总线延时函数
void Delayus(unsigned int us);
bit Get18B20Ack(void);
void DS18B20Write(unsigned char dat);
unsigned char DS18B20Read(void);
bit Start18B20();
bit Get18B20Temp(int *temp);


#endif

猜你喜欢

转载自blog.csdn.net/Xiaomo_haa/article/details/88227539