IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 蓝桥杯CT107D:2017年第七届真题——模拟风扇 -> 正文阅读

[C++知识库]蓝桥杯CT107D:2017年第七届真题——模拟风扇

PDF文件链接

链接地址:链接:https://pan.baidu.com/s/1qNA1aDIerGZU4Fpdy_blRw????? 提取码:9956

编程题解答

?思路:

??? 1.这题里面我们要用到数码管、定时器、LED、独立按键、DS18B20、PWM这几个部分。

??? 2.独立按键S4切换风速模式我们还是需要用到一个变量来计数,按下S4我们就让这个变量改变,当变量改变到什么时候时,我们执行数模式切换工作,这个功能我们通常运用if语句以及switch语句结合来实现。

 3.独立按键的扫描我们还是用状态机的方法,也可以使用一些简单的if、else if语句还实现,但是都要记得在按下后给予一个返回值,这是用来识别是哪一个按键按下的标志。

 4.数码管的display我们不用怎么说,就是按照以往的这个样子写,简单万能。

 5.PWM的话还是简单的一个占空比的运用我们就不多说了。值得一提的是PWM的定时我们要选择100us,不然会不准确。

 6.温度测量是比较容易出意外的,我在写的时候就好几次一直写不出来。温度测量一直不准确,原因是我们在定义变量的时候要统一变量的类型,比如我们在ds18b20.c中的读取温度的函数是float型的,但是我们在主函数中定于的接收温度的变量是char型的话则会造成干扰,无法读出准确的温度数据。这里需要强调的一点是我们就收温度数据最好是使用int型的变量接收,因为float型的数据在给int型的时候会直接省略小数点后面的数,而我们题目要求的是显示两位数的温度数据,所以我们直接用int型的数据进行接收。

?????????接下来开始码。头文件STC.h我们利用STC-ISP软件自动生成添加到工程文件夹中即可。HC138.h是我个人比较喜欢的自定义函数。

#include "STC.h"
void HC138(unsigned int n)
{
	switch(n)
	{
		case 4:P2=(P2&0x1f)|0x80;break;
		case 5:P2=(P2&0x1f)|0xa0;break;
		case 6:P2=(P2&0x1f)|0xc0;break;
		case 7:P2=(P2&0x1f)|0xe0;break;
	}
}

?????????下面是主函数部分

#include "STC.h"
#include "HC138.h"
#include "ds18b20.h"

//======================== 0    1     2    3    4    5    6   7    8    9   10-  11. 12全黑  13C
code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xBF,0x7F,0xff,0xc6};
unsigned char dspcom;
unsigned char dspbuf[]={10,1,10,12,12,0,0,0};
unsigned char jm_mod=0,key_val=0;//jm_mod控制温度风速界面的变量
unsigned char dsp_time=0;
unsigned char fs_mod=1;//控制风速的变量
unsigned int n1=0,n2=0,n3=0;//定时机计时
unsigned int temper;//接受温度数据
unsigned char pwm_value  = 2;
unsigned char pwm_counter = 0;

bit temp_flag;
sbit PWM_OUT = P3^4;  


void display()
{	
	HC138(7);
	P0=0xff;
	P2&=0x1f;
	
	HC138(6);
	P0=1<<dspcom;
	P2&=0x1f;
	
	HC138(7);
	P0=tab[dspbuf[dspcom]];
	P2&=0x1f;
	
	if(++dspcom==8)
	{
		dspcom=0;
	}
}

void key_scanf()//独立按键的扫描方式,可以直接套用这个代码
{
	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;
				}
				break;
	}
}

void key_function()
{
	static unsigned char add_time=0;
	switch(key_val)
	{
		case 7://风速温度界面切换
				if(jm_mod==0)
				{
					jm_mod=1;
				}
				else
				{
					jm_mod=0;
				}
				key_val=0;//每次都要清零,不然识别的就一直持续上一个按键的值
				break;
		case 6://S6按键的功能
				dsp_time=0;
				add_time=0;
				key_val=0;
				break;
		case 5://S5按键按一次计时时间加60秒,最高120,再加清零
				add_time+=60;
				if(add_time==180)	
				{
					add_time=0;
				}
				dsp_time=add_time;
				key_val=0;
				break;
		case 4://S4按键按下切换风速模式
				if(++fs_mod==4)
				{
					fs_mod=1;
				}
				key_val=0;
				break;
	}
}

void Timer0Init(void)		//2毫秒@12.000MHz
{
	HC138(5);
	P0=0xaf;
	P2&=0x1f;
	
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x40;		//设置定时初始值
	TH0 = 0xA2;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;

    AUXR |= 0x40;	//晶振12M时,定时器1定时100us,自动重装初值	
	TMOD &= 0x0F;		
	TL1 = 0x50;		
	TH1 = 0xFB;		
	TR1 = 1;			
    ET1=0;

}
void Timer0()	interrupt 1
{
	display();//2ms显示数码管
	
	if(++n1==10)
	{
		n1=0;
		temp_flag=1;
	}//20ms测一次温度
	
	if(++n2==10)
	{
		n2=0;
		key_scanf();
	}//20ms扫描一次键盘
	
	if(++n3==500)
	{	
		if(dsp_time!=0)
		{
			dsp_time--;
		}
		n3=0;
	}//每秒减1

}

void Timer1() interrupt 3
{
	//PWM_OUT输出200us高电平,800us低电平
	//pwm_value的值不同,则输出的脉宽不一样
	if(++pwm_counter <= pwm_value)
	{
		PWM_OUT = 1;
	}
	else
	{
		PWM_OUT = 0;
		if(pwm_counter == 10)
		{
			pwm_counter = 0;
		}
	}
}


void LEDlight(unsigned int fs_mod)
{
	if(fs_mod==1)
	{
		HC138(4);
		P0=0xfe;
		P2&=0x1f;
	}
	else if(fs_mod==2)
	{
		HC138(4);
		P0=0xfd;
		P2&=0x1f;
	}
	else if(fs_mod==3)
	{
		HC138(4);
		P0=0xfb;
		P2&=0x1f;
	}
	else
	{
		HC138(4);
		P0=0xff;
		P2&=0x1f;
	}
}

void main()
{
	float temperature;
	
	Timer0Init();
	while(1)
	{
		if(temp_flag==1)
		{
			temp_flag=0;
			temperature=rd_temperature_f();
			temper=temperature;
		}

		if(jm_mod==0)
		{
			dspbuf[1]=fs_mod;
			dspbuf[5]=dsp_time/100;
			dspbuf[6]=dsp_time%100/10;
			dspbuf[7]=dsp_time%10;
		}
		else
		{
			dspbuf[1]=4;
			dspbuf[4]=12;
			dspbuf[5]=temper/10;
			dspbuf[6]=temper%10;
			dspbuf[7]=13;
		}
		 
		key_function();
		LEDlight(fs_mod);
	}
}

??????? 下面是DS18B20的驱动代码ds18b20.c官方会在选手数据包中给出,需要注意的是我们要知道读取温度的函数float rd_temperature_f()如何编写并添加到其中,这是至关重要的。

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

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

//单总线延时函数
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0; i<8; 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;
}


float rd_temperature_f(void)
{
    unsigned int temp;
	float temperature;
    unsigned char low,high;
  
  	init_ds18b20();
  	Write_DS18B20(0xCC);
  	Write_DS18B20(0x44); //启动温度转换
  	//Delay_OneWire(200);
	while (!DQ); //等待转换完成

  	init_ds18b20();
  	Write_DS18B20(0xCC);	
  	Write_DS18B20(0xBE); //读取寄存器

  	low = Read_DS18B20(); //低字节
  	high = Read_DS18B20(); //高字节
  /** 精度为0.0625摄氏度 */  
	temp = (high&0x0f);
	temp <<= 8;
	temp |= low;
	temperature = temp*0.0625;
	
    return temperature;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:13:22  更:2022-03-10 22:16:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:25:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码