蓝桥杯第七届省赛 模拟风扇控制系统

蓝桥杯第七届省赛 模拟风扇控制系统

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

程序框架:
main函数:
两个界面:温度显示,时间倒计时

common函数:
定时器中断:控制LED,控制数码管显示,记录时间
scan_button() :S4,S5,S6,S7实现对应功能

onewire.c

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

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

//单总线延时函数
void Delay_OneWire(unsigned int t);   //先声明


//通过单总线向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;
}

//添加部分*************************************************
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t*=11;     //修改延时,增加到原来的11倍
	while(t--);
}

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

common.c

#include<common.h>

uchar dsp_buff[8]={11,10,11,10};
uchar L1,L2,L3;        //控制LED1,L2,L3
uchar count_key;       //控制按键刷新率
uchar mode_work=wind_sleep;  //工作模式
uchar temp=0,level=0;   //温度,工作模式区间
uchar PWM_duty;         //PWM占空比
uint count_sec=0;       //控制倒计时
uint remain_time;       //剩余工作时间
uint count_temp;        //控制温度刷新率
bit interface=work;     //显示界面

uchar dsp_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6}; //数字0~9,关闭,-

void system_init()
{
	uchar i;
	
	P0=0xff;P2=0x80;P2=0;
	P0=0x00;P2=0xa0;P2=0;
	
	for(i=0;i<70;i++)    //读取温度,待温度读取稳定后再显示
		temp=read_temp()+0.5;
	
	Timer0Init();
}

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

void tm0(void) interrupt 1
{
	static uchar bit_com=0,count_dsp=0;
	
	if(++count_dsp<=PWM_duty)  //控制占空比
		P34=1;                   //题目要求P34输出脉冲调制信号
	else
		P34=0;
	
	if(count_dsp==10)   //每隔1ms对外设进行一次引脚操作
	{
		count_dsp=0;
		P0=~(4*L3+2*L2+L1);P2=0x80;P2=0; //控制led
		
		P0=0;P2=0xc0;P2=0;
		P0=dsp_code[dsp_buff[bit_com]];P2=0xe0;P2=0;
		P0=1<<bit_com;P2=0xc0;P2=0;
		
		if(bit_com==7)
			bit_com=0;
		else
			bit_com++;
	}
	
	if(++count_sec==10000)
	{
		count_sec=0;
		if(remain_time>0)  //注意先判断再自减,防止溢出
			--remain_time;   //每隔1s自减一次
	}
	
	++count_key;
	++count_temp;
}

void scan_button(void)
{
	static uchar key_stat=0;
	uchar key_val=0,key_x=0,key_y=0;
	
	P3=0x0f;P4=0x00;     //行扫描
	if(!P30)	key_x=3;
	else if(!P31) key_x=2;
	else if(!P32) key_x=1;
	else if(!P33) key_x=0;
	
	P3=0xf0;P4=0xff;
	if(!P34) key_y=4;
	else if(!P35) key_y=3;
	else if(!P42) key_y=2;
	else if(!P44) key_y=1;
	
	key_val=key_x+key_y*4;   //综合行列扫描的结果,判断具体位置
	
	switch(key_stat)
	{
		case 0:
			if(key_val!=0) key_stat=1;  //第一次检测到有按键按下,状态为1
			break;
		case 1:
			if(key_val==0) key_stat=0;  //第二次(10ms后)若检测到无按键按下。即认为为抖动,返回状态0
			else
			{
				key_stat=2;
				
				if(key_val==7)    //按下S7,显示当前室温
				{
					interface=~interface;
				}
				
				if(interface==work)
				{
					switch(key_val)
					{
						case 4:       //按下S4为工作模式切换,3种模式循环切换
							if(++mode_work==14)
								mode_work=11;
							break;
							
						case 5:      //按下S5为定时按键,0,1,2分钟循环切换
							count_sec=0;
							if(level==0)
								remain_time=60;
							else if(level==1)
								remain_time=120;
							else if(level==2)
								remain_time=0;
							
							if(++level==3)
								level=0;
							break;
							
						case 6:     //按下S6为停止按键
							remain_time=0;
							level=0;
					}
				}
			}
			
			case 2:
				if(key_val==0) key_stat=0;
		}
}

main.c

#include<main.h>


extern uchar dsp_buff[];
extern uchar L1,L2,L3;        //控制LED1,L2,L3
extern uchar count_key;       //控制按键刷新率
extern uchar mode_work;  //工作模式
extern uchar temp,level;   //温度,工作模式区间
extern uchar PWM_duty;         //PWM占空比
extern uint count_sec;       //控制倒计时
extern uint remain_time;       //剩余工作时间
extern uint count_temp;        //控制温度刷新率
extern bit interface;     //显示界面



extern uchar dsp_code[]; //数字0~9,关闭,-

void main()
{
	system_init();
	
	while(1)
	{
		if(interface==work)  //工作界面显示
		{
			if(mode_work==wind_sleep)
			{
				dsp_buff[1]=1;
			}
			else if(mode_work==wind_nature)
			{
				dsp_buff[1]=2;
			}
			else if(mode_work==wind_normal)
			{
				dsp_buff[1]=3;
			}
			
			dsp_buff[4]=remain_time/1000%10;
			dsp_buff[5]=remain_time/100%10;
			dsp_buff[6]=remain_time/10%10;
			dsp_buff[7]=remain_time%10;
		}
		else if(interface==mesure) //室温显示界面
		{
			if(count_temp>7499)   //750ms刷新一次温度
			{
				count_temp=0;
				temp=read_temp()+0.5;
			}
			dsp_buff[1]=4;
			dsp_buff[4]=10;
			dsp_buff[5]=temp/10;
			dsp_buff[6]=temp%10;
			dsp_buff[7]=12;    //数码管第七位显示“C”
		}
		
		if(remain_time==0)
		{
			L1=L2=L3=0;  //熄灭所有LED
			PWM_duty=0;
		}
		else
		{
			if(mode_work==wind_sleep)
			{
				L1=1;     //点亮L1
				L2=L3=0;  //熄灭L2,L3
				PWM_duty=2;  //PWM占空比为20%
			}
			else if(mode_work==wind_nature)
			{
				L2=1;
				L1=L3=0;
				PWM_duty=3;    //PWM占空比为30%
			}
			else if(mode_work==wind_normal)
			{
				L3=1;
				L1=L2=0;
				PWM_duty=7;    //PWM占空比为70%
			}
		}
		
		if(count_key>99)  //10ms刷新一次按键,相当于消抖10ms
		{
			count_key=0;
			scan_button();
		}
	}
}
		
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rgb2gray

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值