SIM800L上传数据到OneNET(HTTP)

前言

本案例是使用51单片机和SIM800L模块实现上传温度数据的功能,同时可以发短信点灯。SIM800L模块可以收发短信和拨打电话,价格也挺便宜的,是户外上云的一个选择吧。虽说是使用51单片机,但是其他单片机的实现原理也一样,可以借鉴一下的。


一、前期准备

1、在OneNET平台下创建使用HTTP协议的产品和设备
2、准备SIM卡,SIM800L支持移动卡和联通卡,最好是移动卡
3、在进行单片机测试前,可以使用USB转串口的模块单独测试

二、AT指令测试

在将SIM800L模块接入单片机前,使用USB转串口对模块进行AT指令的测试,可以帮助了解上传数据的整个过程。
指令说明
在这里插入图片描述
在这里插入图片描述

串口助手显示:
连接OneNET服务器指令:AT+CIPSTART=“TCP”,“183.230.40.33”,80
每条指令都应该带回车换行,其中1A需要按16进制发送
在这里插入图片描述
指令发送:
可以按照如下顺序发送AT指令来上传数据到OneNET云平台。
要改的是发送数据中设备ID和Master-APIkey,其中699063374是设备ID,=08b33=G=KP8qxRoCYYrurN41yk=是Master-APIkey,18是数据(,;Temp,20;Humi,30;)长度

//查看SIM卡的状态)回车,返回:+CPIN:READY  OK(正常)
AT+CPIN?
//信号质量查询
AT+CSQ
//检查是否注册到网络,返回:+CREG: 0,1(正常)
AT+CREG?
//检查 GPRS 附着状态,返回:+CGATT: 1(正常)
AT+CGATT?
//设备连接OneNET服务器,返回:CONNECT OK(正常)
AT+CIPSTART="TCP","183.230.40.33",80
//准备发送数据,返回:>(正常)
AT+CIPSEND 
//发送数据
POST /devices/699063374/datapoints?type=5 HTTP/1.1
api-key:=08b33=G=KP8qxRoCYYrurN41yk=
Host:api.heclouds.com
Content-Length:18

,;Temp,30;Humi,60;
//发送结束符
1A(按16进制发送)

OneNET显示数据:
在这里插入图片描述

三、接线说明

SIM800L模块:TX—P30 RX—P31 VCC—3.5-4.2V
DS18B20: IO—P37
由于单片机上没有3.5~4.2V的电压,所以我接了5V。

四、案例效果

串口助手输出界面:
注:为了实现上传多个数据,伪造了一个湿度数据。
在这里插入图片描述

OneNET云平台显示数据:
在这里插入图片描述

显示历史数据:
在这里插入图片描述
应用界面搭建:
在这里插入图片描述
实物照片:
在这里插入图片描述

五、代码实现

main.c文件

#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器
#include <stdio.h>
#include <string.h>
#include "usart.h"
#include "delay.h"
#include "18b20.h"

//需要修改的是下面2行
#define  devkey   "=08b33=G=KP8qxRoCYYrurN41yk="   //onenet平台产品apikey
#define  devid    "699063374"                      //onenet平台设备id

float  Temp = 30.5;   //温度
float  Humi = 66.5;   //湿度
unsigned int connectErr = 0;  //连接状态,0正常连接,1断开连接
unsigned int OneNet_FillBuf(char *buf);   //将上传的数据打包
void send_msg(char *phone,char *msg);     //发送短信
void call_phone(char *phone);             //拨打电话

#if 1
void main()
{
    
    
	char xdata buf[64];
	unsigned int bufLen = 0;
	set52_baudrate(11.0592, 115200);//串口初始化
	printf("AT\r\n");  
	DelayMs(2000);
	printf("AT+CPIN?\r\n");  //查看SIM卡的状态)回车,返回:+CPIN:READY  OK(正常)
	DelayMs(2000);
	printf("AT+CSQ\r\n");    //信号质量查询
	DelayMs(2000);
	printf("AT+CREG?\r\n");  //检查是否注册到网络,返回:+CREG: 0,1(正常)
	DelayMs(2000);
	printf("AT+CGATT?\r\n");  //检查 GPRS 附着状态,返回:+CGATT: 1(正常)
	DelayMs(2000);

	printf("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n"); //设备连接OneNET服务器,返回:CONNECT OK(正常)
	//printf("AT+CIPSTART=\"TCP\",\"101.200.212.234\",1234\r\n"); //连接个人服务器
	DelayMs(5000);
	
	 bufLen = OneNet_FillBuf(buf);
	printf("AT+CIPSEND\r\n");  //准备发送数据,返回:>(正常)
	DelayMs(1000);
	//发送数据
	printf("POST /devices/%s/datapoints?type=5 HTTP/1.1\r\napi-key:%s\r\nHost:api.heclouds.com\r\nContent-Length:%d\r\n\r\n%s",devid,devkey,bufLen,buf);	
	DelayMs(1000);
	UARTSendByte(0X1A);
	DelayMs(1000);

	while(1)
	{
    
    
		Temp=(float)ReadTemperature()*0.0625;		//读取温度并转换
		
	    bufLen = OneNet_FillBuf(buf);
		printf("AT+CIPSEND\r\n");  //准备发送数据,返回:>(正常)
		DelayMs(1000);
		//发送数据
		printf("POST /devices/%s/datapoints?type=5 HTTP/1.1\r\napi-key:%s\r\nHost:api.heclouds.com\r\nContent-Length:%d\r\n\r\n%s",devid,devkey,bufLen,buf);	
		DelayMs(1000);
		UARTSendByte(0X1A);
		DelayMs(1000);
		//意外断开连接时重新连接服务器
		if(connectErr==1)
		{
    
    
			connectErr = 0;
			printf("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n"); //设备连接服务器
			DelayMs(3000);
		}
	}		
}
#endif

unsigned int OneNet_FillBuf(char *buf)
{
    
    
	char xdata text[32];
	
	memset(text, 0, sizeof(text));
	
	strcpy(buf, ",;");
		
	memset(text, 0, sizeof(text));
	sprintf(text, "Temp,%.1f;", Temp); 
	strcat(buf, text);
		  
	memset(text, 0, sizeof(text));
	sprintf(text, "Humi,%.1f;",Humi);
	strcat(buf, text);
	
	return strlen(buf);
}

void send_msg(char *phone,char *msg)
{
    
    
	printf("AT+CMGF=1\r\n");
	DelayMs(1000);
	printf("AT+CMGS=\"%s\"\r\n",phone);
	DelayMs(1000);
	printf("%s",msg);
	DelayMs(1000);
	//SendASC(0x1a);
	UARTSendByte(0x1a);
	DelayMs(1000);
}

void call_phone(char *phone)
{
    
    
	printf("ATD%s;\r\n",phone);
	DelayMs(3000);
}

串口中断服务程序
这部分代码是上传数据成功后p20处LED闪烁、短信点灯、断开重连

char  uart_buf[32] = {
    
    0};  //用于保存串口数据
unsigned char uart_cnt = 0;   //用于定位串口数据的位置
extern unsigned int connectErr;
void UART_SER (void) interrupt 4 	//串行中断服务程序
{
    
    
	if(RI==1)                        //判断是接收中断产生
	{
    
    
		ES = 0;  //关闭串行中断
		RI=0;    //清除串口接收标志位
		
		uart_buf[uart_cnt++] =SBUF;  	//接收串口数据
	
		//收到succ后表示数据发送成功  succ
		if(uart_buf[uart_cnt-4]=='s'&&uart_buf[uart_cnt-3]=='u'&&uart_buf[uart_cnt-2]=='c'&&uart_buf[uart_cnt-1] == 'c')  
		{
    
           
			uart_cnt = 0;
			led1 = ~led1;
		}
		//判断是否意外断开了连接 CLOSED
		 if(uart_buf[uart_cnt-4]=='O'&&uart_buf[uart_cnt-3]=='S'&&uart_buf[uart_cnt-2]=='E'&&uart_buf[uart_cnt-1] == 'D')  
		{
    
           
			uart_cnt = 0;
			connectErr = 1;
			led2 = ~led2;
		}
		//如果模块接收到短信,会提示如:+CMTI:"SM",2
		if(uart_buf[uart_cnt-4]=='C'&&uart_buf[uart_cnt-3]=='M'&&uart_buf[uart_cnt-2]=='T'&&uart_buf[uart_cnt-1]=='I')  
		{
    
           
			uart_cnt = 0;
			led3 = ~led3;
		}

		if(uart_cnt>28)   //防止数组越界
		{
    
    
			
			uart_cnt = 0;
		}
		ES = 1;  //开启串行中断
	}
	
	if(TI==1)  //如果是发送标志位,清零
	{
    
    
		TI=0;
	}
} 

代码需要修改的地方

1、devkey 是Master-APIkey,devid 是设备ID
在这里插入图片描述
2、这个函数是将需要上传的数据打包成一定的格式,并返回数据包的长度。
如果想要上传更多的数据,只需要拷贝memset,spintf,strcat这三条代码,将仿照温湿度数据上传的格式来写。此外需要定义一个足够大的buf数组。
在这里插入图片描述

六、发短信点灯

这部分的代码实现在串口接收中断里面,由于时间原因,我没有对短信的具体内容进行解读,只是收到任意短信后,在P2_2处的灯状态取反而已。收到短信后串口会接收到字符串+CMTI:“SM”,2 其中2代表是接收到的短信在第几条。

//如果模块接收到短信,会提示如:+CMTI:"SM",2
if(uart_buf[uart_cnt-4]=='C'&&uart_buf[uart_cnt-3]=='M'&&uart_buf[uart_cnt-2]=='T'&&uart_buf[uart_cnt-1]=='I')  
{
    
           
	uart_cnt = 0;
	led3 = ~led3;
}

关于接收短信几点总结
查询短信条数 AT+CPMS?
返回“SIM”,3,50,“SIM”,3,50,“SIM”,3,50 说明短信最多能有50条,现在有3条。
删除短信 AT+CMGD=N //N是第几条短信
删除第1条短信后,后面的第2条短信并不会成为第1条短信,所以要删除第2条还得发AT+CMGD=2指令。
SIM800L在接收到短信后,会输出字符串+CMTI:“SM”,2
在读取短信前应该把短信设置为文本格式,不然读取出来的是一连串看不懂的数字
短信设置为文本格式:AT+CMGF=1
读取短信: AT+CMRD=N //N是第几条短信

七、收发短信、拨打电话

SIM800L最基本的功能还是用来收发短信和拨打电话,代码中也有写

void send_msg(char *phone,char *msg);     //发送短信
void call_phone(char *phone);             //拨打电话

总结

使用SIM800L将温湿度数据上传到OneNET里面,重点是如何将数据打包好,如果发送的数据格式不对,就会与OneNET服务器断开连接。代码还有需要改进的地方,有时候程序会突然卡死,不知道什么原因。

猜你喜欢

转载自blog.csdn.net/NICHUN12345/article/details/124646317