51大作业分享

本次设计的灵感来自于日常空调以及打印机

设计思路

  1. 现在的空调,风扇等温度控制产品都没有广泛的普及“智能家居”的概念,所以一个WiFi控制模块是必要的;
  2. 温度控制产品都缺少“自动控制温度”的一种功能,在我看来是不够合理的,所以程序之中设定自动温度调整
  3. 空调仅仅显示它所被设定的温度值,我觉得这个不是很合理,那种座式的空调,占据了大量的空间,只显示设定的温度值,这个温度数值也没什么实际意义,所以我设计显示环境温度以及当前时间

本次实物设计仅为一个想法的小demo,还有许多不够合理的地方

产品框架和实现思路

日期,时间,天气模块

使用lcd1602和ds1302进行实现

ds1302时钟芯片是将时分秒年月日以BCD码的形式存储在八个时钟寄存器之中的,数据先发低位再发高位,核心要点就是进行在写入和读出的时候都要注意去进行数制转换,这款芯片的功耗很低,51开发板上面没有备用电源,所以无法做到掉电后时钟不停,只需要外接一个备用电源即可。

lcd1602的端口不再是P0,我进行了相应的端口调整,从而在开发板上能够同时使用lcd1602以及数码管

温度模块

使用ds18b20和数码管实现

数码管摈弃了传统的使用74ls138译码器实现位选,转而去使用两片74hc595级联实现位选和段选的功能,仅用三个IO口就可以满足16个IO口的驱动,但也带来了一个问题,开发板上的74hc245芯片是固定接在了P0端口上的,没有了这块芯片,数码管的显示不是很稳定,外接一块74hc245即可解决

ds18b20温度传感器是以16位二进制数表示温度值,高五位代表正负,后十一位代表温度的数值,转换为十进制再乘以0.0625即为此时的温度值

“温度控制模块”(使用步进电机进行代替)

28BYJ48 步进电机和ULN2003驱动模块(这个模块没有跑通,还未找到问题所在)

WiFi控制模块

两套方式,适用于不同的场景,在教室的空调使用AP模式进行控制,直接连上设备的wifi即可调整设备的温度,Station模式就是平常的智能家居的模式,配置在同一个局域网下即可实现控制

引脚配置

各模块代码

lcd1602

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//定义lcd1602数据端口,八位输入

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=0;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

ds1302

#include "intrins.h"
#include "public.h"

//引脚定义
sbit DS1302_RST=P3^5;//复位管脚
sbit DS1302_CLK=P3^6;//时钟管脚
sbit DS1302_IO=P3^4;//数据管脚

//DS1302写入和读取时分秒的地址命令
u8 gREAD_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
u8 gWRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//DS1302时钟初始化2023年12月26日星期二15点00分22秒
//存储顺序是秒分时日月周年,存储格式是用BCD码
u8 gDS1302_TIME[7] = {0x22, 0x00, 0x15, 0x26, 0x12, 0x02, 0x23};

//DS1302写单字节,addr地址/命令,dat数据
void ds1302_write_byte(u8 addr,u8 dat)
{
	u8 i=0;
	
	DS1302_RST=0;	
	DS1302_CLK=0;//CLK低电平
	DS1302_RST=1;//RST由低到高变化

	for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位
	{
		DS1302_IO=addr&0x01;
		addr>>=1;
		DS1302_CLK=1;//CLK由低到高产生一个上升沿,从而写入数据
		DS1302_CLK=0; 		
	}
	for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位
	{
		DS1302_IO=dat&0x01;
		dat>>=1;
		DS1302_CLK=1;//CLK由低到高产生一个上升沿,从而写入数据
		DS1302_CLK=0;		
	}
	DS1302_RST=0;//RST拉低	
}

//ds1302读单字节,addr地址/命令
u8 ds1302_read_byte(u8 addr)
{
	u8 i=0;
	u8 temp=0;
	u8 value=0;

	DS1302_RST=0;
	DS1302_CLK=0;//CLK低电平
	DS1302_RST=1;//RST由低到高变化
	
	for(i=0;i<8;i++)//循环8次,每次写1位,先写低位再写高位
	{
		DS1302_IO=addr&0x01;
		addr>>=1;	
		DS1302_CLK=1;//CLK由低到高产生一个上升沿,从而写入数据
		DS1302_CLK=0;	
	}
	for(i=0;i<8;i++)//循环8次,每次读1位,先读低位再读高位
	{
		temp=DS1302_IO;
		value=(temp<<7)|(value>>1);//先将value右移1位,然后temp左移7位,最后或运算
		DS1302_CLK=1;//CLK由低到高产生一个上升沿,从而写入数据
		DS1302_CLK=0;;		
	}
 
	DS1302_CLK=1;// 使数据口有一个上升沿脉冲。
	DS1302_IO = 0;
	DS1302_IO = 1;
	return value;		
}

//DS1302初始化时间
void ds1302_init(void)
{
	u8 i=0;
	ds1302_write_byte(0x8E,0X00);//在写寄存器之前,关闭写寄存器保护
	for(i=0;i<7;i++)
	{
		ds1302_write_byte(gWRITE_RTC_ADDR[i],gDS1302_TIME[i]);	
	}
	ds1302_write_byte(0x8E,0X80);	//重新开启保护
}

//ds1302读取时间
void ds1302_read_time(void)
{
	u8 i=0;
	for(i=0;i<7;i++)
	{
		gDS1302_TIME[i]=ds1302_read_byte(gREAD_RTC_ADDR[i]);	
	}	
}

数码管

#include "smg.h"
#include <intrins.h>

sbit stcp=P1^0;				//RC(RCLK)
sbit shcp=P1^1;				//SC(SRCLK)
sbit DS=P1^2;					//SE(SER)

// 数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void hc595_write(u8 show_number)
{
	u8 i=0;
	for(i=0;i<8;i++)
	{
		DS=show_number&(0x80>>i);
		shcp=0;
		shcp=1;	
	}
}
void hc595_latch(void)
{
	stcp=0;
	stcp=1;
}

//dat:要显示的数据
//pos:从左开始第几个位置开始显示,范围1-8
void smg_display(u8 dat[],u8 pos)
{
	
	static u8 i=0;
	static u8 pos_temp;
	pos_temp=pos-1;
	for(i=pos_temp;i<8;i++)
	{		
        hc595_write((0xfe << i) | (0xfe >> (8 - i)));//传送位选数据
		hc595_write(dat[i-pos_temp]);//传送段选数据
		hc595_latch();//锁存
		delay_10us(100);//延时一段时间,等待显示稳定
		hc595_write(0x00);//消影
		hc595_latch();//锁存
	}
}

ds18b20

#include "public.h"
#include "intrins.h"
 
//引脚定义
sbit DS18B20_PORT=P3^7;	//DS18B20数据口定义
 
//ds18b20复位功能
void ds18b20_reset(void)
{
	DS18B20_PORT=0;	//拉低DQ
	delay_10us(75);	//拉低750us
	DS18B20_PORT=1;	//拉高DQ
	delay_10us(2);	//拉高20US
}

//检测DS18B20是否存在,1表示不存在
u8 ds18b20_check(void)
{
	u8 time_temp=0;

	while(DS18B20_PORT&&time_temp<20)	//等待DQ为低电平
	{
		time_temp++;
		delay_10us(1);	
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	else time_temp=0;
	while((!DS18B20_PORT)&&time_temp<20)	//等待DQ为高电平
	{
		time_temp++;
		delay_10us(1);
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	return 0;
}

//从DS18B20读取一个位bit
u8 ds18b20_read_bit(void)
{
	u8 dat=0;
	
	DS18B20_PORT=0;
	DS18B20_PORT=1;	 //该段时间不能过长,必须在15us内读取数据
	if(DS18B20_PORT)dat=1;	//如果总线上为1则数据dat为1,否则为0
	else dat=0;
	delay_10us(5);
	return dat;
} 
//从DS18B20读取一个字节,读八次bit即读一个字节
u8 ds18b20_read_byte(void)
{
	u8 i=0;
	u8 dat=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
	{
		temp=ds18b20_read_bit();
		dat=(temp<<7)|(dat>>1);
	}
	return dat;	
}

//写一个字节到ds18b20
void ds18b20_write_byte(u8 dat)
{
	u8 i=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
	{
		temp=dat&0x01;//选择低位准备写入
		dat>>=1;//将次高位移到低位
		if(temp)
		{
			DS18B20_PORT=0;
			_nop_();_nop_();
			DS18B20_PORT=1;	
			delay_10us(6);
		}
		else
		{
			DS18B20_PORT=0;
			delay_10us(6);
			DS18B20_PORT=1;
			_nop_();_nop_();	
		}	
	}	
}

//开始温度转换
void ds18b20_start(void)
{
	ds18b20_reset();//复位
	ds18b20_check();//检查DS18B20
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0x44);//转换命令	
}

//初始化ds18b20并且检测其是否
u8 ds18b20_init(void)
{
	ds18b20_reset();
	return ds18b20_check();	
}

//读取温度数值
float ds18b20_read_temperture(void)
{
	float temp;
	u8 dath=0;
	u8 datl=0;
	u16 value=0;

	ds18b20_start();//开始转换
	ds18b20_reset();//复位
	ds18b20_check();
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0xbe);//读存储器

	datl=ds18b20_read_byte();//低字节
	dath=ds18b20_read_byte();//高字节
	value=(dath<<8)+datl;//合并为16位数据

	if((value&0xf800)==0xf800)//判断符号位,负温度
	{
		value=(~value)+1; //数据取反再加1
		temp=value*(-0.0625);//乘以精度	
	}
	else //正温度
	{
		temp=value*0.0625;	
	}
	return temp;
}

key

#include "public.h"

//定义独立按键控制脚
sbit k1=P2^4;
sbit k2=P2^3;
sbit k3=P2^2;


u8 cur_sta[4]={1,1,1,1};
u8 pre_sta[4]={1,1,1,1};

u8 key_scan()
{
	u8 i;
  u8 key_value=0;
	
	//判断两个按键是否同时按下
	for(i=0;i<3;i++)
	{
	 if(pre_sta[i]!=cur_sta[i])
	 {
	  if(pre_sta[i])
		{
//			 if(i==1 && cur_sta[0]==0) //当第二个按键按下时,第一个按键也正好处于按下状态
		   
			if(i==2 && cur_sta[1]==0)//当第三个按键按下的时候,第二个按键也处于按下的状态
			key_value=4;
		else
		 { 
			 key_value=i+1;
		 }
		}
		pre_sta[i]=cur_sta[i];// 状态更新
	 }
	}
	return(key_value);
}


void cur_sta_update()
{
	u8 i;
  static u8 keybuff[3]={0xff,0xff,0xff};
  
	//八次更新状态,要是按键对应的八位都为1则是按下
	keybuff[0]=(keybuff[0]<<1)|k1;
  keybuff[1]=(keybuff[1]<<1)|k2;
  keybuff[2]=(keybuff[2]<<1)|k3;
	
	//遍历三个按键
  for(i=0;i<3;i++)
 {
  if(keybuff[i]==0xff)
		cur_sta[i]=1;
	else if(keybuff[i]==0x00)
		cur_sta[i]=0;
 }
}

stepmotor

#include <REG52.H>
#include "public.h"

//对步进电机引脚的定义
sbit IN1_D=P1^4;
sbit IN1_C=P1^5;
sbit IN1_B=P1^6;
sbit IN1_A=P1^7;

//步进电机旋转配置
void stepmotor(u8 step,u8 dir)//步数和方向设置函数
{
	u8 temp=step;
	
	if(dir==0) temp=7-step;
	
	switch(temp)
	{
		case 0:	IN1_A=1;IN1_B=1;IN1_C=1;IN1_D=0;break;
		case 1:	IN1_A=1;IN1_B=1;IN1_C=0;IN1_D=0;break;
		case 2:	IN1_A=1;IN1_B=1;IN1_C=0;IN1_D=1;break;
		case 3:	IN1_A=1;IN1_B=0;IN1_C=0;IN1_D=1;break;
		case 4:	IN1_A=1;IN1_B=0;IN1_C=1;IN1_D=1;break;
		case 5:	IN1_A=0;IN1_B=0;IN1_C=1;IN1_D=1;break;
		case 6:	IN1_A=0;IN1_B=1;IN1_C=1;IN1_D=1;break;
		case 7:	IN1_A=0;IN1_B=1;IN1_C=1;IN1_D=0;break;	
	}
}

uart

#include "uart.h"

#define RELOAD_COUNT 0xFA //宏定义波特率发生器的载入值 9600
													//配合外部晶振频率11.0592M使用可以更加精确的进行串口通信

void UART_Init(void)
{
	SCON|=0X50;			//设置为工作方式1
	TMOD|=0X20;			//设置计数器工作方式2
	PCON=0X80;			//波特率加倍
	TH1=RELOAD_COUNT;	//计数器初始值设置
	TL1=TH1;
	ES=0;				//关闭接收中断
	EA=1;				//打开总中断
	TR1=1;				//打开计数器
}

void UART_SendData(u8 dat)
{
	ES=0; //关闭串口中断
	TI=0; //清发送完毕中断请求标志位
	SBUF=dat; //发送
	while(TI==0); //等待发送完毕
	TI=0; //清发送完毕中断请求标志位
	ES=1; //允许串口中断
}

void UART_SendString(u8 *pbuf)
{
	while(*pbuf!='\0') //遇到空格跳出循环	
	{
		UART_SendData(*pbuf);
		delay_10us(5);
		pbuf++;	
	}
}

u8 UART_RX_BUF[UART_REC_LEN];//接收缓冲,最大UART_REC_LEN个字节.
u16 UART_RX_STA=0;//接收状态标记	

//串口中断模板
//void UART_IRQn() interrupt 4
//{
//	u8 r;
//	static u8 i=0;
//	
//	if(RI)
//	{
//		RI=0;
//		UART_RX_BUF[i]=SBUF;//读取接收到的数据
//		if(UART_RX_BUF[0]=='+')i++;
//		else i=0;
//		if(i==10)
//		{
//			i=0;
//		}		  		
//	}	
//}

WiFi control(main)

#include "wifi_control.h"
#include "ds18b20.h"
#include "uart.h"
#include "smg.h"
#include "lcd1602.h"
#include "ds1302.h"
#include "timer0.h"
//#include "key.h"
//#include "beep.h"
//#include "stepmotor.h"

//定义LED1管脚
sbit LED1=P2^0;//黄灯
sbit LED2=P2^1;//红灯


//定义WIFI控制命令
#define LED1_ON_CMD			'1'
#define LED1_OFF_CMD		'2'

//#define SPEEDMAX 1//设定步进旋转速度最大值
//#define SPEEDMIN 5//设置步进旋转速度最小值
//u8 key=0;
extern unsigned char gDS1302_TIME[7];

//ESP8266 WIFI发送AT指令
//pbuf:AT指令,字符串格式,如:"AT"
void ESP8266_SendCmd(u8 *pbuf)
{
	while(*pbuf!='\0') //遇到空格跳出循环	
	{
		UART_SendData(*pbuf);
		delay_10us(5);
		pbuf++;	
	}
	delay_10us(5);
	UART_SendData('\r');//回车
	delay_10us(5);
	//WiFi模块发送AT指令需要发送一个换行结束符
	UART_SendData('\n');//换行
	delay_ms(1000);
}

//ESP8266 WIFI发送数据到APP
//pbuf:数据
void ESP8266_SendData(u8 *pbuf)
{
	ESP8266_SendCmd("AT+CIPSEND=0,7");//id0号,数据长度为128(最大为2048)
	while(*pbuf!='\0') //遇到空格跳出循环	
	{
		UART_SendData(*pbuf);
		delay_10us(5);
		pbuf++;	
	}
	//WiFi模块发送AT指令需要发送一个换行结束符
	UART_SendData('\n');//换行	
}

//ESP8266-WIFI模块工作模式初始化
void ESP8266_ModeInit(void)//station模式连接
{
	ESP8266_SendCmd("AT+CWMODE=1");//设置路由器模式 1 station模式 2 AP点 路由器模式 3 station+AP混合模式
  ESP8266_SendCmd("AT+CWJAP=\"lingqii\",\"77777777\""); //设置连接WIFI名及密码
	ESP8266_SendCmd("AT+RST");//重新启动wifi模块
	delay_ms(2000);
	ESP8266_SendCmd("AT+CIPMUX=1");	//开启多路连接模式,允许多个各客户端接入
	ESP8266_SendCmd("AT+CIPSERVER=1,5000");	
																			//启动TCP/IP 端口为8080 实现基于网络控制
	ESP8266_SendCmd("AT+CIPSTO=0");

} 

//ESP8266-WIFI模块工作模式初始化
//void ESP8266_ModeInit(void)//AP模式连接
//{
//	ESP8266_SendCmd("AT+CWMODE=2");//设置路由器模式 1 staTIon模式 2 AP点 路由器模式 3 station+AP混合模式
//	ESP8266_SendCmd("AT+CWSAP=\"PRECHIN\",\"prechin168\",11,0"); //设置WIFI热点名及密码
//	ESP8266_SendCmd("AT+CIPAP=\"192.168.4.1\"");
	ESP8266_SendCmd("AT+RST");//重新启动wifi模块
	delay_ms(2000);
//	ESP8266_SendCmd("AT+CIPMUX=1");	//开启多连接模式,允许多个各客户端接入
//	ESP8266_SendCmd("AT+CIPSERVER=1,8080");	//启动TCP/IP 端口为8080 实现基于网络控制	
//} 

//WIFI控制初始化
void wifi_control_init(void)
{
	UART_Init();
	ds18b20_init();//初始化DS18B20
	ESP8266_ModeInit();
	ES=1;//允许串口中断
}

//WIFI控制(主函数)
void wifi_control(void)
{
	u16 i=0;
  u16 temp_value;
	u8 temp_buf[5];
	u8 wifi_send_buf[7];
	u8 time_buf[7];
	u8 j;
//	u8 dir=0;
//	u8 step=0;
//	u8 speed=SPEEDMAX;
//	bit stepmove=0;//步进电机旋转标志位,0为停止,1为旋转
	while(1)
	{
//		key=key_scan();
//		
//		if(key==1)//按键一按下令步进电机旋转或停止
//		{
//			stepmove=!stepmove;
//			beep_alarm(100,7);
//		}
//		if(stepmove==1)	//判断是否要让步进电机旋转
//			{
//				stepmotor(step++,dir);
//				if(step==8)	step=0;
//				delay_ms(speed);
//				beep_alarm(100,7);				
//			}
//		if(key==4)//同时按下二三键令步进电机反转	
//			{
//				dir=!dir;
//			beep_alarm(100,7);				
//			}
//			
//			//步进电机速度控制		
//			else if (key==2)//按下按键二令步进电机加速
//			{
//				if(speed>SPEEDMAX) speed-=1;
//				beep_alarm(100,7);
//			}	
//				else if (key==3)//按下按键三令步进电机减速
//			{
//					if(speed<SPEEDMIN) speed+=1;
//					beep_alarm(100,7);
//			}delay_ms(SPEEDMAX);//通过每一步的延时来调节步进电机的速度

		i++;
		if(i%50==0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间60us
			temp_value=ds18b20_read_temperture()*10;//保留温度值小数后一位
		
//		//读出来的是乘以十的温度值,故做此判断
//		if(temp_value>220) 
//		{	
//		LED2=0;//温度超过阈值,亮红灯,电机正转
		stepmove=1;
//		}
//		else LED2=1;
//		if(temp_value<190) 
//		{
//			LED1=0;//温度低于阈值,亮黄灯,电机反转
			dir=~dir;
//		}
//			else LED1=1;
			
		if(temp_value<0)//如果温度是零下
		{
			temp_value=-temp_value;//数值取反
			temp_buf[0]=0x40;//显示负号
			wifi_send_buf[0]='-';	
		}
		else
		{
			temp_buf[0]=0x00;//不显示
			wifi_send_buf[0]='+';
		}		
		temp_buf[1]=gsmg_code[temp_value/1000];//百位
		temp_buf[2]=gsmg_code[temp_value%1000/100];//十位
		temp_buf[3]=gsmg_code[temp_value%1000%100/10]|0x80;//个位+小数点
		temp_buf[4]=gsmg_code[temp_value%1000%100%10];//小数点后一位
		smg_display(temp_buf,4);
		if(i%100==0)//间隔一定时间发送
		{
			wifi_send_buf[1]=temp_value/1000+0x30;
			wifi_send_buf[2]=temp_value%1000/100+0x30;
			wifi_send_buf[3]=temp_value%1000%100/10+0x30;
			wifi_send_buf[4]='.';
			wifi_send_buf[5]=temp_value%1000%100%10+0x30;
			wifi_send_buf[6]='\0';
			ESP8266_SendData(wifi_send_buf);//通过串口发送温度数据到APP	
		}		
		for (j = 0 ; j< 7 ; j++)
		{
			time_buf[j]=(gDS1302_TIME[j]/16)*10+gDS1302_TIME[j]%16;//将数组中的bcd形式的值转换成10进制并保存在其他数组中
		}
		//显示日期,周几,24时制时间,天气
		LCD_ShowNum(1,1,20,2);
		LCD_ShowNum(1,3,time_buf[6],2);
		LCD_ShowChar(1,5,'-');
		LCD_ShowNum(1,6,time_buf[4],2);
		LCD_ShowChar(1,8,'-');
		LCD_ShowNum(1,9,time_buf[3],2);
		LCD_ShowString(1,12,"Day");
		LCD_ShowNum(1,15,time_buf[5],1);
		LCD_ShowNum(2,1,time_buf[2],2);
		LCD_ShowChar(2,3,':');
		LCD_ShowNum(2,4,time_buf[1],2);
		LCD_ShowChar(2,6,':');
		LCD_ShowNum(2,7,time_buf[0],2);
		LCD_ShowString(2,12,"Sunny");
	}	
}

//串口中断服务函数
//接收手机APP发送的信号后控制51
void UART_IRQn() interrupt 4
{
	static u8 i=0;

	if(RI)
	{
		RI=0;//恢复为0,停止中断
		UART_RX_BUF[i]=SBUF;//读取接收到的数据
		if(UART_RX_BUF[0]=='+')i++;
		else i=0;
		if(i==10)
		{
			i=0;
			//WIFI控制
			if(UART_RX_BUF[9]==LED1_ON_CMD)
				LED1=0;
			else if(UART_RX_BUF[9]==LED1_OFF_CMD)
				LED1=1;
//			else if(UART_RX_BUF[9]==3)
//				key=1;
//			else if(UART_RX_BUF[9]==4)
//				key=2;
//			else if(UART_RX_BUF[9]==5)
//				key=3;
		}			
	}	
}
void Timer1_Routine() interrupt 1
{
		static unsigned int T0Count;//配置了静态变量,保证值不丢
		TL0 = 0x66;				//设置定时初始值
		TH0 = 0xFC;				//设置定时初始值
		T0Count++;				//计数器,每次加1微妙
		if(T0Count>=1000)
		{
			T0Count=0;
			ds1302_read_time();	
	}	
}
		
//void Timer2_Routine() interrupt 3
//{
//		TH0=63536>>8;
//	  TL0=63536;
//	  cur_sta_update();
//}


后言

本次作业也有许多不足的地方

  • 没能实现用wifi模块实时获取天气信息,json解析数据没整明白
  • 步进电机模块和按键模块都没能正常运行
  • 代码结构以及变量大小控制都不是很精细

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值