想玩物联网的时候物色了很多国内的云平台,最后选了中移云去实现。其实阿里云华为云机智云都不错,机智云网页界面不行但是带APP,阿里云也有个贝壳物联APP功能更强大,华为云不太了解不过好像也还行。中移云感觉更加的纯粹,没有那么多花里胡哨的功能(其实是我用不到而已)。这里记录一下基于4个stm32+lora建立组网,上传数据到云平台这个简单的项目。

硬件环境

硬件环境即一个主控板(照片找不到了)+三个采集板,基于LORA构建组网,采集3个不同地点的环境数据,通过WIFI模块上发数据到云平台。外加一个OpenMV3做人脸识别。采集板挂载了温湿度+光照强度+LORA模块。

软件环境

IDE:Keil 5.15
OS:Ucos-III

ESP8266 WIFI模块基本知识详解

市面上的WIFI模块大多数都是乐鑫的,通过串口+AT指令,即可简单的进行操作。
硬件连接:

AT指令基本结构:

WIFI模块和服务器建立连接有两种方式:

TCP连接通信比较常用,再该模式下,相应的设备必须处于同一网络中,即处于同一个局域网中!!!AP模式下ESP8266做服务端时就是,手机和电脑必须连在ESP8266的WiFi,才能用网络调试助手等软件与ESP8266通信。

WIFI 模块的AT指令配置大家看官方文档即可,整体了来说还是比较简单的。WIFI一般有WIFI-AP模式,WIFI-STA模式,WIFI-AP兼STA模式三种,这里只说常用的前两种:
①、WIFI-AP模式:首先,我们可以把WIFI模块当成一个热点,开启热点以后别的设备可以连接这个热点,从而我们就可以向连接热点的设备
!!发送数据!!
ESP8266建立TCP服务器时,步骤为:
1.AT+CWMODE=2//配置ESP8266为AP模式,(路由器模式,发出WIFI)。

2.AT+RST // 重启模块使刚刚配置模式生效
3.AT+CWSAP=“wifi账号”,“WIFI密码”,1,4

4.AT+CIPMUX = 1 // 启动多连接
5.AT+CIPSERVER = 1,8080 // 模块开启服务器模式,端口号8080
这一步一定要保证设备连接到了ESP8266的WIFI,不然会连接失败
6.AT+CIPSEND=X,X // 第一个X是对应的ID号,第二个X是对应的字符个数,调用这个AT指令就可以向对应的客户端发送数据,注意对应的字符个数问题,如果个数少了就不发,个数多了就只发前对应的个数。
以上,便是ESP8266做服务器,PC端(移动端)做客户端的情况。

ESP8266做客户端,PC端(移动端)做服务器时(单路连接),具体的步骤简要为:
完成连接后,调用AT+CIPSEND这个指令即可与服务器收发数据。这里我们只介绍单路连接,这种模式下是可以做到最多5路连接,感兴趣的话可以查一下相关资料。

②.WIFI-STA模式:这个模式与AP模式相反,是ESP8266去连接别的路由器(WIFI),只要保证与通信方处于同一局域网下即可,可以理解为一个基站去接收信号。
ESP8266做服务器,PC做客户端,具体步骤为:

到这里,我们发送AT+CWLAP指令可以查询周围的WIFI信号(去酒店之类的可以用这招预防那种WIFI摄像头,但是SD卡那种还是防不了的。。)
发送AT+CWJAP?可以查看WIFI是否真的连接成功。
4.AT+CIPMUX=1启动多连接
5.AT+CIPSERVER=1,8080 // 打开服务器端口为8080
6.AT+CIFSR // 看一下你模块现在分配的ip是多少,只要模块联网就会重新分配ip地址,这也是网络调试助手里面远程主机栏要填写的ip地址。

ESP8266做客户端,PC端(移动端)做服务器,具体步骤如下:
1.AT+CWMODE=1,设置为STA模式
2.AT+RST , 重启生效
3.AT+CWJAP=“WIFI账号”,“WIFI密码”
4.AT+CIPMUX=0 ,单连接
5.AT+CIPSTART=“TCP”,“192.168.1.101”,8080
下面用AT+CIPSEND发送数据即可

这次工程是把WIFI模块配成STA模式下的客户端,网站就当成服务器,方便操作。

OneNET建立自己的物联网应用

首先来个官网网址中移云网址,进去以后注册一个自己的账号

点击开发者中心,然后创建自己的产品。这里跟着官方文档走就好了,不多赘述创建产品
接入协议这里选择http协议,因为我们只需要POST上报数据,GET获得数据即可。有能力的话建议搞一下MQTT协议,近两年最火的物联网协议。然后建一个设备,这里跟着官方文档走就可以了。最后我们会得到这些必要信息:

这四个ID/key是上报数据必须的东西,要做好记录。至此平台端我们已经解决了大半。

收发协议

因为涉及了不同设备多个数据的采集,这里制定了一个简单的协议,只有一个帧头采集板发过来的帧头到主控板会被识别为ASCII码,所以主控接收从机帧头时一定要以ASCII码形式判断。其实出来实习以后,发现这些协议走16进制的话会更方便,便于不同平台之间交互。下面上代码:

u8 a = 0;
u8 b = 0;
u8 c = 0;
u8 RX1_Buff[3];
u8 RX2_Buff[3];
u8 RX3_Buff[3];
int i = 1;
int j = 1;
int k = 1;
char one = '1';
char two = '2';
char three = '3';void USART2_IRQHandler(void)
{u8 res;{res=USART_ReceiveData(USART2);//printf("%c",res);if(res == one){a = 1;two = '7';three = '8';}if(a == 1){switch(i){case 1:i++;break;case 2:i++;RX1_Buff[0] = res;break;case 3:i++;RX1_Buff[1] = res;break;case 4:i++;RX1_Buff[2] = res;i=1;a=0;two = '2';three = '3';break;default:break;}}if(res == two){b=1;one = '6';three = '8';}if(b == 1){switch(j){case 1:j++;break;case 2:j++;RX2_Buff[0]=res;;break;case 3:j++;RX2_Buff[1]=res;;break;case 4:j++;RX2_Buff[2]=res;j=1;b=0;one = '1';three = '3';break;default:break;}}if(res == three){c = 1;one = '6';two = '7';}if(c == 1){switch(k){case 1:k++;break;case 2:k++;RX3_Buff[0]=res;break;case 3:k++;RX3_Buff[1]=res;break;case 4:k++;RX3_Buff[2]=res;k=1;c=0;one = '1';two = '2';break;default:break;}}LED0 = ~LED0;printf("从机1%d,%d,%d\r\n",RX1_Buff[0],RX1_Buff[1],RX1_Buff[2]);printf("从机2%d,%d,%d\r\n",RX2_Buff[0],RX2_Buff[1],RX2_Buff[2]);printf("从机3%d,%d,%d\r\n",RX3_Buff[0],RX3_Buff[1],RX3_Buff[2]);USART_ClearITPendingBit(USART2,USART_IT_RXNE);}
}

其实思想就是每个从机都有自己的一个帧头,后面分别跟着温度湿度光照强度等环境数据。

与OneNET云平台的交互

这里我们把WIFI模块设置为STA工作模式,就是把WIFI模块连接我们手机的热点,然后与OenNET云平台建立TCP连接,开启透传模式。数据通过POST发送,打包成JSON格式。现在知道了官方有个cJSON,经过简单的移植就可以自动打包JSON数据,但是当时年少无知,就直接手打JSON格式就好了。datastreams这个数据后面跟着传感器的名称和数据流的名称即可。api-key从前面我们说的地方获取即可,Host则直接用这个网址就好,Content-Length的值一定要和datastreams后面的大小对应,不然会报格式错误。

#include "common.h"
#include "stdlib.h"
#include "string.h"
#include "dht11.h"
#include "adc.h"
#include "lsens.h"
#include "led.h"
//ATK-ESP8266 WIFI STA测试
//用于测试TCP/UDP连接
//返回值:0,正常
//    其他,错误代码
extern u8 RX1_Buff[3];
extern u8 RX2_Buff[3];
extern u8 RX3_Buff[3];
u8 atk_8266_wifista_test(void)
{u8 key;u8 timex=0; u8 b;char RX_Buff[200];u8 strData[2];u8 *p;u8 *q;u8 *m;u16 t=9999;  //加速第一次获取链接状态u8 res=0;u16 rlen=0;u8 constate=0; //连接状态HC_Init();//LORA数据收发协议初始化atk_8266_send_cmd("AT+CWMODE=1","OK",500);  //设置WIFI STA模式atk_8266_send_cmd("AT+RST","OK",200);  //DHCP服务器关闭(仅AP模式有效) delay_ms(1000);         //延时3S等待重启成功delay_ms(1000);//设置连接到的WIFI网络名称/加密方式/密码,这几个参数需要根据自己的路由器设置进行修改!! //sprintf((char*)p,"AT+CWJAP=\"%s\",\"%s\"",wifista_ssid,wifista_password);//设置无线参数:ssid,密码 p = "AT+CWJAP=\"mayday123\",\"sunshine998\"";while(atk_8266_send_cmd(p,"WIFI GOT IP",3000));     //连接目标路由器,并且获得IP{atk_8266_send_cmd("AT+CIPMUX=0","OK",200);   //0:单连接,1:多连接q = "AT+CIPSTART=\"TCP\",\"183.230.40.33\",80";//sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s",(u8*)ipbuf,(u8*)portnum);    //配置目标TCP服务器while(atk_8266_send_cmd(q,"OK",2000));atk_8266_send_cmd("AT+CIPMODE=1","OK",2000);      //传输模式为:透传   }USART3_RX_STA=0;atk_8266_quit_trans();atk_8266_send_cmd("AT+CIPSEND","OK",200);         //开始透传 while(1){/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
///***********************************发送第一从机温度数据**************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:63\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"temp_num\",\"datapoints\":[{\"value\":%d}]}]}",RX1_Buff[0]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
///******************************************************************************************/
delay_ms(500);
///***********************************发送第一从机湿度数据**************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:63\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"humi_num\",\"datapoints\":[{\"value\":%d}]}]}",RX1_Buff[1]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
///******************************************************************************************/
delay_ms(500);
///***********************************发送第一从机光照强度数据************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:63\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"illu_num\",\"datapoints\":[{\"value\":%d}]}]}",RX1_Buff[2]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
///******************************************************************************************/
delay_ms(500);
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/***********************************发送第二从机温度数据**************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"temp1_num\",\"datapoints\":[{\"value\":%d}]}]}",RX2_Buff[0]); u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
/*********************************************************************************************/
delay_ms(500);
///***********************************发送第二从机湿度数据**************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"humi1_num\",\"datapoints\":[{\"value\":%d}]}]}",RX2_Buff[1]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
///******************************************************************************************/
delay_ms(500);
///***********************************发送第二从机光照强度数据************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"illu1_num\",\"datapoints\":[{\"value\":%d}]}]}",RX2_Buff[2]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
/******************************************************************************************/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/***********************************发送第三从机温度数据**************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"temp2_num\",\"datapoints\":[{\"value\":%d}]}]}",RX3_Buff[0]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
/*********************************************************************************************/
delay_ms(500);
/***********************************发送第三从机湿度数据*************************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"humi2_num\",\"datapoints\":[{\"value\":%d}]}]}",RX3_Buff[1]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
///******************************************************************************************/
delay_ms(500);
///***********************************发送第三从机光照强度数据*********************************/sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:64\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"illu2_num\",\"datapoints\":[{\"value\":%d}]}]}",RX3_Buff[2]);u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}
/******************************************************************************************/ delay_ms(500);if(LED2 == 1){sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:63\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"open_see\",\"datapoints\":[{\"value\":11}]}]}");u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}}else{sprintf(RX_Buff,"POST /devices/526305478/datapoints HTTP/1.1\r\n\
api-key:AXFPHI6MWoj6oTvz6MQVyEGANR0=\r\n\
Host:api.heclouds.com\r\n\
Content-Length:63\r\n\
\r\n\
{\"datastreams\":[{\"id\":\"open_see\",\"datapoints\":[{\"value\":22}]}]}");u3_printf("%s",RX_Buff);
//    delay_ms(500);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}}
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/     atk_8266_at_response(1);for(b = 0;b < sizeof(RX_Buff);b++){RX_Buff[b] = 0 ;}  }return res;
}

AT指令的发送直接用了原子的程序,在串口中断里根据协议接收数据然后上发到云平台即可。简要来说就是:
通过将WIFI连接上网络,解析出OneNET云平台的IP和端口号,在云平台新建设备,每个设备会分配一个独有的序列号(用于WIFI与设备连接),然后通过AT指令,将WIFI模块连接上云平台,此时用WIFI发送在云平台新建好的设备的序列号,即可连接设备,与设备进行通信。然后定时发送从采集板收到的数据,当数据超过云平台的报警值之后,云平台会自动报警,并将报警信息通过用户绑定邮箱发送给用户,实现实时监测的效果。

把每个步骤都打印出来:

当执行到指令AT+CIPSEND时,将数据打包成JSON格式发送即可。

反馈的信息为:

这个项目比较简单不需要解析反馈的JSON格式的数据,当error后面为0时,则代表数据上传正确。

下面介绍两个比较重要的点。
如何截取整段反馈的JSON报文

//串口接收缓存区
u8 USART3_RX_BUF[USART3_MAX_RECV_LEN];     //接收缓冲,最大USART3_MAX_RECV_LEN个字节.
u8 USART3_TX_BUF[USART3_MAX_SEND_LEN];    //发送缓冲,最大USART3_MAX_SEND_LEN字节
//通过判断接收连续2个字符之间的时间差不大于10ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过10ms,则认为不是1次连续数据.也就是超过10ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度
vu16 USART3_RX_STA=0;
void USART3_IRQHandler(void)
{u8 res;       if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据{  res =USART_ReceiveData(USART3);   if((USART3_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据{ if(USART3_RX_STA<USART3_MAX_RECV_LEN) //还可以接收数据{TIM_SetCounter(TIM7,0);//计数器清空              //计数器清空if(USART3_RX_STA==0)     //使能定时器7的中断 {TIM_Cmd(TIM7,ENABLE);//使能定时器7}USART3_RX_BUF[USART3_RX_STA++]=res; //记录接收到的值  }else {USART3_RX_STA|=1<<15;    //强制标记接收完成} }}
}
//初始化IO 串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率
void usart3_init(u32 bound)
{  NVIC_InitTypeDef NVIC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能USART_DeInit(USART3);  //复位串口3//USART3_TX   PB10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10               //USART3_RX   PB11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11 USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART3, &USART_InitStructure); //初始化串口 3USART_Cmd(USART3, ENABLE);                    //使能串口 //使能接收中断USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断   //设置中断优先级NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   //IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器TIM7_Int_Init(10000-1,7200-1);  //100ms中断USART3_RX_STA=0;  //清零TIM_Cmd(TIM7,DISABLE);   //关闭定时器7
}

这里也是用原子的程序,其实思想很简单,第一次进入串口中断时打开定时器,一定时间(10ms)没有接收到数据就判定为一帧数据接收完毕。其实如果现在做这个的话直接用IDEL更方便,不需要这么麻烦。

串口3的重定向

//va_list 是C语言定义的宏,解决变量参数的一个宏,可以传入一个参数或多个参数,且对类型无要求,用法:
//首先在函数中,定义一个具有va_list类型的参数ap
//然后在va_start宏初始化变量刚定义的va_list类型的变量,执行:ap = (va_list)&fmt + _INTSIZEOF(fmt),此时ap指向第一个可变参数在堆栈的地址。
//函数声明:int vsprintf(char *str, const char *format, va_list arg)
//str -- str指向一个字符数组的指针,该数组存储了C字符串。
//format -- 这是字符串,包含了要被写入到字符串str的文本。它可以包含嵌入的format标签,format标签可被随后的附加参数中指定的值替换
//并按需求进行格式化。format标签属性是%[flags][width][.precision][length]specifier。
//va_end(ap)的作用是清空va_list ap。
//下面是事例,一看就懂。
void u3_printf(char* fmt,...)
{  u16 i,j; va_list ap; va_start(ap,fmt);vsprintf((char*)USART3_TX_BUF,fmt,ap);va_end(ap);i=strlen((const char*)USART3_TX_BUF);  //此次发送数据的长度for(j=0;j<i;j++)       //循环发送数据{while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   USART_SendData(USART3,USART3_TX_BUF[j]); }
}

这个其实没啥讲的,用的东西是非开源的,只要直到怎么用就好了,注释的很清楚。这样做就可以把串口3以printf的形式调用,非常方便。

效果展示




在我们的云平台是可以搭建界面的,这里显示了3地温湿度,光照强度的曲线比较,并且也可以单独显示某一个地点的环境数据,并且还有异常报警机制,就是发邮箱了。。

物联网实战之基于OneNET的智能农业系统相关推荐

  1. 物联网毕设(基于stm32的智能家居系统)

    第二节 硬件端实现 文章目录 目录 第二节 硬件端实现 文章目录 前言 一.配置ESP8266 1.ESP8266.c 2.ESP8266.h 3.如何使用 (1)初始化 (2) 进入主程序​ 二.如 ...

  2. 专题五 在Cisco Packet Tracer中设计基于 PT 和 OneNet 的智能家居系统

    摘    要 智能家居是物联网在家庭中的基础应用,随着宽带业务的普及,智能家居产品涉及到方方面面. 家中无人,可利用手机等产品客户端远程操作智能空调,调节室温,甚者还可以学习用户的使用习惯,从而实现全 ...

  3. 【毕业设计】基于zigbee的智能家居系统 - 单片机 物联网 stm32

    文章目录 1 简介 2前言 2.1 系统目标 3 系统架构 3.1 网关板设计: 3.2 ZigBee网络感知层 3.3 显示控制平台及数据保存 3.4 NB-IOT模块实现 实现效果 4 最后 1 ...

  4. 【毕业设计】基于STM32的智能路灯设计与实现 - 物联网 嵌入式 单片机

    文章目录 1 简介 2 绪论 2.1 项目背景 2.2 需求分析 3 系统设计 3.1 功能设计 3.1.1 系统角色分析 3.1.2 开发环境 3.2 总体设计 3.3 硬件部分 3.3.1 整体架 ...

  5. 【物联网服务NodeJs-5天学习】第三天实战篇③ ——基于MQTT的环境温度检测

    [NodeJs-5天学习]第三天实战篇③ --基于MQTT的环境温度检测 1. 前言 2.实现思路 2.1 NodeJs服务器代码 2.2.1 本地部署MQTT服务器,端口1883 2.2.1.1 用 ...

  6. java ee 物联网 论文_基于物联网的智能社区互助系统的设计研究论文

    基于物联网的智能社区互助系统的设计研究论文 1 绪论 目前行业内的智能社区解决方案分为两大阵营,无线阵营和总线阵营,无线阵营主张以互联网为平台,底层传感网使用短距离无线的传输网,并通过耦合两个异构网络 ...

  7. 基于golang的智能物联网网关的设计论文

    很抱歉,我不能提供具体的智能物联网网关的设计论文,但是我可以提供一些相关信息供您参考. 智能物联网网关是物联网系统的重要组成部分,它起到了连接物联网设备和云端服务器的作用.基于 Golang 的智能物 ...

  8. 【NodeJs-5天学习】第三天实战篇② ——基于物联网的WiFi自动打卡考勤系统

    [NodeJs-5天学习]第三天实战篇② --基于物联网的WiFi自动打卡考勤系统 1. 前言 2.实现思路 2.1 NodeJs服务器代码 2.1.1 对接Express服务器 2.1.2 对接Ma ...

  9. 【物联网服务NodeJs-5天学习】第三天实战篇② ——基于物联网的WiFi自动打卡考勤系统

    [NodeJs-5天学习]第三天实战篇② --基于物联网的WiFi自动打卡考勤系统 1. 前言 2.实现思路 2.1 NodeJs服务器代码 2.1.1 对接Express服务器 2.1.2 对接Ma ...

最新文章

  1. 单片机原理,单片机能做什么?
  2. 程序员如何切入区块链去中心化应用开发
  3. 嵌入式开发之davinci--- DVRRDK, EZSDK和DVSDK这三者有什么区别
  4. 在Android Studio上进行OpenCV 3.1开发
  5. Qt 常量中有换行符 中文
  6. luogu P4240 毒瘤之神的考验(莫比乌斯反演+递推前缀和+数论分块)
  7. HDU4911 Inversion 解题报告
  8. 前端学习(627):数据类型
  9. 分级加权评分算法 java_荐书|智能风控:原理、算法与工程实践
  10. leetcode - 303.区域和检索-数组不可变(动态规划)
  11. Raki的读paper小记:EDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification
  12. wpf自己画表盘_练手WPF(一)——模拟时钟与数字时钟的制作(上)
  13. 超星未来:让智能驾驶更简单! | 百万人学AI评选
  14. 哈尔滨工程大学学生郭天祥六年非一般的大学
  15. html制作简单框架网页 实现自己的音乐驿站 操作步骤及源文件下载 (播放功能限mp3文件)
  16. bios和boot menu的关系?
  17. 净宗科学观-净空法师讲于台南某高等学府
  18. Xilinx Alveo加速卡开发入门
  19. 史玉柱亲笔写的脑白金策划方案
  20. 编译osgEarth2.8遇到gdal_vrt.h找不到的问题

热门文章

  1. 关于“前台根据后台值,操作字段、显示或select选中状态”的几种做法
  2. JWT手动签发| 自动签发
  3. android system image 编译出错,Android framework 编译常见错误
  4. 【小5聊】C#一键设置桌面壁纸同时叠加今天工作或备注内容到壁纸上(windows窗体篇)
  5. SAP IDES ECC6.0 EHP4 安装后的RZ10参数设置 减小内存 SGEN 编译组件
  6. Windows下设置桌面壁纸的代码(QT版)
  7. 阿里云服务器调用阿里云企业邮箱
  8. Dell服务器型号的详解
  9. 深度学习入门(一)快速建立自己的图片数据集
  10. 谈谈引用和Threadlocal的那些事