android app控制stm32开发板,并上传温湿度数据
整体项目条件:
硬件端:野火指南者(F103)+esp8266+SHTC3(温湿度传感器)
软件环境:eclipse(集成了ADT开发工具)
1、主函数部分
主函数中的初始化代码只要有四个,其他的都是无关紧要的,首先是串口的初始化,串口主要是用来打印调试信息的,然后是系统嘀嗒定时器的初始化,嘀嗒定时器?顾名思义–>用来定时的?定时倒是没必要了这里使用嘀嗒定时器主要是用来延时的。这两部分代码就不贴上来了,有需要的可以到野火论坛下载相关的代码即可。
对了,忘了还有一个温湿度的初始化函数,这个函数主要看你使用的温湿度传感器,我使用的是I2C协议的SHTC3温湿度传感器。、
2、功能函数
主函数中最重要的就是ESP8266_Init ()函数和ESP8266_StaTcpClient_UnvarnishTest()函数了,下面对这两个函数进行详细讲解。
首先是ESP8266_Init ()函数
在这个函数中对esp8266进行引脚初始化
static void ESP8266_GPIO_Config ( void )
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置 CH_PD 引脚*/
macESP8266_CH_PD_APBxClock_FUN ( macESP8266_CH_PD_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = macESP8266_CH_PD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( macESP8266_CH_PD_PORT, & GPIO_InitStructure );
/* 配置 RST 引脚*/
macESP8266_RST_APBxClock_FUN ( macESP8266_RST_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN;
GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure );
}
配置wifi串口传输
static void ESP8266_USART_Config ( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART clock */
macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
/* USART GPIO config */
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(macESP8266_USARTx, &USART_InitStructure);
/* 中断配置 */
USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断
USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口总线空闲中断
ESP8266_USART_NVIC_Configuration ();
USART_Cmd(macESP8266_USARTx, ENABLE);
}
复位wifi以及是否使能wifi(初始化的时候先不使能,等到后面真正开始使用的时候在进行使能)
这两个并不是一个函数,只是两个宏定义
ESP8266_StaTcpClient_UnvarnishTest()函数。这个函数是测试函数,也就是整个程序的主要任务部分
void ESP8266_StaTcpClient_UnvarnishTest ( void )
{
char text[50];
uint8_t ucId;
//uint8_t ucLed1Status = 0, ucLed2Status = 0, ucLed3Status = 0;
char cStr [ 100 ] = { 0 }, cCh;
char * pCh;
printf ( "\r\n正在配置 ESP8266 ......\r\n" );
macESP8266_CH_ENABLE();
ESP8266_AT_Test ();
ESP8266_Net_Mode_Choose ( AP );
while ( ! ESP8266_CIPAP ( macUser_ESP8266_TcpServer_IP ) );
//开启wifi,设置wifi的密码,设置wifi的加密方式
while ( ! ESP8266_BuildAP ( macUser_ESP8266_BulitApSsid, macUser_ESP8266_BulitApPwd, macUser_ESP8266_BulitApEcn ) );
//是否开启多连接
ESP8266_Enable_MultipleId ( ENABLE );
while ( ! ESP8266_StartOrShutServer ( ENABLE, macUser_ESP8266_TcpServer_Port, macUser_ESP8266_TcpServer_OverTime ) );
//获取ap的名称,密码,端口
ESP8266_Inquire_ApIp ( cStr, 20 );
printf ( "\r\n本模块WIFI为%s,密码开放\r\nAP IP 为:%s,开启的端口为:%s\r\n手机网络助手连接该 IP 和端口,最多可连接5个客户端\r\n",
macUser_ESP8266_BulitApSsid, cStr, macUser_ESP8266_TcpServer_Port );
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
while ( 1 )
{
SHTC3_MEASUREMENT_TEMP_HUM();
//printf("温度值:%d.%d\n",TEMP_DATA,decimal);
//printf("湿度值:%d%\n",HUM_DATA);
Delay_ms(200);
//接收到的数据格式:+IPD,<id>,<len>:<data>
//一次数据接收完毕
if (strEsp8266_Fram_Record .InfBit .FramFinishFlag)
{
USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, DISABLE ); //禁用串口接收中断
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
printf ( "接收到的内容是:%s\r\n", strEsp8266_Fram_Record .Data_RX_BUF );
//判断接收到的数据中是否有更新温湿度数据命令
if ( ( pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CMD_LED_" ) ) != 0 )
{
//接收到的数据(不包括前面的IPD,id以及len)从第0个数据地址开始,+1就等于+往后移动一个char的地址 就是移动两个字节
cCh = * ( pCh + 8 );
switch ( cCh )
{
case '1': //CMD_LED_11
cCh = * ( pCh + 9 );
switch ( cCh )
{
case '0':
macLED1_OFF ();
//ucLed1Status = 0;
break;
case '1':
macLED1_ON ();
//ucLed1Status = 1;
break;
default :
break;
}
break;
case '2':
cCh = * ( pCh + 9 );
switch ( cCh )
{
case '0':
macLED2_OFF ();
// ucLed2Status = 0;
break;
case '1':
macLED2_ON ();
// ucLed2Status = 1;
break;
default :
break;
}
break;
case '3':
cCh = * ( pCh + 9 );
switch ( cCh )
{
case '0':
macLED3_OFF ();
// ucLed3Status = 0;
break;
case '1':
macLED3_ON ();
// ucLed3Status = 1;
break;
default :
break;
}
break;
default :
break;
}
}
else if( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "Updata_H_T" ) != 0 )
{
printf("稍等!正在打包温湿度数据...\n");
//清空数组
memset(text, 0, sizeof(text));
strcpy(cStr, "{");
memset(text, 0, sizeof(text));//将text清零
sprintf(text, "\"Temp\":%d.%d,",TEMP_DATA,decimal);//控制精度并打印到text中
strcat(cStr, text);//将字符串text添加到buf结尾处并添加'\0'
memset(text, 0, sizeof(text));//将text清零
sprintf(text, "\"Humi\":%d%%",HUM_DATA);//控制精度并打印到text中
strcat(cStr, text);//将字符串text添加到buf结尾处并添加'\0'
strcat(cStr, "}");
}
if ( ( pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD," ) ) != 0 )
{
//此时拿到的id是一个字符,要将字符编程一个int类型,就需要-'0'
printf("获取ID\n");
ucId = * ( pCh + strlen ( "+IPD," ) ) - '0';
printf("获取到的id是:%c\n",ucId );
printf("需要发送上的内容是:%s\n",cStr );
//将数据发送给客户端
ESP8266_SendString (DISABLE, cStr, strlen ( cStr ), ( ENUM_ID_NO_TypeDef ) ucId);
//发送完一次的数据之后就清空数组,为下次发送做准备
memset(cStr, 0, sizeof(cStr));
}
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中断
}
}
}
(1)在这一块函数中我们首先对esp8266进行使能
macESP8266_CH_ENABLE();
(2)AT指令测试
ESP8266_AT_Test ();
void ESP8266_AT_Test ( void )
{
char count=0;
macESP8266_RST_HIGH_LEVEL();
Delay_ms ( 1000 );
while ( count < 10 )
{
if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) return;
ESP8266_Rst();
++ count;
}
}
(3)设置esp8266为AP模式,AP模式就是esp8266作为一个路由器,发出wifi热点,后面手机需要接入这个热点,app才能通过wifi与指南者进行通行,如果还想了解更多关于AP模式或者esp8266的相关信息的话可以去看看乐鑫的官方手册。
ESP8266_Net_Mode_Choose ( AP );
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
switch ( enumMode )
{
case STA:
return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 );
case AP:
return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 );
case STA_AP:
return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 );
default:
return false;
}
}
做完这些工作之后就可以配置wifi的密码 名称,开放端口等等。
while ( ! ESP8266_CIPAP ( macUser_ESP8266_TcpServer_IP ) );
//开启wifi,设置wifi的密码,设置wifi的加密方式
while ( ! ESP8266_BuildAP ( macUser_ESP8266_BulitApSsid, macUser_ESP8266_BulitApPwd, macUser_ESP8266_BulitApEcn ) );
//是否开启多连接
ESP8266_Enable_MultipleId ( ENABLE );
while ( ! ESP8266_StartOrShutServer ( ENABLE, macUser_ESP8266_TcpServer_Port, macUser_ESP8266_TcpServer_OverTime ) );
//获取ap的名称,密码,端口
ESP8266_Inquire_ApIp ( cStr, 20 );
printf ( "\r\n本模块WIFI为%s,密码开放\r\nAP IP 为:%s,开启的端口为:%s\r\n手机网络助手连接该 IP 和端口,最多可连接5个客户端\r\n",
macUser_ESP8266_BulitApSsid, cStr, macUser_ESP8266_TcpServer_Port );
涉及太多代码了,后面就不贴完整代码了,只贴出重要部分。。。
指南者接收来自app的数据
接收到的数据是有格式的,后面对数据进行读取的时候需要根据格式进行一个字节一个字节读取
指南者发送数据(发送数据的前提是app给指南者发送命令)
else if( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "Updata_H_T" ) != 0 )
{
printf("稍等!正在打包温湿度数据...\n");
//清空数组
memset(text, 0, sizeof(text));
strcpy(cStr, "{");
memset(text, 0, sizeof(text));//将text清零
sprintf(text, "\"Temp\":%d.%d,",TEMP_DATA,decimal);//控制精度并打印到text中
strcat(cStr, text);//将字符串text添加到buf结尾处并添加'\0'
memset(text, 0, sizeof(text));//将text清零
sprintf(text, "\"Humi\":%d%%",HUM_DATA);//控制精度并打印到text中
strcat(cStr, text);//将字符串text添加到buf结尾处并添加'\0'
strcat(cStr, "}");
}
if ( ( pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD," ) ) != 0 )
{
//此时拿到的id是一个字符,要将字符编程一个int类型,就需要-'0'
printf("获取ID\n");
ucId = * ( pCh + strlen ( "+IPD," ) ) - '0';
printf("获取到的id是:%c\n",ucId );
printf("需要发送上的内容是:%s\n",cStr );
//将数据发送给客户端
ESP8266_SendString (DISABLE, cStr, strlen ( cStr ), ( ENUM_ID_NO_TypeDef ) ucId);
//发送完一次的数据之后就清空数组,为下次发送做准备
memset(cStr, 0, sizeof(cStr));
}
为了后面方便app读取接收到的数据,这里使用json的格式进行打包发送
。。。。一次性写太多看着难受,下次再写关于app部分的吧
能力有限,有错误的地方希望大家批评指正!