0、背景
朋友企业机房空调容易跳闸,给他做了个温湿度异常报警,发短信打电话。
1、环境配置
开发环境uVersion5,c库,硬件 stm32 f105 开发板,温湿度传感器 dht22,GSM模块.
2、代码
#include "main.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
#include "timer.h"
#include "string.h"
#include "rt_heap.h"
#include "stdlib.h"
//#include "DB18B20ForStm32.h"
#include "GSM.h"
#include "AT_Cmd.h"
/**********************************************************************
实例温湿度监控发送短信实验
实验现象:D2,D3闪烁,时间间隔为300ms.
***********************************************************************/
/*#define Buf2_Max 200 //串口2缓存长度*/
/************* 本地常量声明 **************/
const char *string = "AT+CIPSTART=\"TCP\",\"xxiems.wicp.vip\",26476"; //IP登录服务器
u8 Times=0,First_Int = 0,shijian=0;
u16 Heartbeat=0, NetState =0, RegNetWork = 0, RegNetWorkTime = 0, ReSetSIM = 0, ReSetSIMCount = 0;
vu8 Timer0_start; //定时器0延时启动计数器
vu8 Uart2_Start; //串口2开始接收数据
vu8 Uart2_End; //串口2接收数据结束
vu8 Heart_beat; //发送心跳帧标志位
vu32 DHT11Time = 0; //温湿度计定时计数器
vu8 DHT11State = 0;
vu32 SMSNoticeTime = 0;//短信提醒间隔 600s
vu8 SMSNoticeClockState = 0;//短信提醒计时标记
vu8 SMSFirstNoticeFlag = 1;//开机后首次温度异常第一次提醒
char result[60];
char * phoneNumberUnicode = "0031003800390031003400370036003400000380000";//陶XX的手机号
char * phoneNumber = "18914760000";//脱敏
//char * phoneNumberUnicode = "00310033003600310036003200390035000000320000";//爱友晴天的手机号
//char * phoneNumber = "13616290000";//ken_ji_ji的手机号
char * messageHead = "673A623F60000EA662A58B66";//机房温度报警
char * messageLoginHead = "673A623F73AF588376D00007542F52A8";//机房环境监控启动
/************* 本地函数声明 **************/
void Rec_Server_Data(void);
void getTempAndHum(int flag);
void ByteToHexStr01(const unsigned char* source, char* dest, int sourceLen);
int HexStrToByteBCC(const char* source/*, unsigned char* dest*/, int sourceLen);
char * postpack(float temper, float humidity);
char * loginpack(void);
void CL_Result(void);
char *del_char(char *str, char ch);
void rep_char(char *str, char * out, char oldch, char newch);
int main(void)
{
char clientidArr[50];
int bcc_count;
char * login;
u8 res;
u8 len;
u8 t;
u16 times=0;
SystemInit(); //系统时钟初始化默认为72M,SYSCLK_FREQ_72MHz
delay_init(72); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //LED端口初始化
/*串口1初始化*/
usart_config(115200);
/*串口2初始化*/
USART2_Init_Config(115200);
Timer2_Init_Config();
NetState = 0;//网络连接状态 0 未连接 1 连接
//res = AT_Test();
//usart_printf("\r\n...AT_Test:%d...\r\n", res);
//GSM初始化
LED0=1;
res=1;
while(res)
{
LED0=0;
res= GSM_Dect();
delay_ms(1000);
delay_ms(1000);
}
/*中英文短信模式初始化*/
//GSM_InitCN();
LED0=1;
res=1;
NetState = 1;//网络连接状态 0 未连接 1 连接
Heart_beat = 0;
Heartbeat = 0;
CL_Result();
delay_ms(100);
getTempAndHum(1);
delay_ms(1000);
//res = AT_Test();
//usart_printf("\r\n...AT_Test:%d...\r\n", res);
UART1_SendString("\r\nBegin Main Loop\r\n");
while(1)
{
//网络状态心跳和发数据 AT超时次数大于5重连
if(RegNetWorkTime > 5)
{
usart_printf("\r\n网络状态AT超时次数大于5 重连 {%d}", RegNetWorkTime);
NetState = 0;
res=1;
LED0=1;//D2灯灭
while(res)
{
LED0=0;
UART1_SendString("\r\nMain Loop Reg GSM...");
RegNetWorkTime = 0;//如果模块死机这里就是死循环
res=GSM_Dect();
delay_ms(1000);
delay_ms(1000);
}
LED0=1;
Set_ATE0();
delay_ms(1000);
/*中英文短信模式初始化*/
//GSM_InitCN();
res=1;
UART1_SendString("\r\nGSM模块在主循环中初始化成功\r\n");
delay_ms(1000);
NetState = 1;//网络连接状态 0 未连接 1 连接
Heart_beat = 0;
Heartbeat = 0;
RegNetWorkTime = 0;
}
LED1=0;//D3灯亮
if(DHT11State && NetState)
{
LED0=0;//D2灯亮
UART1_SendString("\r\nDHT11State && NetState\r\n");
getTempAndHum(0);
LED0=1;
DHT11State = 0;
Heart_beat=0;
Heartbeat = 0;
}
delay_ms(1800);
LED1=1;//D3灯灭
//LED0=1;
delay_ms(1000);
//UART1_SendString("\r\nDHT11State && NetState...\r\n");
//usart_printf("\r\n...DHT11State:%d, NetState:%d...\r\n", DHT11State, NetState);
}
}
/*******温湿度*******/
void getTempAndHum(int flag){
u8 ret = 1;
char * post;
float t;//ds18b20 温度
u8 buffer[5];
float hum;
float temp;
u8 testNum = 3;
char tempStr[140];
char msg[100];
//UART1_SendString("\r\n *******dht11_read_data(buffer) == 0 里面有死循环******");//2020-09-24 注释
if (dht11_read_data(buffer) == 0)
{
hum = ((buffer[0]<<8)+buffer[1])/10.0;
temp = ((buffer[2]<<8)+buffer[3])/10.0;
}
CL_Result();
usart_printf("\r\nT:%.2f, H:%.2f\r\n", temp, hum);
sprintf(result, "%.2fC", temp);
ByteToHexStr01(result, tempStr, strlen(result));
UART1_SendString("\r\ntempStr:");
UART1_SendString(tempStr);
UART1_SendString("\r\n");
if(flag == 1){
sprintf(msg, "%s%s", messageLoginHead, tempStr);
}else{
sprintf(msg, "%s%s", messageHead, tempStr);
}
UART1_SendString("\r\nmsg:\r\n");
UART1_SendString(msg);
UART1_SendString("\r\n");
Heart_beat = 0;//心跳计数器置0 否则发送数据时冲突。
Heartbeat = 0;
if(temp <= 27){
SMSNoticeClockState = 0;
SMSFirstNoticeFlag = 1;
SMSNoticeTime = 0;
}else{
SMSNoticeClockState = 1;
}
/*测试AT指令最多3次*/
ret = AT_Test();
if(ret && testNum){
ret = AT_Test();
testNum--;
delay_ms(300);
}
testNum = 3;
usart_printf("\r\nAT_Test in getTemp:ret= %d \r\n", ret);
//delay_ms(300);
usart_printf("\r\n End Post RealData****AT_Test -> ret=%d ,RegNetWorkTime=%d", ret,RegNetWorkTime);
if(ret != 0){
RegNetWorkTime++;
}else{
RegNetWorkTime = 0;
if(flag){
UART1_SendString("\r\n发送启动短信:\r\n");
GSM_SendMessageCN((char*)phoneNumberUnicode, (char*)msg);
delay_s(5);//延时5秒
return;
}
usart_printf("\r\n ****SMSNoticeClockState=%d ,SMSFirstNoticeFlag=%d", SMSNoticeClockState, SMSFirstNoticeFlag);
if(temp > 27 && SMSFirstNoticeFlag)
{//温度大于27度或者开机时发送短信通知
usart_printf("\r\n ****temp > 27 && SMSFirstNoticeFlag=%d 发送报警短信", SMSFirstNoticeFlag);
SMSFirstNoticeFlag = 0;
GSM_SendMessageCN((char*)phoneNumberUnicode, (char*)msg);
delay_s(5);//延时5秒
if(temp > 29){//温度大于29度时拨打电话
usart_printf("\r\n ****temp > 29 && SMSFirstNoticeFlag=%d 拨打报警电话", SMSFirstNoticeFlag);
GSM_CallPhone((char *)phoneNumber);
delay_s(20);//延时20秒
GSM_EndPhone();
}
}
}
}
char * del_char(char *str, char ch)
{
unsigned char i=0,j=0;
while(str[i] != '\0')
{
if(str[i] != ch) //只有在不是空格的情况下才会移动赋值
{
str[j++] = str[i];
}
i++; //源一直移动
}
str[j] = '\0';
UART1_SendString(str);
return str;
}
void rep_char(char *str, char * out, char oldch, char newch)
{
int i=0;
for(i = 0; i < strlen(str); i++)
{
if(str[i] == oldch){
str[i] = newch;
}
}
strcpy(out, str);
}
/*双字节字符转化为16进制字符串发中文短信使用*/
void ByteToHexStr01(const unsigned char* source, char* dest, int sourceLen)
{
short i;
unsigned char highByte, lowByte;
for (i = 0; i < sourceLen; i++)
{
highByte = source[i] >> 4;
lowByte = source[i] & 0x0f;
highByte += 0x30;
dest[i * 4] = '0';
if (highByte > 0x39)
dest[i * 4 + 2] = highByte + 0x07;
else
dest[i * 4 + 2] = highByte;
lowByte += 0x30;
dest[i* 4+ 1] = '0';
if (lowByte > 0x39)
dest[i * 4 + 3] = lowByte + 0x07;
else
dest[i * 4 + 3] = lowByte;
}
//usart_printf("out = %s\n", dest);
}
/*16进制字符串BCC校验*/
int HexStrToByteBCC(const char* source, int sourceLen)
{
unsigned char * dest = (unsigned char*)malloc((sourceLen + 1) / 2);
short i;
unsigned char highByte, lowByte;
int aubChecksum = 0;
for (i = 0; i < sourceLen; i += 2)
{
highByte = toupper(source[i]);
lowByte = toupper(source[i + 1]);
if (highByte > 0x39)
highByte -= 0x37;
else
highByte -= 0x30;
if (lowByte > 0x39)
lowByte -= 0x37;
else
lowByte -= 0x30;
dest[i / 2] = (highByte << 4) | lowByte;
aubChecksum ^= dest[i / 2];
//printf("%d\n", dest[i / 2]);
}
free(dest);
dest = NULL;
//printf("aubChecksum:%d\n", aubChecksum);
return aubChecksum;
}
void CL_Result(void)
{
u16 k;
for(k = 0; k < strlen(result); k++)
{
result[k] = 0x00;
}
}
/*******************************************************************************
* 函数名 : Rec_Server_Data
* 描述 : 接收服务器数据函数
* 输入 :
* 输出 :
* 返回 :
* 注意 :
*******************************************************************************/
void Rec_Server_Data(void)
{
//UART1_SendString("\r\nRec_Server_Data");
//UART1_SendString(AT_RecvBuffer);
if(strstr(AT_RecvBuffer,"+IPD")!=NULL) //若缓存字符串中含有^SISR
{
Heartbeat=0; //清除心跳帧计数器
Heart_beat=0;
delay_ms(100);
if(strstr(AT_RecvBuffer,"onled")!=NULL)
{
//LED1_ON();
}
else if(strstr(AT_RecvBuffer,"offled")!=NULL)
{
//LED1_OFF();
}
UART1_SendString("收到新信息:\r\n");
UART1_SendString(AT_RecvBuffer);
//CLR_Buf2();
//AT_DataInit();
Heart_beat=1;//发送应答数据,告诉服务器收到数据
}
}
/*******************************************************************************
* 函数名 : TIM2_IRQHandler
* 描述 : 定时器2中断服务函数
* 输入 : 无
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void TIM2_IRQHandler(void) //TIM2中断
{
static u8 flag =1;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查TIM2更新中断发生与否
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除TIMx更新中断标志
//AT指令延时判断
if(Timer0_start)
Times++;
if(Times > shijian)
{
Timer0_start = 2;
Times = 0;
}
//UART1_SendString("中断执行\r\n");
//End AT指令延时判断
//TCP心跳 20秒钟
Heartbeat++;
if(Heartbeat > 20)//每20秒发送心跳帧
{
Heartbeat=0;
Heart_beat=1;
//UART1_SendString("\r\n *******H B T N(IRQ)******");//2020-09-24 注释
}
//End TCP心跳 20秒钟
//DHT22 10分钟测温湿度
DHT11Time++;
if(DHT11Time > 119)
{
DHT11Time = 0;
DHT11State = 1;
UART1_SendString("\r\n *******S D T N(IRQ)******");//2020-09-24 注释
}
//End DHT2 10分钟测温度
//vu32 SMSNoticeTime = 0;//短信提醒间隔 600s
//vu8 SMSNoticeClockState = 1;//短信提醒计时标记
//vu8 SMSFirstNoticeFlag = 1;//开机后首次温度异常第一次提醒
if(SMSNoticeClockState){
SMSNoticeTime++;
if(SMSNoticeTime > 599){
SMSNoticeTime = 0;
SMSFirstNoticeFlag = 1;
}
//usart_printf("\r\nSMSNoticeTime=>%d, SMSFirstNoticeFlag=>%d\r\n",SMSNoticeTime, SMSFirstNoticeFlag);
}
}
}