通过WIFI或GPRS上传温度到云端
本篇博客将介绍如何使用WIFI或GPRS模块将温度数据上传到云端。我们将涵盖连接网络的过程、上传数据的过程以及相关代码。
准备工作
在开始之前,我们需要准备以下材料:
- STM32F4开发板
- 温度传感器(例如18B20)
- WIFI模块或GPRS模块
- 连接线
接下来,按照以下步骤进行准备:
- 将温度传感器连接到STM32F4开发板,确保传感器正常工作并能够读取温度数据。
- 将WIFI模块或GPRS模块连接到STM32F4开发板,并进行相应的配置。
完成上述准备后,我们可以开始编写代码。
实现过程
根据原理图,我们需要进行一下设置
- 配置串口1
- 配置AHB2
- DMA2
- APB2
1.串口初始化
首先,我们需要初始化串口以便与
ESP8266
进行通信。
在STM32F4上,我们可以使用UART来与ESP8266进行串口通信。以下是一个示例代码片段,用于初始化串口:
修改文件:usart.c
void USART1_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //串口1时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // GPIOB时钟
GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_USART1); //PB10复用为USART1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_USART1); //PA11复用为USART1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PA2-TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
//USART3_RX PB11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11
USART_InitStructure.USART_BaudRate = 115200;//波特率一般设置为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(USART1, &USART_InitStructure); //初始化串口 1
USART_Cmd(USART1, ENABLE); //使能串口
//使能接收中断
//设置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
TIM2_Init(1000-1,7200-1); //中断
USART1_RX_STA=0; //清零
TIM_Cmd(TIM2,ENABLE); //关闭定时器2
}
2. 网络配置
- 连接服务器
- 配置网络
在连接WIFI之前,我们需要配置ESP8266的网络参数。以下是一个示例代码片段,用于配置ESP8266的网络参数:
#include "esp8266.h"
#include "string.h"
#include "usart.h"
#include "stm32f4xx.h"
#include "sys1.h"
#include "delay.h"
#include "stdlib.h"
char flag = 0;
void esp8266_Init(){
cs_init();
esp8266_quit_trans();
esp8266_start_trans(); //esp8266进行初始化
wifigotcompleteflag=1;
}
//ESP8266模块和PC进入透传模式
void esp8266_start_trans(void)
{
u8 *str;
//设置工作模式 1:station模式 2:AP模式 3:兼容 AP+station模式
while(esp8266_send_cmd("AT+CWMODE=1","OK",50))
{
printf("AT+CWMODE_ERR\r\n");
}
printf("AT+CWMODE_OK\r\n");
//让Wifi模块重启的命令
while(esp8266_send_cmd("AT+RST","ready",50));
{
printf("AT+RST_ERR\r\n");
}
printf("AT+RST_OK\r\n");
delay_ms(1000); //延时3S等待重启成功
delay_ms(1000);
printf("delay_OK\r\n");
while(esp8266_send_cmd("AT+CWJAP=\"wifi名称\",\"WiFi密码\"","WIFI GOT IP",200))
{
printf("WIFI GOT IP_ERR\r\n");
}
//=0:单路连接模式 =1:多路连接模式
while(esp8266_send_cmd("AT+CIPMUX=0","OK",30))
{
printf("AT+CIPMUX_ERR\r\n");
}
//建立TCP连接 这四项分别代表了 要连接的ID号0~4 连接类型 远程服务器IP地址 远程服务器端口号
while(esp8266_send_cmd("AT+CIPSTART=\"TCP\",\"远程服务器ip\",远程服务器端口号","CONNECT",200))
{
printf("AT+CIPSTART_ERR\r\n");
}
//是否开启透传模式 0:表示关闭 1:表示开启透传
while(esp8266_send_cmd("AT+CIPMODE=1","OK",200))
{
printf("AT+CIPMODE_ERR\r\n");
}
//透传模式下 开始发送数据的指令 这个指令之后就可以直接发数据了
while(esp8266_send_cmd("AT+CIPSEND","OK",50))
{
printf("AT+CIPSEND_ERR\r\n");
}
printf("连接服务器完成\r\n");
}
u8 esp8266_quit_trans(void)
{
u8 result=1;
u1_printf("+++");
delay_ms(1000); //等待500ms太少 要1000ms才可以退出
result=esp8266_send_cmd("AT","OK",200);//退出透传判断.
if(result)
printf("quit_trans failed!");
else
printf("quit_trans success!");
return result;
}
//向ESP8266发送命令
//cmd:发送的命令字符串;ack:期待的应答结果,如果为空,则表示不需要等待应答;waittime:等待时间(单位:10ms)
//返回值:0,发送成功(得到了期待的应答结果);1,发送失败
u8 esp8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
{
u8 res=0;
USART1_RX_STA=0;
u1_printf("%s\r\n",cmd); //发送命令
if(ack&&waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(20);
if(USART1_RX_STA&0X8000)//接收到期待的应答结果
{
if(esp8266_check_cmd(ack))
{
printf("ack:%s\r\n",(u8*)ack);
break;//得到有效数据
}
USART1_RX_STA=0;
}
}
if(waittime==0)res=1;
}
return res;
}
//ESP8266发送命令后,检测接收到的应答
//str:期待的应答结果
//返回值:0,没有得到期待的应答结果;其他,期待应答结果的位置(str的位置)
u8* esp8266_check_cmd(u8 *str)
{
char st[20];
char *strx=0;
if(USART1_RX_STA&0X8000) //接收到一次数据了
{
USART1_RX_BUF[USART1_RX_STA&0X7FFF]=0;//添加结束符
strx=strstr((const char*)USART1_RX_BUF,(const char*)str);
}
return (u8*)strx;
}
//向ESP8266发送数据
//cmd:发送的命令字符串;waittime:等待时间(单位:10ms)
//返回值:发送数据后,服务器的返回验证码
u8* esp8266_send_data(u8 *cmd,u16 waittime)
{
char temp[5];
char *ack=temp;
USART1_RX_STA=0;
u1_printf("%s",cmd); //发送命令
if(waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(10);
if(USART1_RX_STA&0X8000)//接收到期待的应答结果
{
USART1_RX_BUF[USART1_RX_STA&0X7FFF]=0;//添加结束符
ack=(char*)USART1_RX_BUF;
//printf("ack:%s\r\n",(u8*)ack);
USART1_RX_STA=0;
break;//得到有效数据
}
}
}
return (u8*)ack;
}
extern u8 wifigotcompleteflag;
char stehttpbehind[500]=" HTTP/1.1\r\n\
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n\
Accept-Encoding: gzip, deflate\r\n\
Accept-Language: zh-CN,zh;q=0.9\r\n\
Connection: keep-alive\r\n\
Host: 192.168.0.109:8001\r\n\
Upgrade-Insecure-Requests: 1\r\n\
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36\r\n\r\n";
void esp8266_http_send(char *sb){
char stehttp[600]="GET /";
strcat((char*)stehttp,sb);
strcat((char*)stehttp,stehttpbehind);
u1_printf("%s",stehttp);
}
int fflag;
void Wifi_data(char *Wifi_data){
char sp[20];
char* Point=NULL;
if(strstr((const char *)Wifi_data, (const char *)"ctrl=")!=NULL)//接收到设置阈值命令
{
Point = strstr((const char *)Wifi_data, (const char *)"ctrl=")+5;
memcpy(sp, Point, 3);
fflag=atoi(sp);
}
}
void cs_init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
sys_gpio_set(GPIOE, SYS_GPIO_PIN7,
SYS_GPIO_MODE_OUT, SYS_GPIO_OTYPE_OD, SYS_GPIO_SPEED_MID, SYS_GPIO_PUPD_PU);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
/* 数据端口输出 */
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE, GPIO_Pin_7 );
}
3. 温度上传
温度上传的过程涉及到从温度传感器读取温度值,并将其发送到云端。
在你的已完成的温度获取模块中,可能有相应的函数来读取温度值。以下是一个示例代码片段,用于上传温度值到云端:
while (1)
{
temperature = ds18b20_get_temperature();
TEMP_SEND=(float)temperature/10;
printf("temp:%f",TEMP_SEND);
sprintf(send_string,"temp:%f",TEMP_SEND);
printf("°´¼ü£º%d",KEYD6);
u1_printf(send_string);
}
4.打开网络助手
打开网络调试助手(NetAssist
软件)设置为TCP Server
数据将会被上传到这里