《物联网反向呼叫项目》上(C51部分)

项目概要

        自制一款可以联网操作的呼叫器正向手机发送ID可以控制响起,反向温度过高进行报警,手机网页端可以通过MQTT协议和ESP8266模块通信,ESP8266再通过串口和51单片机进行通信。添加温度报警功能,C51单片机通过获取到温度利用串口和ESP8266通信,将温度数据传递到ESP8266模块上。ESP8266模块再通过HTTP请求向后台Java接口进行数据的上传,保存到数据库中,并且实现数据的实时显示。该项目,不是特别的完美可以有很多创新和改进的地方,但主要实现了ESP8266的MQTT、HTTP网络通信协议应用,还有串口通信的使用,大家可以当做例子进行学习。

C51部分模块的使用

        OLED:第一行,进行本机的ID号显示,当前环境温度的显示,第二行显示当前所叫到号的ID。

        震动马达/蜂鸣器:当叫号ID和本机ID相匹配的时候,震动马达和蜂鸣器响起。

        DS18B20:温度模块对环境温度进行获取,实时的显示到OLED屏幕上,并经过串口发送到WIFi模块。

        其他模块的选取如下表所示:

Proteus8.11仿真图

        ID表示显示本机ID号,Te表示显示温度和U2即DS18B20的温度一致,现在是14度,则屏幕显示也为14度,CurrentID表示当前呼叫的ID号。左边按键从上至下功能依次是,控制复位按键(当震动马达和蜂鸣器响起的时候可以进行关闭)、设置加(对本机ID号进行加设置)、设置减(对本机ID号进行减设置)。D2震动马达利用红色LED进行仿真代替,ESP8266模块利用P3.0和P3.1进行RXD和TXD的交叉相连进行模拟。

KeilC代码

        [这里对各个模块的头文件和驱动代码不做过多的讲解,想必大家也有基础,只对整个设计思路进行讲解。]

        可以看下方代码的注释是否的清楚没有难度大的地方,重点为温度发送函数和数据ID接受函数为重点。

#include <reg51.h>
#include "oled.h"
#include "DELAY.h"
#include "DS18B20.h"

#define uchar unsigned char
uchar buf,RXData,RXStart,number;
uchar ID[4]={4,3,2,1};
uchar ReceiveId[4]={0,0,0,0};
sbit ctrlKey = P1^2;					//控制复位按键
sbit addNumberKey = P1^5;			//加按键
sbit deleteNumberKey = P1^7;	//减按键
sbit motor = P0^0;						//震动马达
sbit sounder = P0^1;					//蜂鸣器
int RT;						//温度存储变量
int i,j,k,f,f_ctrl;			//一些变量
void config();				//初始化配置
void sendid(int i);		//发送温度函数
void senddata(uchar buf);			//字节发送函数
void init_serial();				//串口初始化函数
void receive();						//串口接受函数
void ControllerSlave(uchar buf);
void KeyControl();				//按键控制函数
//主函数
void main(){
	config();				//变量及模块初始化
	while(1){
		DS18B20_Init();	//DS18B20温度传感器初始化
		ds18b20_changetemp();				//获取改变后的温度
		if(RT!=ds18b20_gettemp()/10){			//对温度进行存储,如果温度发送改变则发送当前温度
			RT=ds18b20_gettemp()/10;
			sendid(RT);						//发送改变后的温度
		}
		KeyControl();						//按键控制函数
		OLED_ShowString(0,0,"ID:",16);	//显示本机ID号
		OLED_ShowNum(24,0,ID[0],1,16);	//ID4位数依次显示
		OLED_ShowNum(32,0,ID[1],1,16);		
		OLED_ShowNum(40,0,ID[2],1,16);
		OLED_ShowNum(48,0,ID[3],1,16);
		OLED_ShowString(67,0,"Te:",16);	//显示当前的温度
		OLED_ShowNum(104,0,RT,2,16);
		OLED_ShowChar(122,0,'C',16);
	}
}
void config(){
	P2=0x40;						//本机ID号的初始化
	k=j=0;							//以下都是变量的初始化设置
	i=1;
	RXData=0;
	RXStart=0;
	motor=1;
	sounder=0;
	init_serial();			//串口初始化
	OLED_Init();				//初始化OLED 
	OLED_ColorTurn(0);	//0正常显示,1 反色显示
  OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示	
	OLED_ShowString(0,2,"CurrentID:",16);			//初始化显示当前所叫到号的ID默认为0000
	OLED_ShowNum(88,2,ReceiveId[0],1,16);
	OLED_ShowNum(96,2,ReceiveId[1],1,16);		
	OLED_ShowNum(104,2,ReceiveId[2],1,16);
	OLED_ShowNum(112,2,ReceiveId[3],1,16);
}

void KeyControl(){
	if(ctrlKey==0){
		motor=1;				//当控制按键按下时候蜂鸣器和震动模块关闭
		sounder=0;
	}
	if(ID[k]!=9){			//当加的数据不等于9时候进行加操作
		if(addNumberKey==0){		//当按下加操作按键时候
			ID[k]++;				//ID[k]里面的数据进行加操作
			if(ID[k]==9){			//当ID[k]里面的数据等于9的时候
				if(k!=3){			//k不等于3的时候
					k++;			//k进行加操作
				}
			}
		}
	}
	if(ID[k]!=0){					//当减的数据不等于0的时候进行减操作
		if(deleteNumberKey==0){		//当按下减操作的按键时候
			ID[k]--;				//ID[k]里面的数据进行减操作
			if(ID[k]==0){			//ID[k]里面的数据不等于0的时候
				if(k!=0){			//k不等于0的时候
					k--;			//k进行减操作
				}
			}
		}
	}
}
//温度发送函数
void sendid(int i){
	senddata(0x30+i/10);		//发送温度的十位
	senddata(0x30+i%10);		//发送温度的个位
	senddata('$');				//发送结束标识符$
	Delay(100);
}
//发送数据函数
void senddata(uchar buf)
{
	/* 发送数据 */
		TI = 0;
		TB8 = 0;				// 发送数据帧
		SBUF =buf;	
		while(!TI);
		TI = 0;
}
//串口初始化函数
void init_serial()
{
	TMOD = 0x20;				// 定时器T1使用工作方式2
	TH1 = 250;
	TL1 = 250;
	TR1 = 1;					// 开始计时
	PCON = 0x80;				// SMOD = 1
	SCON = 0xd0;				// 工作方式,9位数据位,波特率9600kbit/s,允许接收 
	ES = 1; //开串口中断
  TR1 = 1; //启动定时器1
  EA = 1; //中断 总开关
}

void receive() interrupt 4 //串口中断服务函数
{
  ES = 0; //关闭串口中断
  if(RI){		//再次判断,是否接收到数据(接收到数据后,RI会置1,需手动清0)
		RXData = SBUF;
		if(RXData == '*'){ 		
			RXStart=0;		//关闭数据接收
			j=0;			//接受控制变量清零
			number=0;		//数据转换存储变量清零
			OLED_Clear();				//屏幕清零
			OLED_ShowString(0,2,"CurrentID:",16);	//显示当前的呼叫ID
			OLED_ShowNum(88,2,ReceiveId[0],1,16);
			OLED_ShowNum(96,2,ReceiveId[1],1,16);		
			OLED_ShowNum(104,2,ReceiveId[2],1,16);
			OLED_ShowNum(112,2,ReceiveId[3],1,16);
			for(f=0;f<4;f++){				//进行4位逐个校验
				if(ReceiveId[f]==ID[f]){	
					f_ctrl+=0;					//相同时控制变量加0
				}else{			
					f_ctrl+=1;					//不同时控制变量加1			
				}
			}
			if(f_ctrl==0){		//当ID校验控制变量为0时候表示验证通过
				motor=0;			//马达震动
				sounder=1;			//蜂鸣器响起
			}
			f_ctrl=0;	//ID校验控制变量清零
		}
		if(RXStart == 1){					//接受开启
			if(j!=4){						//只支持接收4位数字
				number=RXData-0x30;			//将数据文本型转换为字符型
				ReceiveId[j]=number;		//存储数据
			}
			j++;
		}
		if(RXData == '$'){				//数据结束标志
			RXStart=1;					//数据接收开启标志
		}
	}
  RI = 0; //清除接收标志位
  ES = 1; //重新开启串口中断
}

小结

        代码和文件比较多,如果想参考可以到评论区留言,我私发给你。文中有不清楚的地方也可以私信我,或者评论区留言。本文关注度高的话会更新中和下的内容,分享给大家,制作不易,请大家多多评论,多多点赞转发!!!

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值