目录
一、项目描述
二、原理图
三、实物
四、代码
六、论文
七、资料清单
资料下载地址:基于STM32无线抄表系统
一、项目描述
1.通过串口获取电表数据,并在OLED液晶上显示;
2. 通过ESP8266WIFI模块将电表数据上传到云平台和手机APP上
二、原理图
三、实物
手机APP
云平台
四、代码
ESP8266代码
#include "bsp_esp8266.h" #include "common.h" #include#include #include #include "bsp_SysTick.h" #include "test.h" #include "bsp_usart1.h" static void ESP8266_GPIO_Config ( void ); static void ESP8266_USART_Config ( void ); static void ESP8266_USART_NVIC_Configuration ( void ); struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 }; //ESP8266接收数据结构体 void ESP8266_Init ( void ) { ESP8266_GPIO_Config (); //ESP8266模块使用到的IO口初始化 ESP8266_USART_Config (); //与ESP8266模块连接的串口初始化 macESP8266_RST_HIGH_LEVEL(); //ESP8266模块 复位脚设置为高电平 macESP8266_CH_DISABLE(); //片选引脚不选中 } static void ESP8266_GPIO_Config ( void ) { GPIO_InitTypeDef GPIO_InitStructure; 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 ); macESP8266_RST_APBxClock_FUN ( macESP8266_RST_CLK, ENABLE ); GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN; GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure ); } static void ESP8266_USART_Config ( void ) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE ); macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE ); 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 ); GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init( macESP8266_USART_RX_PORT, &GPIO_InitStructure ); 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 ); } static void ESP8266_USART_NVIC_Configuration ( void ) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x ); NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); } void macESP8266_USART_INT_FUN ( void ) { // char * pCh; // char cStr [ 100 ] = { 0 }; uint8_t ucCh; if ( USART_GetITStatus ( macESP8266_USARTx, USART_IT_RXNE ) != RESET ) //若串口中有数据进来,存储接收到的数据 { ucCh = USART_ReceiveData( macESP8266_USARTx ); if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //预留1个字节写结束符 strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = ucCh; } //进入空闲中断,说明一组数据接收完成 if ( USART_GetITStatus( macESP8266_USARTx, USART_IT_IDLE ) == SET ) //数据帧接收完毕 { strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1; //设置数据接收完成标志 ucCh = USART_ReceiveData( macESP8266_USARTx ); //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR) USART_ClearITPendingBit( macESP8266_USARTx, USART_IT_IDLE ); //检测与服务器的连接是否断开 只在Station模式下使用 ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSEDrn" ) ? 1 : 0; } } void ESP8266_Rst ( void ) { #if 1 ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 ); #else macESP8266_RST_LOW_LEVEL(); Delay_ms ( 500 ); macESP8266_RST_HIGH_LEVEL(); #endif } bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime ) { strEsp8266_Fram_Record .InfBit .FramLength = 0; //接收缓冲区数据长度清0 macESP8266_Usart ( "%srn", cmd ); //向模块发送命令 if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收数据 return true; Delay_ms ( waittime ); //延时 等待接收模块返回的指令 strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = ' '; //接收到的字符串末尾加入 结束符 macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF ); //调试口打印接收到模块的指令 if ( ( reply1 != 0 ) && ( reply2 != 0 ) ) return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 ) return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ); else return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); } //void ESP8266_AT_Test ( void ) //{ // macESP8266_RST_HIGH_LEVEL(); // // Delay_ms ( 1000 ); // // while ( ! ESP8266_Cmd ( "AT", "OK", NULL, 200 ) ) ESP8266_Rst (); //} 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; //如果接收到模块返回的OK指令,就直接返回 ESP8266_Rst(); //否则复位模块,重新发送AT测试指令 ++ count; //Main_Uart2(); } } 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; } } bool ESP8266_JoinAP ( char * pSSID, char * pPassWord ) { char cCmd [120]; sprintf ( cCmd, "AT+CWJAP="%s","%s"", pSSID, pPassWord ); return ESP8266_Cmd ( cCmd, "OK", NULL, 5000 ); } bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode ) { char cCmd [120]; sprintf ( cCmd, "AT+CWSAP="%s","%s",1,%d", pSSID, pPassWord, enunPsdMode );//名称、密码、通道号(默认为1)、加密方式 return ESP8266_Cmd ( cCmd, "OK", 0, 1000 ); } bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx ) { char cStr [20]; sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) ); return ESP8266_Cmd ( cStr, "OK", 0, 500 ); } bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id ) { char cStr [100] = { 0 }, cCmd [120]; switch ( enumE ) { case enumTCP: sprintf ( cStr, ""%s","%s",%s", "TCP", ip, ComNum ); break; case enumUDP: sprintf ( cStr, ""%s","%s",%s", "UDP", ip, ComNum ); break; default: break; } if ( id < 5 ) sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr ); else sprintf ( cCmd, "AT+CIPSTART=%s", cStr ); return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 ); } bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver ) { char cCmd1 [120], cCmd2 [120]; if ( enumMode ) //开启服务 { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum ); sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver ); return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) && ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) ); } else //关闭服务 { sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum ); return ESP8266_Cmd ( cCmd1, "OK", 0, 500 ); } } uint8_t ESP8266_Get_LinkStatus ( void ) { if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ) { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2rn" ) ) //获得ip return 2; else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3rn" ) ) //建立连接 return 3; else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4rn" ) ) //失去连接 return 4; } return 0; } uint8_t ESP8266_Get_IdLinkStatus ( void ) { uint8_t ucIdLinkStatus = 0x00; if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ) { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) ) ucIdLinkStatus |= 0x01; else ucIdLinkStatus &= ~ 0x01; if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) ) ucIdLinkStatus |= 0x02; else ucIdLinkStatus &= ~ 0x02; if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) ) ucIdLinkStatus |= 0x04; else ucIdLinkStatus &= ~ 0x04; if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) ) ucIdLinkStatus |= 0x08; else ucIdLinkStatus &= ~ 0x08; if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) ) ucIdLinkStatus |= 0x10; else ucIdLinkStatus &= ~ 0x10; } return ucIdLinkStatus; } uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength ) { char uc; char * pCh; ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 ); pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,"" ); if ( pCh ) pCh += 6; else return 0; for ( uc = 0; uc < ucArrayLength; uc ++ ) { pApIp [ uc ] = * ( pCh + uc ); if ( pApIp [ uc ] == '"' ) { pApIp [ uc ] = ' '; break; } } return 1; } bool ESP8266_UnvarnishSend ( void ) { if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) ) return false; return ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 ); } void ESP8266_ExitUnvarnishSend ( void ) { Delay_ms ( 1000 ); macESP8266_Usart ( "+++" ); Delay_ms ( 500 ); } bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId ) { char cStr [20]; bool bRet = false; if ( enumEnUnvarnishTx ) { macESP8266_Usart ( "%s", pStr ); bRet = true; } else { if ( ucId < 5 ) sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 ); else sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 ); ESP8266_Cmd ( cStr, "> ", 0, 1000 ); bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 1000 ); } return bRet; } char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx ) { char * pRecStr = 0; strEsp8266_Fram_Record .InfBit .FramLength = 0; strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0; while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag ); strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = ' '; if ( enumEnUnvarnishTx ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; else { if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) ) pRecStr = strEsp8266_Fram_Record .Data_RX_BUF; } return pRecStr; } uint8_t ESP8266_CWLIF ( char * pStaIp ) { uint8_t uc, ucLen; char * pCh, * pCh1; ESP8266_Cmd ( "AT+CWLIF", "OK", 0, 100 ); pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "," ); if ( pCh ) { pCh1 = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "AT+CWLIFrrn" ) + 11; ucLen = pCh - pCh1; } else return 0; for ( uc = 0; uc < ucLen; uc ++ ) pStaIp [ uc ] = * ( pCh1 + uc ); pStaIp [ ucLen ] = ' '; return 1; } uint8_t ESP8266_CIPAP ( char * pApIp ) { char cCmd [ 30 ]; sprintf ( cCmd, "AT+CIPAP="%s"", pApIp ); if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) ) return 1; else return 0; }
六、论文
七、资料清单



