续上次水质检测系统模块ESP8266替换为SIM900A

一.替换原因:

本次项目名称为基于LoRa山区水库水质检测,由此可以看到检测对象为山区的水质检测,山区用ESP8266肯定就不合适的,因为山区没有局域网,所有这里我就用2G模块SIM900A来代替ESP8266传输数据到云端。

二.SIM900A通信方式:

1.模块介绍:

2.通信注意事项:

SIM900A跟ESP8266类似也是通过串口发送AT指令进行配置的,其中需要注意的是SIM900A有两组TX和RX,其中一组为5v的TX和RX,另外一组为3.3v的TX和RX,如果后续单片机串口接在5v的TX和RX上,需要注意的是此时通信的波特率为9600;如果单片机接在3.3v的TX和RX上,此时双方通信的波特率为:115200;最后就是SIM900A供电是用5v进行供电的。

三.SIM900A常用的AT指令:

AT+CPMS                       // 查询SIM卡内短消息使用状态
AT+CNMI                       // 新消息指示设置
AT+CMGF                       // 选择短消息格式 
AT+CSCS                       // 编码设置
AT+CSCA                       // 查询、设置SMS服务中心号码
AT+CSMP                       // 设置短消息文本模式参数
AT+CMGS                      // 发送短消息
AT+CMGR                      // 读取短消息
AT+CMGD                      // 删除短消息
AT+CMGDA                     // 删除所有短消息
AT&F                         // 恢复出厂设置
AT+CSQ                       // 信号质量

更多的AT指令可以是找对应的开发文档,这里就不在一一展示了,咱们在开发这个模块的时候,可以首先用串口调试器进行测试一下这个模块,调试成功后才能更加方便程序设计。

四.SIM900A程序设计:

1.串口初始化程序

我这里单片机的串口2接在了SIM900A模块5v的TX和RX,所有这里的波特率就应该是9600.

//Usart2_Init(9600);    //5TX---PA3   5RX---PA2


void Usart2_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//PA2	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA3	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送
	usartInitStruct.USART_Parity = USART_Parity_No;									//无校验
	usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位
	USART_Init(USART2, &usartInitStruct);
	
	USART_Cmd(USART2, ENABLE);														//使能串口
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中断
	
	nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvicInitStruct);

}


void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}

}

2.SIM900A模块初始化程序

/*==================================================
函数  功能:GSM模块初始化检测
函数返回值:1表示模块检测失败,0表示成功
===================================================*/
u8 SIM800C_InitCheck(void)
{
		UsartPrintf(USART_DEBUG, "01. AT\r\n");
		while(ESP8266_SendCmd("AT\r\n", "OK"))
		 delay_ms(500);
		
		UsartPrintf(USART_DEBUG, "02. ATE0\r\n");
		while(ESP8266_SendCmd("ATE0\r\n", "OK"))
		 delay_ms(500);
		
		UsartPrintf(USART_DEBUG, "03. AT+CGMI\r\n");
		while(ESP8266_SendCmd("AT+CGMI\r\n", "OK"))
		 delay_ms(500);
		
		UsartPrintf(USART_DEBUG, "04. AT+CGMM\r\n");
		while(ESP8266_SendCmd("AT+CGMM\r\n", "OK"))
		 delay_ms(500);
			
		return 0;
}

3.SIM900A模块与OneNET建立TCP连接

/*=======================================================
函数功能: 连接TCP服务器
函数参数: 
				ipaddr:ip地址
				port:端口 
返 回 值: 0表示成功,其他值表示失败
========================================================*/
u8 SIM800C_Connect_TCP_Server(char *ipaddr,char *port)
{
	 char cmd_buff[100];
	 
	 ESP8266_SendCmd("AT+CIPSHUT\r\n","SHUT OK");		//关闭移动场景 
	 sprintf(cmd_buff,"AT+CIPSTART=\"TCP\",\"%s\",\"%s\"\r\n",ipaddr,port);
	 while(ESP8266_SendCmd(cmd_buff,"OK"))
	 {
		 	delay_ms(500);	
	 }
	 printf("TCP 连接成功\r\n");
	 
	 return 0;
	
}

4.SIM900A模块采用HTTP协议方式向OneNET服务器上报数据

我这里采用了count来计算SIM900A向OneNET云平台发送数据错误的次数,当错误小于等于5次时,就重新进行一次与OneNET建立TCP连接,这样效果就会很好,经过24小时的长时间测试,SIM900A会一直向OneNET发送数据而不会断。

int count=0;
void OneNet_HTTP_DataUpdate(float temp,float tds, float ph)
{
		char OneNet_HTTP_CMD[400]={0};
		char OneNet_HTTP_BUFF[200]={0};
	
	  snprintf(OneNet_HTTP_BUFF,sizeof(OneNet_HTTP_BUFF),
			"{\"datastreams\":[{\"id\":\"Temp\",\"datapoints\":[{\"value\":%.1f}]},{\"id\":\"TDS\",\"datapoints\":[{\"value\":%.1f}]},{\"id\":\"PH\",\"datapoints\":[{\"value\":%.1f}]}]}",temp,tds,ph);

		//拼接数据
		snprintf(OneNet_HTTP_CMD,sizeof(OneNet_HTTP_CMD),
			"POST /devices/%s/datapoints HTTP/1.1\r\n"\
			"api-key:%s\r\n"\
			"Host:api.heclouds.com\r\n"\
			"Content-Length:%d\r\n"\
			"\r\n"\
			"%s",
	  ONENET_DEVICE_ID,ONENET_API_KEY,strlen(OneNet_HTTP_BUFF),OneNet_HTTP_BUFF);
		
		
		if( SIIM800C_TCP_SendData( (u8*)OneNet_HTTP_CMD,strlen(OneNet_HTTP_CMD) ) == 0 )
		{
			printf("send data ok!\r\n");
		}
		else
		{
			printf("send data error!\r\n");
			count++;
			if(count >= 5)
			{
				count=0;
				while(SIM800C_Connect_TCP_Server("183.230.40.33","80"))
				{
					delay_ms(500);
				}
			}
			
		}			
}

5.主程序

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "usart3.h"
#include "key.h"
#include "stdio.h"
#include "string.h"
#include "lora.h"
#include "sim800c.h"
#include "time.h"




//Lora接收数据数组
extern char lora_rx_data[50];
extern char lora_rx_data2[50];



//接收数据变量
float Temp=0.0;
float TDS=0.0;
float PH=0.0;



int main()
{
/*=======================================系统初始化======================================*/
	
	//时钟初始化
	SysTick_Init(72);
	
	//中断优先级分组 分2组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  
	
	//串口初始化
  Usart1_Init(115200);
	Usart2_Init(9600);    //5TX---PA3   5RX---PA2
	Usart3_Init(115200);
	
	//定时1ms
	TIM4_Init ( 99, 719 ); 
	
/*=======================================传感器初始化======================================*/
	
	//初始化SIM800C
  while(SIM800C_InitCheck())
	{
		delay_ms(500);
	}
	
	while(SIM800C_Connect_TCP_Server("183.230.40.33","80"))
	{
		delay_ms(500);
	}
	
	
	//Lora初始化
	LORA_Init();
	
	
	
/*=======================================while循环========================================*/
	while(1)
	{
		//数据接收	
		Lora_Get_Data();
		
		
		//发布数据
		if(tim_v.count_SIM > 2000)
		{
			tim_v.count_SIM=0;
			OneNet_HTTP_DataUpdate(Temp,TDS,PH);
		}
			
		
		//延时
		
		delay_ms(10);

	}

}



五.数据展示

1.OneNET数据流

2.安卓小程序数据流

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值