You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
641 lines
15 KiB
641 lines
15 KiB
#include "led.h" |
|
#include "delay.h" |
|
#include "sys.h" |
|
#include "usart.h" |
|
#include "wifi.h" |
|
#include "lcd1602.h" |
|
#include "adc.h" |
|
#include "timer.h" |
|
#include "string.h" |
|
#include "ds18b20.h" |
|
#include "Lcd_Driver.h" |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include "DS1302.h" |
|
#include "oled.h" |
|
#include "key.h" |
|
|
|
// 0 - 加热模式 (手动启动/设定时间自动启动) |
|
// 1 - 杀菌模式 |
|
// 2 - 保温模式 |
|
|
|
// 用户数据的结构体 |
|
struct UserInfo{ |
|
float water_temp; |
|
int now_tager_temp; |
|
int water_target_temp; |
|
int model; // 模块 0-加热模式 1-杀菌模式 2-保温模式 |
|
struct timing SetTimer; // 设定时间 |
|
u8 TimerFlag; |
|
u8 HotFlag; |
|
u8 Heating_state; |
|
u8 Water_pump; |
|
float water_level; |
|
u16 setLevel; |
|
}; |
|
|
|
struct RegulatoryTasks |
|
{ |
|
int hour; |
|
int min; |
|
int sec; |
|
u8 flag; |
|
float temp; |
|
}; |
|
|
|
struct UserInfo userInfo; |
|
struct timing nowTime; |
|
|
|
|
|
u8 Settime[6]={0x22,0x04,0x27,0x19,0x17,0x20}; // 设置时间 22年 03月 27日 22:34:00 |
|
|
|
int setModel = 0; |
|
int change = 0; |
|
|
|
// 函数声明 |
|
int getValue(void); |
|
int getFirstIndexes(const char str); |
|
int getLastIndexes(const char str); |
|
u8 getTimerResult(void); |
|
struct timing getTimer(void); |
|
void Sys_Init(void); |
|
void DisplayTask(void); |
|
void TaskProcessing(void); |
|
void DataProcessing(void); |
|
|
|
/** |
|
* @description: main函数 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
int main(void) |
|
{ |
|
Sys_Init(); |
|
delay_ms(1000); |
|
BEEP = 1; |
|
while(1) |
|
{ |
|
TaskProcessing(); |
|
DataProcessing(); |
|
DS1302_Readtime(); |
|
DisplayTask(); |
|
delay_ms(200); |
|
} |
|
} |
|
|
|
/** |
|
* @description: 系统初始化 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void Sys_Init(void) |
|
{ |
|
delay_init(); |
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); |
|
uart_init(115200); |
|
Model_Init(); |
|
LED_Init(); |
|
DS18B20_Init(); |
|
Adc_Init(); // 水位模块 |
|
OLED_Init(); |
|
Key4x4_GPIO_Config(); |
|
DS1302_init(Settime); |
|
//DS1302_SetTime(Settime); |
|
OLED_Clear(); |
|
} |
|
|
|
/** |
|
* @description: 显示 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void DisplayTask(void) |
|
{ |
|
char str[30]; |
|
if(setModel == 0){ |
|
sprintf(str,"%2d-%2d %2d:%2d:%2d ", nowTime.mon, nowTime.day, nowTime.hour, nowTime.min, nowTime.sec); |
|
OLED_ShowString(0, 0, str, 16); |
|
sprintf(str,"%0.2fC %dC %0.2fcm %d", userInfo.water_temp, userInfo.now_tager_temp,userInfo.water_level, userInfo.setLevel); |
|
OLED_ShowString(0, 2, str, 16); |
|
}else{ |
|
sprintf(str,"%2dC Level:%d %d", userInfo.water_target_temp,userInfo.setLevel, change); |
|
OLED_ShowString(0, 0, str, 16); |
|
sprintf(str,"%2d-%2d-%2d %2d:%2d:%2d T:%d,H:%d", userInfo.SetTimer.year,userInfo.SetTimer.mon, userInfo.SetTimer.day, userInfo.SetTimer.hour, userInfo.SetTimer.min, userInfo.SetTimer.sec, userInfo.TimerFlag, userInfo.HotFlag); |
|
OLED_ShowString(0, 2, str, 16); |
|
} |
|
}; |
|
|
|
|
|
/** |
|
* @description: 报警 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void Warning(){ |
|
BEEP = 0; |
|
delay_ms(100); |
|
BEEP = 1; |
|
} |
|
|
|
|
|
/** |
|
* @description: 加热水 目标温度 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
int HeatWaterTask(int target_temp) |
|
{ |
|
static struct RegulatoryTasks task; |
|
int result; |
|
userInfo.now_tager_temp = target_temp; |
|
// 定时加热开启后的监管任务,如5分钟内温度变化在2摄氏度内,则中断加热 |
|
if(task.flag && userInfo.Heating_state){ |
|
if(task.hour == nowTime.hour && task.min == nowTime.min && task.sec == nowTime.sec){ |
|
// 温度无变化,关闭加热 |
|
if(fabs(task.temp - userInfo.water_temp) <= 2){ |
|
HOT = 0; |
|
task.flag = 0; |
|
printf("No change in temperature, Turn off heating\r\n"); |
|
} |
|
} |
|
} |
|
// 时间生效时为自动模式,否则为手动模式 |
|
if(userInfo.TimerFlag){ |
|
result = getTimerResult(); |
|
if(result && task.flag == 0){ |
|
printf("Time to heat up!\r\n"); |
|
Warning(); |
|
HOT = 1; |
|
task.flag = 1; |
|
task.hour = nowTime.hour; |
|
task.min = nowTime.min; |
|
task.sec = nowTime.sec; |
|
task.temp = userInfo.water_temp; |
|
// 过五分钟 |
|
task.min += 1; |
|
if(task.min > 59){ |
|
task.min = task.min - 60; |
|
task.hour += 1; |
|
if(task.hour > 23) task.hour = task.hour - 24; |
|
} |
|
}else if(result == 0 && task.flag == 0){ // 时间未到默认关闭 |
|
HOT = 0; |
|
} |
|
else if(!userInfo.Heating_state) task.flag = 0; |
|
|
|
}else{ |
|
task.flag = 0; |
|
// 时间不生效时默认由HotFlag控制是否加热 |
|
HOT = userInfo.HotFlag; |
|
} |
|
|
|
// 判断水位过低、或温度达到 |
|
if(userInfo.water_level < 1 || userInfo.water_temp == target_temp) { |
|
HOT = 0; |
|
task.flag = 0; |
|
if(userInfo.water_level < 1) return 1; |
|
if(userInfo.water_temp >= target_temp) return 2; |
|
} |
|
return 0; |
|
} |
|
|
|
/** |
|
* @description: 更改水位 0-低水位 1-中水位 2-高水位 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void ChageWaterLevelTask() |
|
{ |
|
double WaterH = 2, WaterL = 1.0; |
|
if(userInfo.setLevel == 1) WaterH = 3, WaterL = 2; |
|
else if(userInfo.setLevel == 2) WaterH = 4, WaterL = 3; |
|
// 加水 |
|
if(userInfo.water_level < WaterL){ |
|
// 启动水泵 |
|
MOTOR = 1; |
|
}else if(userInfo.water_level >= WaterL && userInfo.water_level < WaterH){ |
|
// 关闭水泵 |
|
MOTOR = 0; |
|
}else if(userInfo.water_level > WaterH){ |
|
// 黄灯闪烁 |
|
LED_YELLOW = 1; |
|
delay_ms(100); |
|
LED_YELLOW = 0; |
|
MOTOR = 0; |
|
} |
|
if(userInfo.water_level < 1 && userInfo.Heating_state){ |
|
LED_RED = 1; |
|
BEEP = 0; |
|
delay_ms(100); |
|
LED_RED = 0; |
|
BEEP = 1; |
|
} |
|
} |
|
|
|
/** |
|
* @description: 加热模式 (控制水位、自动模式(定时加热水、不可手动开关热水功能)、手动模块(手动开关热水功能)) |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void HeatingModeTask() |
|
{ |
|
// 温度达到进入保温模式 |
|
if(HeatWaterTask(userInfo.water_target_temp) == 2){ |
|
printf("The temperature reached:%d", userInfo.water_target_temp); |
|
BEEP = 0; |
|
delay_ms(100); |
|
BEEP = 1; |
|
userInfo.model = 2; |
|
} |
|
} |
|
|
|
/** |
|
* @description: 杀菌模式 (加热到80度, 在降温到设定的温度) |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void SterilizationModeTask() |
|
{ |
|
static u8 flag = 0; |
|
if(flag == 0){ |
|
if(HeatWaterTask(30) == 2){ |
|
printf("The temperature reached:%d", 80); |
|
BEEP = 0; |
|
delay_ms(100); |
|
BEEP = 1; |
|
userInfo.now_tager_temp = userInfo.water_target_temp; |
|
userInfo.model = 2; |
|
flag = 1; |
|
} |
|
}else{ |
|
// 关闭加热 |
|
userInfo.TimerFlag = 0; |
|
userInfo.HotFlag = 0; |
|
// 温度达到进入保温模式 |
|
if(HeatWaterTask(userInfo.water_target_temp) == 2) { |
|
printf("The temperature reached:%d", userInfo.water_target_temp); |
|
BEEP = 0; |
|
delay_ms(100); |
|
BEEP = 1; |
|
userInfo.model = 2; |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* @description: 保温模式 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void HeatPreservationModetask() |
|
{ |
|
if(userInfo.water_temp <= (userInfo.water_target_temp - 1)) { |
|
userInfo.TimerFlag = 0; |
|
userInfo.HotFlag = 1; |
|
// 切换为加热模式 |
|
userInfo.model = 0; |
|
} |
|
} |
|
|
|
|
|
/** |
|
* @description: 改变值 |
|
* @param {int} Value |
|
* @return {*} |
|
*/ |
|
void ChangeValue(int Value){ |
|
if(setModel != 1) return; |
|
switch(change){ |
|
case 0: |
|
if(userInfo.water_target_temp < 10){ |
|
userInfo.water_target_temp = userInfo.water_target_temp * 10 + Value; |
|
} |
|
break; |
|
case 1: |
|
userInfo.setLevel = Value; |
|
if(userInfo.setLevel >= 3) userInfo.setLevel = 2; |
|
break; |
|
case 2: |
|
if(userInfo.SetTimer.year < 10){ |
|
userInfo.SetTimer.year = userInfo.SetTimer.year * 10 + Value; |
|
} |
|
break; |
|
case 3: |
|
if(userInfo.SetTimer.mon < 10){ |
|
userInfo.SetTimer.mon = userInfo.SetTimer.mon * 10 + Value; |
|
if(userInfo.SetTimer.mon > 12) userInfo.SetTimer.mon = 12; |
|
} |
|
break; |
|
case 4: |
|
if(userInfo.SetTimer.day < 10){ |
|
userInfo.SetTimer.day = userInfo.SetTimer.day* 10 + Value; |
|
if(userInfo.SetTimer.day > 31) userInfo.SetTimer.day = 31; |
|
} |
|
break; |
|
case 5: |
|
if(userInfo.SetTimer.hour < 10){ |
|
userInfo.SetTimer.hour = userInfo.SetTimer.hour * 10 + Value; |
|
if(userInfo.SetTimer.hour > 23) userInfo.SetTimer.hour = 23; |
|
} |
|
break; |
|
case 6: |
|
if(userInfo.SetTimer.min < 10){ |
|
userInfo.SetTimer.min = userInfo.SetTimer.min * 10 + Value; |
|
if(userInfo.SetTimer.min > 59) userInfo.SetTimer.min = 59; |
|
} |
|
break; |
|
case 7: |
|
if(userInfo.SetTimer.sec < 10){ |
|
userInfo.SetTimer.sec = userInfo.SetTimer.sec * 10 + Value; |
|
if(userInfo.SetTimer.sec > 59) userInfo.SetTimer.sec = 59; |
|
} |
|
break; |
|
} |
|
} |
|
|
|
/** |
|
* @description: 删除键 * |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void DeleteValue() |
|
{ |
|
if(setModel != 1) return; |
|
switch(change){ |
|
case 0: |
|
userInfo.water_target_temp /= 10; |
|
break; |
|
case 1: |
|
userInfo.setLevel /= 10; |
|
break; |
|
case 2: |
|
userInfo.SetTimer.year /= 10; |
|
break; |
|
case 3: |
|
userInfo.SetTimer.mon /= 10; |
|
break; |
|
case 4: |
|
userInfo.SetTimer.day /= 10; |
|
break; |
|
case 5: |
|
userInfo.SetTimer.hour /= 10; |
|
break; |
|
case 6: |
|
userInfo.SetTimer.min /= 10; |
|
break; |
|
case 7: |
|
userInfo.SetTimer.sec /= 10; |
|
break; |
|
} |
|
} |
|
|
|
/** |
|
* @description: 按键处理 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void keyHandling(){ |
|
int key = 16; |
|
key = Key_Scan(); |
|
switch (key) |
|
{ |
|
case 12: |
|
if(setModel == 0) setModel = 1; |
|
else setModel = 0; |
|
OLED_Clear(); |
|
break; |
|
case 13: |
|
change++; |
|
if(change >= 8) change = 0; |
|
break; |
|
case 14: |
|
if(userInfo.HotFlag == 0) userInfo.HotFlag = 1; |
|
else userInfo.HotFlag = 0; |
|
break; |
|
case 15: |
|
if(userInfo.TimerFlag == 0) userInfo.TimerFlag = 1; |
|
else userInfo.TimerFlag = 0; |
|
break; |
|
case 11: |
|
DeleteValue(); |
|
break; |
|
default: |
|
if(!setModel || key == 16) break; |
|
if(key < 10) ChangeValue(key); |
|
break; |
|
} |
|
} |
|
|
|
|
|
/** |
|
* @description: 任务处理 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void TaskProcessing() |
|
{ |
|
float temp; |
|
u16 num; |
|
keyHandling(); |
|
if(setModel == 0){ |
|
// 获取数据 |
|
// 获取水温 |
|
userInfo.water_temp = DS18B20_Get_Temp() / 10; |
|
num = Get_Adc_Average(ADC_Channel_1,10); |
|
temp = (float)num * (10 / 4096 / 3.3); // 以最高水位10cm来算 |
|
userInfo.water_level = temp; |
|
// 获取加热棒状态 |
|
userInfo.Heating_state = HOT; |
|
// 处于加热模式 定时生效 |
|
if(userInfo.model == 0) HeatingModeTask(); |
|
else if(userInfo.model == 1) SterilizationModeTask(); |
|
else if(userInfo.model == 2) HeatPreservationModetask(); |
|
ChageWaterLevelTask(); |
|
} |
|
} |
|
|
|
/** |
|
* @description: 判断时间是否到达 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
u8 getTimerResult(void) |
|
{ |
|
u8 result = 1; |
|
// 不考虑年 |
|
//if(userInfo.SetTimer.year != nowTime.year) result = 0; |
|
if(userInfo.SetTimer.mon != nowTime.mon) result = 0; |
|
else if(userInfo.SetTimer.day != nowTime.day) result = 0; |
|
else if(userInfo.SetTimer.hour != nowTime.hour) result = 0; |
|
else if(userInfo.SetTimer.min != nowTime.min) result = 0; |
|
else if(userInfo.SetTimer.sec != nowTime.sec) result = 0; |
|
return result; |
|
} |
|
|
|
/** |
|
* @description: 解析数据 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
int getValue(void) |
|
{ |
|
int target1 = 0, target2 = 0,i = 0; |
|
int result = 0; |
|
target1 = (char *)strstr((const char *)USART_RX_BUF, "(") - (char *)USART_RX_BUF; |
|
target2 = (char *)strstr((const char *)USART_RX_BUF, ")") - (char *)USART_RX_BUF; |
|
result = 0; |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* @description: 获取字符出现的第一个索引 |
|
* @param {char} str |
|
* @return {*} |
|
*/ |
|
int getFirstIndexes(const char str){ |
|
int i = 0; |
|
int length = USART_RX_STA & 0x3fff; |
|
for(i = 0; i < length; i++){ |
|
if(str == USART_RX_BUF[i]) return i; |
|
} |
|
return 0; |
|
} |
|
|
|
/** |
|
* @description: 获取字符出现的最后一个索引 |
|
* @param {char} str |
|
* @return {*} |
|
*/ |
|
int getLastIndexes(const char str){ |
|
int result = 0, i = 0; |
|
int length = USART_RX_STA & 0x3fff; |
|
for(i = 0; i < length; i++){ |
|
if(str == USART_RX_BUF[i]) result = i; |
|
} |
|
return result; |
|
} |
|
|
|
/** |
|
* @description: 解析Timer |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
struct timing getTimer() |
|
{ |
|
struct timing timer; |
|
int target1 = 0, target2 = 0,i = 0 , result = 0; |
|
|
|
target1 = (char *)strstr((const char *)USART_RX_BUF, "(") - (char *)USART_RX_BUF; |
|
target2 = getFirstIndexes('-'); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.year = result; |
|
result = 0; |
|
target1 = getFirstIndexes('-'); |
|
target2 = getLastIndexes('-'); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.mon = result; |
|
|
|
result = 0; |
|
target1 = getLastIndexes('-'); |
|
target2 = getFirstIndexes(' '); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.day = result; |
|
|
|
result = 0; |
|
target1 = getFirstIndexes(' '); |
|
target2 = getFirstIndexes(':'); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.hour = result; |
|
|
|
result = 0; |
|
target1 = getFirstIndexes(':'); |
|
target2 = getLastIndexes(':'); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.min = result; |
|
|
|
result = 0; |
|
target1 = getLastIndexes(':'); |
|
target2 = getLastIndexes(')'); |
|
for(i = target1 + 1; i < target2; i++){ |
|
result = result * 10 + (*(USART_RX_BUF + i) - 0x30); |
|
} |
|
timer.sec = result; |
|
return timer; |
|
} |
|
|
|
/** |
|
* @description: 接收数据 |
|
* @param {*} |
|
* @return {*} |
|
*/ |
|
void DataProcessing(void) |
|
{ |
|
// 接受到数据 |
|
if(USART_RX_STA & 0x8000){ |
|
// 模式切换 |
|
if(strstr((const char*)USART_RX_BUF, "model") != NULL){ |
|
userInfo.model++; |
|
if(userInfo.model >= 2) userInfo.model = 0; |
|
if(userInfo.model == 0) printf("The heating mode\r\n"); |
|
else if(userInfo.model == 1) printf("Sterilization mode\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "getModel") != NULL){ |
|
if(userInfo.model == 0) printf("The heating mode\r\n"); |
|
else if(userInfo.model == 1) printf("Sterilization mode\r\n"); |
|
else printf("Heat preservation mode\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "setTargetTemp") != NULL){ |
|
userInfo.water_target_temp = getValue(); |
|
printf("setTargetTemp OK!\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "setTimer") != NULL){ |
|
userInfo.SetTimer = getTimer(); |
|
printf("setTimer OK!\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "setLevel") != NULL){ |
|
userInfo.setLevel = getValue(); |
|
if(userInfo.setLevel >= 3) userInfo.setLevel = 2; |
|
printf("setLevel OK!\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "TimerFlag") != NULL){ |
|
if(userInfo.TimerFlag == 0) userInfo.TimerFlag = 1; |
|
else userInfo.TimerFlag = 0; |
|
if(userInfo.TimerFlag == 0) printf("Close Timer!\r\n"); |
|
else printf("Open Timer!\r\n"); |
|
} |
|
|
|
if(strstr((const char*)USART_RX_BUF, "HotFlag") != NULL){ |
|
if(userInfo.HotFlag == 0) userInfo.HotFlag = 1; |
|
else userInfo.HotFlag = 0; |
|
if(userInfo.HotFlag == 0) printf("Close Hot!\r\n"); |
|
else printf("Open Hot!\r\n"); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "getInfo") != NULL){ |
|
printf("Water_temp:%0.1f℃, target:%d℃, setTemp:%d ℃, water_level:%0.2fcm, TimerFlag:%d , HotFlag:%d\r\n", userInfo.water_temp, userInfo.now_tager_temp,userInfo.water_target_temp, userInfo.water_level, userInfo.TimerFlag, userInfo.HotFlag); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "getTime") != NULL){ |
|
printf("Time: 20%d-%d-%d %d:%d:%d\r\n", nowTime.year, nowTime.mon, nowTime.day, nowTime.hour, nowTime.min, nowTime.sec); |
|
} |
|
if(strstr((const char*)USART_RX_BUF, "getTimer") != NULL){ |
|
printf("Timer: %d-%d-%d %d:%d:%d\r\n", userInfo.SetTimer.year, userInfo.SetTimer.mon, userInfo.SetTimer.day, userInfo.SetTimer.hour, userInfo.SetTimer.min, userInfo.SetTimer.sec); |
|
} |
|
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF)); |
|
USART_RX_STA = 0x00; |
|
} |
|
} |
|
|
|
|
|
|