功能:
0.本项目采用STM32F103C8T6作为单片机系统的控制MCU
1.系统采用LCD1602液晶显示花盆湿度、温度和光照状态值等参数
2.可实现远程控制,通过GSM短信远程浇水和补光灯控制。
3.湿度低于35自动浇水、光照较暗自动补光。
4.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
#include "bsp_lcd1602.h"
#include "bsp_adc.h"
#define INIT 0x00
#define WATER 0x01
#define Light 0x02
#define GETMESG 0x03
#define SOMEONE 0x09
char tab[16];
u8 readsoilHmFlag = 0; // 读取土壤湿度标志 定时器中处理
u16 lightValue = 0; //光照值
u16 soilhmValue = 0; //土壤湿度值值
u8 mesgWaterFlag = 0; // 短信浇水标志
u8 waterCnt = 0; // 短信浇水计时 定时器中处理
u8 mesgLightFlag = 0; // 短信补光标志
u8 lightCnt = 0; // 短信补光计时 定时器中处理
unsigned char stepNum = 0; // 运行步骤
unsigned int timeCount = 0; // 接收短信处理延时
char Crtl_Z[1] = {0x1a}; // 发送短信最后字节
char AT_CMGS[26] = "AT+CMGS=\"";
unsigned char rebackMesFlag; // 返回短信
unsigned char clearMesFlag = 0; // 定时清除短信
unsigned char readMesIng = 0; // 读取短信中标志
int main(void)
{
unsigned int i;
Delay_Init(); // 延时函数初始化
NVIC_Configuration(); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
UART_Init(115200); // 串口初始化
ADCx_Init();
LED_Init(); // LED端口初始化
TIM3_Int_Init(499, 7199); // 10Khz的计数频率,计数到500为50ms
LED_GSM = 0;
LCD_GPIO_Init(); // 初始化lcd引脚
LCD_Init(); // 初始化lcd屏幕
Delay_ms(20);
LCD_DispStr(0, 0, "My Designer! "); // 初始化显示
sprintf(tab, "Hm:%3d%% L:%3d%%", soilhmValue, lightValue);
LCD_DispStr(0, 1, tab); // 初始化显示
for (i = 0; i < 50; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, "AT+CMGF=1\r\n", 11); // 设置字符集
for (i = 0; i < 5; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, "AT+CSCS=\"GSM\"\r\n", 15); // 设置干什么、
for (i = 0; i < 5; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, "AT+CMGDA=\"DEL ALL\"\r\n", 20); // 删除所有短信
for (i = 0; i < 5; i++)
Delay_ms(100); // 延时有助于稳定
LED_GSM = 1; // 关闭led
while (1)
{
if (readsoilHmFlag == 1)
{
readsoilHmFlag = 0;
lightValue = 100 - 100 * ADC_ConvertedValue[0] / 4096; //计算百分比
soilhmValue = 100 * (4096 - ADC_ConvertedValue[1]) / 3373; //取土壤湿度传感器有效范围百分比
//水泵开启瞬间电流较大,影响液晶工作,需要重新配置一下液晶
LCD_WriteCommand(0x38, 1); //显示模式设置
LCD_WriteCommand(0x0c, 1); //显示开,不开游标,不闪烁
LCD_DispStr(0, 0, "My Designer! "); // 初始化显示
sprintf(tab, "Hm:%3d%% L:%3d%%", soilhmValue, lightValue);
LCD_DispStr(0, 1, tab); // 初始化显示
if (mesgWaterFlag == 0) // 短信不在控制时
{
if (soilhmValue < 30) //
{
RELAY = 1;
} // 打开继电器
else
{
RELAY = 0;
} // 关闭继电器
}
if (mesgLightFlag == 0) // 短信不在控制时
{
if (lightValue < 30)
{
LIGHT = 1;
} // 打开灯光
else
{
LIGHT = 0;
} // 关闭灯光
}
}
if (readFlag == 1) // 读取短信息标志
{
readFlag = 0; // 读取标志清零
readMesIng = 1; // 读取短信过程中
timeCount++;
if ((stepNum == 0) && (timeCount >= 4)) // 定时读取短信
{
UART_SendStr(USART1, "AT+CMGF=1\r\n", 11); // 设置字符集
timeCount = 0; // 延时设置量
stepNum++; // 进入操作过程1
}
else if ((stepNum == 1) && (timeCount >= 4)) // 定时读取短信
{
for (i = 0; i < SIZEBUF; i++)
{
timebuf[i] = '0'; // 清空timebuf
}
UART_SendStr(USART1, "AT+CMGR=1\r\n", 11);
timeCount = 0; // 延时设置量
stepNum++; // 进入操作过程1
}
else if ((stepNum == 2) && (timeCount >= 4)) // 定时读取短信
{
rebackMesFlag = INIT;
for (i = 0; i < (SIZEBUF - 5); i++)
{
if ((timebuf[i] == 'w') && (timebuf[i + 1] == 'a') && (timebuf[i + 2] == 't') && (timebuf[i + 3] == 'e') && (timebuf[i + 4] == 'r')) // 查询是否接收到water
{
mesgWaterFlag = 1; // 短信控制标志
waterCnt = 0; // 浇水计数
RELAY = 1; // 打开继电器
rebackMesFlag = WATER; // 返回短信标志
break;
}
else if ((timebuf[i] == 'l') && (timebuf[i + 1] == 'i') && (timebuf[i + 2] == 'g') && (timebuf[i + 3] == 'h') && (timebuf[i + 4] == 't')) // 查询是否接收到light
{
mesgLightFlag = 1; // 短信控制标志
lightCnt = 0; // 计数
LIGHT = 1; // 打开灯光
rebackMesFlag = Light; // 返回短信标志
break;
}
else if ((timebuf[i] == 'g') && (timebuf[i + 1] == 'e') && (timebuf[i + 2] == 't')) // 查询是否接收到get
{
rebackMesFlag = GETMESG; // 返回短信标志
break;
}
if ((timebuf[i] == '+') && (timebuf[i + 1] == '8') && (timebuf[i + 2] == '6')) // 查询短信息中的号码
{
LED_GSM = 0;
rebackMesFlag = SOMEONE; // 有人发送短信
AT_CMGS[9] = timebuf[i + 0]; // 提取号码
AT_CMGS[10] = timebuf[i + 1];
AT_CMGS[11] = timebuf[i + 2];
AT_CMGS[12] = timebuf[i + 3];
AT_CMGS[13] = timebuf[i + 4];
AT_CMGS[14] = timebuf[i + 5];
AT_CMGS[15] = timebuf[i + 6];
AT_CMGS[16] = timebuf[i + 7];
AT_CMGS[17] = timebuf[i + 8];
AT_CMGS[18] = timebuf[i + 9];
AT_CMGS[19] = timebuf[i + 10];
AT_CMGS[20] = timebuf[i + 11];
AT_CMGS[21] = timebuf[i + 12];
AT_CMGS[22] = timebuf[i + 13];
}
}
AT_CMGS[23] = '"'; // 整理字符串
AT_CMGS[24] = 0x0d;
AT_CMGS[25] = 0x0a;
if (rebackMesFlag != INIT)
{
UART_SendStr(USART1, "AT+CMGDA=\"DEL ALL\"\r\n", 20); // 删除所有短信
for (i = 0; i < 5; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, "AT+CMGF=1\r\n", 11); // 设置字符集
for (i = 0; i < 3; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, "AT+CSCS=\"GSM\"\r\n", 15); // 设置干什么、
for (i = 0; i < 3; i++)
Delay_ms(100); // 延时有助于稳定
UART_SendStr(USART1, (char *)AT_CMGS, 26); // 准备发送短信
for (i = 0; i < 2; i++)
Delay_ms(100); // 延时有助于稳定
if (rebackMesFlag == WATER)
{
UART_SendStr(USART1, "water_ok! ", 10); // 发送短信息内容
}
else if (rebackMesFlag == Light)
{
UART_SendStr(USART1, "light_ok! ", 10); // 发送短信息内容
}
else if (rebackMesFlag == GETMESG)
{
UART_SendStr(USART1, (char *)tab, 14); // 发送光强/湿度
}
else
{
UART_SendStr(USART1, "cmd_err!", 8); // 发送短信息命令错误
}
Delay_ms(100);
UART_SendStr(USART1, (char *)Crtl_Z, 1); // 发送
for (i = 0; i < 20; i++)
Delay_ms(100); // 延时有助于稳定
}
timeCount = 0; // 延时设置量
stepNum++; // 进入操作过程1
}
else if ((stepNum == 3) && (timeCount >= 4)) // 定时读取短信
{
clearMesFlag++;
if (clearMesFlag > 10)
{
clearMesFlag = 0;
UART_SendStr(USART1, "AT+CMGDA=\"DEL ALL\"\r\n", 20); // 删除所有短信
}
timeCount = 0; // 延时设置量
stepNum = 0; // 进入操作过程1
LED_GSM = 1; // 关闭指示灯
readMesIng = 0; // 读取短信过程中
}
}
}
}