#include "main.h"
#include "adc.h"
#include "dma.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
#include "oled.h"
#include "stdio.h"
#include "norflash.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum {
STATE_MAIN, // 主界面
STATE_MODE_SELECT, // 模式选择
STATE_TIMER_LIST, // 定时列表
STATE_TIMER_EDIT, // 定时编辑
STATE_TIME_EDIT
} SystemState;
//RTC时间设置
typedef enum {
editTimeModeSetTime,
editTimeConfirm,
editTimeCancel
} editTimeMode;
typedef enum {
SET_NONE,
SET_YEAR,
SET_MONTH,
SET_DAY,
SET_HOUR,
SET_MINUTE
} editTimeType;
enum {
EDIT_TIME,//修改时间
EDIT_TEMP,//修改温度
EDIT_SWITCH,//开关
EDIT_CONFIRM,//确认
EDIT_CANCEL,//取消
EDIT_CNT
};
enum {
EDIT_HOUR,//修改小时
EDIT_MINUTE,//修改分钟
EDIT_TARGET_TEMP,//修改目标温度
EDIT_STATE_SWITCH,//修改开关
EDIT_NONE//无操作
};
uint8_t uart1_rx[2];
uint8_t uart2_rx[256];
uint8_t uart3_rx[256];
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define MAX_TEMP 60
#define MIN_TEMP 30
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// 系统状态
static int edit_field = 0;
uint8_t warn_flag = 0;
uint8_t total_power = 1;
SystemState current_state = STATE_MAIN; //当前界面
uint8_t selected_index = 0;
uint8_t target_temp = 50;
uint8_t current_temp = 25;
WorkMode current_mode = MODE_AUTO;//工作模式
PowerState current_power_state = POWER_OFF;//加热状态
short temperature;//温度
float temperature_f;//温度
float TDS_value = 0.0;//水质
waterLevel_t waterlevel = NOMAL_WATER;
// 定时任务
TimerTask timers[3] = {
{8, 0, 50, 0},
{12, 0, 45, 0},
{18, 0, 55, 0}
};
//编辑时间
uint8_t edit_field_state = 0;
TimerTask preTimer;
extern unsigned char esp8266_buf[1024];
extern unsigned short esp8266_cnt;
extern unsigned short esp8266_cntPre;
struct tm nowTime;
struct tm setTime;
const char *topics[] = {"/sys/ifimVLfCKMh/stm32/thing/service/property/set"};
unsigned char *dataPtr = NULL;
unsigned char *cmd = "AT+RST\r\n";
int connectServerFlag = 0;//服务器连接成功
int connectMqttFlag = 0;//订阅成功
int connectFlag = 0;//网络连接成功
uint32_t ADC_VALUE = 0;
float ADC_ConvertedValueLocal;
float kValue = 0.976;
GPIO_PinState low_water, high_water;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t * ) & ch, 1, HAL_MAX_DELAY);
return ch;
}
void save_timers_to_flash();
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief 判断年份是否是闰年
* @note 月份天数表:
* 月份 1 2 3 4 5 6 7 8 9 10 11 12
* 闰年 31 29 31 30 31 30 31 31 30 31 30 31
* 非闰年 31 28 31 30 31 30 31 31 30 31 30 31
* @param year : 年份
* @retval 0, 非闰年; 1, 是闰年;
*/
static uint8_t rtc_is_leap_year(uint16_t year)
{
/* 闰年规则: 四年闰百年不闰,四百年又闰 */
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return 1;
} else {
return 0;
}
}
__weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
if (htim == &htim5) {
KEY_Scan(); // 每10ms扫描一次按键
}
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
}
void Display_MainScreen(void)
{
OLED_NewFrame();
char buf[20];
sprintf(buf, "%02d-%02d-%02d %02d:%02d:%02d", nowTime.tm_year + 1900, nowTime.tm_mon + 1, nowTime.tm_mday,
nowTime.tm_hour, nowTime.tm_min, nowTime.tm_sec);
OLED_PrintString(0, 0, buf, &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "当前温度:%d.%d℃", temperature / 10, temperature % 10);
OLED_PrintString(0, 12, buf, &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "目标温度:%2d℃", target_temp);
OLED_PrintString(0, 24, buf, &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "水位:");
OLED_PrintString(0, 36, buf, &font12x12, OLED_COLOR_NORMAL);
if(waterlevel == NOMAL_WATER){
OLED_PrintString(30, 36, "正常", &font12x12, OLED_COLOR_NORMAL);
}else if(waterlevel == LOW_WATER){
OLED_PrintString(30, 36, "过低", &font12x12, OLED_COLOR_NORMAL);
}else if(waterlevel == HIGH_WATER){
OLED_PrintString(30, 36, "过高", &font12x12, OLED_COLOR_NORMAL);
}
/* 自动模式 */
sprintf(buf, "水质:%.2f", TDS_value);
OLED_PrintString(60, 36, buf, &font12x12, OLED_COLOR_NORMAL);
// 显示当前模式
const char *mode_str[] = {"自动", "节能", "手动", "定时"};
sprintf(buf, "模式:%s", mode_str[current_mode]);
OLED_PrintString(0, 48, buf, &font12x12, OLED_COLOR_NORMAL);
if (current_power_state == POWER_ON) {
OLED_PrintString(72, 48, "加热", &font12x12, OLED_COLOR_NORMAL);
} else if (current_power_state == POWER_OFF) {
OLED_PrintString(72, 48, "待机", &font12x12, OLED_COLOR_NORMAL);
}
OLED_ShowFrame();
}
void Display_ModeSelect(void)
{
static uint8_t selected_index_state = 0;
OLED_NewFrame();
OLED_PrintString(0, 0, "选择工作模式", &font12x12, OLED_COLOR_NORMAL);
const char *modes[] = {"自动模式", "节能模式", "手动模式", "定时模式", "时间设置"};
if (selected_index == 4) {
for (int i = 0; i < 4; i++) {
if (i == selected_index - 1) {
OLED_PrintString(0, 12 + i * 12, ">", &font12x12, OLED_COLOR_NORMAL);
//闪烁效果
if (selected_index_state == 0) {
selected_index_state = 1;
OLED_PrintString(12, 12 + i * 12, modes[i + 1], &font12x12, OLED_COLOR_REVERSED);
} else {
selected_index_state = 0;
OLED_PrintString(12, 12 + i * 12, modes[i + 1], &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(12, 12 + i * 12, modes[i + 1], &font12x12, OLED_COLOR_NORMAL);
}
if (i == current_mode - 1) {
OLED_PrintString(100, 12 + i * 12, "▲", &font12x12, OLED_COLOR_NORMAL);
}
}
} else {
for (int i = 0; i < 4; i++) {
if (i == selected_index) {
OLED_PrintString(0, 12 + i * 12, ">", &font12x12, OLED_COLOR_NORMAL);
//闪烁效果
if (selected_index_state == 0) {
selected_index_state = 1;
OLED_PrintString(12, 12 + i * 12, modes[i], &fonty12x12, OLED_COLOR_NORMAL);
} else {
selected_index_state = 0;
OLED_PrintString(12, 12 + i * 12, modes[i], &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(12, 12 + i * 12, modes[i], &font12x12, OLED_COLOR_NORMAL);
}
if (i == current_mode) {
OLED_PrintString(100, 12 + i * 12, "▲", &font12x12, OLED_COLOR_NORMAL);
}
}
}
OLED_ShowFrame();
}
//定时任务列表
void Display_TimerList(void)
{
static uint8_t blink_state = 0;
OLED_NewFrame();
char buf[20];
OLED_PrintString(0, 0, "定时任务列表", &font12x12, OLED_COLOR_NORMAL);
for (uint8_t i = 0; i < 3; i++) {
sprintf(buf, "定时%d:%02d:%02d %02d℃", i + 1, timers[i].hour, timers[i].minute, timers[i].target_temp);
int len = strlen(buf);
if (timers[i].state == 1) {
sprintf(&buf[len], " %s", "开");
} else {
sprintf(&buf[len], " %s", "关");
}
if (i == selected_index) {
OLED_PrintString(0, 12 + i * 12, ">", &font12x12, OLED_COLOR_NORMAL);
//闪烁效果
if (blink_state) {
blink_state = 0;
OLED_PrintString(8, 12 + i * 12, buf, &font12x12, OLED_COLOR_NORMAL);
} else {
blink_state = 1;
OLED_PrintString(8, 12 + i * 12, buf, &font12x12, OLED_COLOR_REVERSED);
}
} else {
OLED_PrintString(8, 12 + i * 12, buf, &font12x12, OLED_COLOR_NORMAL);
}
}
OLED_ShowFrame();
}
void Display_TimerEdit(uint8_t timer_index)
{
static uint8_t blink_state = 0;
OLED_NewFrame();
char buf[20];
sprintf(buf, "编辑定时%d", timer_index + 1);
OLED_PrintString(0, 0, buf, &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "开启时间: ");
OLED_PrintString(0, 12, buf, &font12x12, OLED_COLOR_NORMAL);
if (edit_field == EDIT_TIME) {
if (edit_field_state == EDIT_NONE) {
sprintf(buf, "%02d:%02d", timers[timer_index].hour, timers[timer_index].minute);
OLED_PrintString(60, 12, buf, &font12x12, OLED_COLOR_NORMAL);
} else if (edit_field_state == EDIT_HOUR) {
sprintf(buf, "%02d", timers[timer_index].hour);
if (blink_state == 0) {
blink_state = 1;
OLED_PrintString(60, 12, buf, &font12x12, OLED_COLOR_REVERSED);
} else if (blink_state == 1) {
blink_state = 0;
OLED_PrintString(60, 12, buf, &font12x12, OLED_COLOR_NORMAL);
}
OLED_PrintString(72, 12, ":", &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "%02d", timers[timer_index].minute);
OLED_PrintString(78, 12, buf, &font12x12, OLED_COLOR_NORMAL);
} else if (edit_field_state == EDIT_MINUTE) {
sprintf(buf, "%02d", timers[timer_index].hour);
OLED_PrintString(60, 12, buf, &font12x12, OLED_COLOR_NORMAL);
OLED_PrintString(72, 12, ":", &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "%02d", timers[timer_index].minute);
if (blink_state == 0) {
blink_state = 1;
OLED_PrintString(78, 12, buf, &font12x12, OLED_COLOR_REVERSED);
} else if (blink_state == 1) {
blink_state = 0;
OLED_PrintString(78, 12, buf, &font12x12, OLED_COLOR_NORMAL);
}
}
} else {
sprintf(buf, "%02d:%02d", timers[timer_index].hour, timers[timer_index].minute);
OLED_PrintString(60, 12, buf, &font12x12, OLED_COLOR_NORMAL);
}
sprintf(buf, "目标温度: ");
OLED_PrintString(0, 24, buf, &font12x12, OLED_COLOR_NORMAL);
if (edit_field == EDIT_TEMP) {
if (edit_field_state == EDIT_TARGET_TEMP) {
sprintf(buf, "%02d", timers[selected_index].target_temp);
if (blink_state == 0) {
blink_state = 1;
OLED_PrintString(60, 24, buf, &font12x12, OLED_COLOR_REVERSED);
} else if (blink_state == 1) {
blink_state = 0;
OLED_PrintString(60, 24, buf, &font12x12, OLED_COLOR_NORMAL);
}
OLED_PrintString(72, 24, "℃", &font12x12, OLED_COLOR_NORMAL);
} else {
sprintf(buf,
"目标温度: %02d℃", timers[timer_index].target_temp);
OLED_PrintString(0, 24, buf, &font12x12, OLED_COLOR_NORMAL);
}
} else {
sprintf(buf,
"目标温度: %02d℃", timers[timer_index].target_temp);
OLED_PrintString(0, 24, buf, &font12x12, OLED_COLOR_NORMAL);
}
// 显示操作提示
if (edit_field == EDIT_TIME) {
OLED_PrintString(100, 12, "▲", &font12x12, OLED_COLOR_NORMAL);
} else if (edit_field == EDIT_TEMP) {
OLED_PrintString(100, 24, "▲", &font12x12, OLED_COLOR_NORMAL);
}
if (timers[timer_index].state == 1) {
sprintf(buf, "[开]");
} else {
sprintf(buf, "[关]");
}
if (edit_field == EDIT_SWITCH) {
if (blink_state) {
blink_state = 0;
OLED_PrintString(50, 36, buf, &font12x12, OLED_COLOR_REVERSED);
} else {
blink_state = 1;
OLED_PrintString(50, 36, buf, &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(50, 36, buf, &font12x12, OLED_COLOR_NORMAL);
}
// 显示确定/取消选项
if (edit_field == EDIT_CONFIRM) {
if (blink_state) {
blink_state = 0;
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_REVERSED);
} else {
blink_state = 1;
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_NORMAL);
}
if (edit_field == EDIT_CANCEL) {
if (blink_state) {
blink_state = 0;
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_REVERSED);
} else {
blink_state = 1;
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_NORMAL);
}
OLED_ShowFrame();
}
void Display_TimeEdit()
{
static uint8_t blink_state = 0;
OLED_NewFrame();
char buf[20];
OLED_PrintString(36, 0, "设置时间", &font12x12, OLED_COLOR_NORMAL);
sprintf(buf, "当前时间: ");
OLED_PrintString(0, 12, buf, &font12x12, OLED_COLOR_NORMAL);
// edit_field = editTimeModeSetTime;
// edit_field_state = SET_MINUTE;
sprintf(buf, "%02d-%02d-%02d %02d:%02d", setTime.tm_year + 1900, setTime.tm_mon + 1, setTime.tm_mday,
setTime.tm_hour, setTime.tm_min);
OLED_PrintString(8, 24, buf, &font12x12, OLED_COLOR_NORMAL);
if (edit_field == editTimeModeSetTime) {
if (blink_state) {
blink_state = 0;
if (edit_field_state == SET_YEAR) {
OLED_DrawLine(8, 36, 31, 36, OLED_COLOR_NORMAL);
} else if (edit_field_state == SET_MONTH) {
OLED_DrawLine(38, 36, 47, 36, OLED_COLOR_NORMAL);
} else if (edit_field_state == SET_DAY) {
OLED_DrawLine(56, 36, 66, 36, OLED_COLOR_NORMAL);
} else if (edit_field_state == SET_HOUR) {
OLED_DrawLine(74, 36, 84, 36, OLED_COLOR_NORMAL);
} else if (edit_field_state == SET_MINUTE) {
OLED_DrawLine(92, 36, 102, 36, OLED_COLOR_NORMAL);
}
} else {
blink_state = 1;
}
}
// 显示确定/取消选项
if (edit_field == editTimeConfirm) {
if (blink_state) {
blink_state = 0;
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_REVERSED);
} else {
blink_state = 1;
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(20, 48, "[确定]", &font12x12, OLED_COLOR_NORMAL);
}
if (edit_field == editTimeCancel) {
if (blink_state) {
blink_state = 0;
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_REVERSED);
} else {
blink_state = 1;
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_NORMAL);
}
} else {
OLED_PrintString(70, 48, "[取消]", &font12x12, OLED_COLOR_NORMAL);
}
OLED_ShowFrame();
}
void System_ProcessInput()
{
// 检查各个按键事件
KeyEvent up_event = KEY_GetEvent(KEY_ID_UP);
KeyEvent down_event = KEY_GetEvent(KEY_ID_DOWN);
KeyEvent enter_event = KEY_GetEvent(KEY_ID_ENTER);
switch (current_state) {
case STATE_MAIN:
if (up_event == KEY_EVENT_CLICK) {
if (target_temp < MAX_TEMP) {
target_temp++;
}
} else if (down_event == KEY_EVENT_CLICK) {
if (target_temp > MIN_TEMP) {
target_temp--;
}
} else if (enter_event == KEY_EVENT_DOUBLE_CLICK) {
current_state = STATE_MODE_SELECT;
selected_index = current_mode;
}
break;
case STATE_MODE_SELECT:
if (up_event == KEY_EVENT_CLICK) {
if (selected_index == 0) {
selected_index = 4;
} else {
selected_index--;
}
} else if (down_event == KEY_EVENT_CLICK) {
if (selected_index == 4) {
selected_index = 0;
} else {
selected_index++;
}
} else if (enter_event == KEY_EVENT_CLICK) {
current_state = STATE_MAIN;
} else if (enter_event == KEY_EVENT_DOUBLE_CLICK) {
if (selected_index == MODE_TIMER) {
current_state = STATE_TIMER_LIST;
current_mode = selected_index;
current_power_state = POWER_OFF;
selected_index = 0;
} else if (selected_index == STATE_TIME_EDIT) {
current_state = STATE_TIME_EDIT;
edit_field = EDIT_TIME;
edit_field_state = SET_NONE;
setTime = nowTime;
} else {
current_mode = selected_index;
}
}
break;
case STATE_TIMER_LIST:
if (up_event == KEY_EVENT_CLICK) {
if (selected_index == 0) {
selected_index = 2;
} else {
selected_index--;
}
} else if (down_event == KEY_EVENT_CLICK) {
if (selected_index == 2) {
selected_index = 0;
} else {
selected_index++;
}
} else if (enter_event == KEY_EVENT_CLICK) {
current_state = STATE_MODE_SELECT;
selected_index = current_mode;
} else if (enter_event == KEY_EVENT_DOUBLE_CLICK) {
current_state = STATE_TIMER_EDIT;
edit_field = EDIT_TIME;
edit_field_state = EDIT_NONE;
preTimer = timers[selected_index];
}
break;
case STATE_TIMER_EDIT:
if (up_event == KEY_EVENT_CLICK) {
if (edit_field == EDIT_TIME) {
if (edit_field_state != EDIT_HOUR && edit_field_state != EDIT_MINUTE) {
edit_field = EDIT_CANCEL;
} else if (edit_field_state == EDIT_HOUR) {
timers[selected_index].hour++;
if (timers[selected_index].hour > 23) {
timers[selected_index].hour = 0;
}
} else if (edit_field_state == EDIT_MINUTE) {
timers[selected_index].minute += 5;
if (timers[selected_index].minute > 59) {
timers[selected_index].minute = 0;
}
}
} else if (edit_field == EDIT_TEMP) {
if (edit_field_state != EDIT_TARGET_TEMP) {
edit_field = EDIT_TIME;
} else if (edit_field_state == EDIT_TARGET_TEMP) {
timers[selected_index].target_temp += 5;
if (timers[selected_index].target_temp > MAX_TEMP) {
timers[selected_index].target_temp = MIN_TEMP;
}
}
} else if (edit_field == EDIT_SWITCH) {
edit_field = EDIT_TEMP;
} else if (edit_field == EDIT_CONFIRM) {
edit_field = EDIT_SWITCH;
} else if (edit_field == EDIT_CANCEL) {
edit_field = EDIT_CONFIRM;
}
} else if (down_event == KEY_EVENT_CLICK) {
if (edit_field == EDIT_TIME) {
if (edit_field_state != EDIT_HOUR && edit_field_state != EDIT_MINUTE) {
edit_field = EDIT_TEMP;
} else if (edit_field_state == EDIT_HOUR) {
timers[selected_index].hour--;
if (timers[selected_index].hour < 0) {
timers[selected_index].hour = 23;
}
} else if (edit_field_state == EDIT_MINUTE) {
timers[selected_index].minute -= 5;
if (timers[selected_index].minute < 0) {
timers[selected_index].minute = 55;
}
}
} else if (edit_field == EDIT_TEMP) {
if (edit_field_state != EDIT_TARGET_TEMP) {
edit_field = EDIT_SWITCH;
} else if (edit_field_state == EDIT_TARGET_TEMP) {
timers[selected_index].target_temp -= 5;
if (timers[selected_index].target_temp < MIN_TEMP) {
timers[selected_index].target_temp = MAX_TEMP;
}
}
} else if (edit_field == EDIT_SWITCH) {
edit_field = EDIT_CONFIRM;
} else if (edit_field == EDIT_CONFIRM) {
edit_field = EDIT_CANCEL;
} else if (edit_field == EDIT_CANCEL) {
edit_field = EDIT_TIME;
edit_field_state = EDIT_NONE;
}
} else if (enter_event == KEY_EVENT_CLICK) {
current_state = STATE_MAIN;
timers[selected_index] = preTimer;
edit_field = EDIT_TIME;
edit_field_state = EDIT_NONE;
} else if (enter_event == KEY_EVENT_DOUBLE_CLICK) {
if (edit_field == EDIT_TIME) {
if (edit_field_state == EDIT_NONE) {
edit_field_state = EDIT_HOUR;
} else if (edit_field_state == EDIT_HOUR) {
edit_field_state = EDIT_MINUTE;
} else if (edit_field_state == EDIT_MINUTE) {
edit_field_state = EDIT_NONE;
}
} else if (edit_field == EDIT_TEMP) {
if (edit_field_state == EDIT_NONE) {
edit_field_state = EDIT_TARGET_TEMP;
} else if (edit_field_state == EDIT_TARGET_TEMP) {
edit_field_state = EDIT_NONE;
}
} else if (edit_field == EDIT_SWITCH) {
timers[selected_index].state = !timers[selected_index].state;
} else if (edit_field == EDIT_CONFIRM) {
current_state = STATE_TIMER_LIST;
//将状态保存至flash
save_timers_to_flash();
} else if (edit_field == EDIT_CANCEL) {
//不保存
current_state = STATE_TIMER_LIST;
timers[selected_index] = preTimer;
edit_field = EDIT_TIME;
edit_field_state = EDIT_NONE;
}
}
break;
case STATE_TIME_EDIT:
if (up_event == KEY_EVENT_CLICK) {
if (edit_field == editTimeModeSetTime) {
if (edit_field_state == SET_NONE) {
edit_field = editTimeCancel;
} else if (edit_field_state == SET_YEAR) {
setTime.tm_year++;
if (setTime.tm_year > 2099) {
setTime.tm_year = 0;
}
} else if (edit_field_state == SET_MONTH) {
setTime.tm_mon++;
if (setTime.tm_mon > 11) {
setTime.tm_mon = 0;
}
} else if (edit_field_state == SET_DAY) {
setTime.tm_mday++;
//2月
if (setTime.tm_mon == 1) {
if (rtc_is_leap_year(setTime.tm_year + 1900)) {
if (setTime.tm_mday > 29) {
setTime.tm_mday = 1;
}
} else {
if (setTime.tm_mday > 28) {
setTime.tm_mday = 1;
}
}
//大月
} else if (setTime.tm_mon == 0 || setTime.tm_mon == 2 || setTime.tm_mon == 4 ||
setTime.tm_mon == 6 || setTime.tm_mon == 7 || setTime.tm_mon == 9 ||
setTime.tm_mon == 11) {
if (setTime.tm_mday > 31) {
setTime.tm_mday = 1;
}
//小月
} else {
if (setTime.tm_mon > 30) {
setTime.tm_mday = 1;
}
}
} else if (edit_field_state == SET_HOUR) {
setTime.tm_hour++;
if (setTime.tm_hour > 23) {
setTime.tm_hour = 0;
}
} else if (edit_field_state == SET_MINUTE) {
setTime.tm_min++;
if (setTime.tm_min > 59) {
setTime.tm_min = 0;
}
}
} else if (edit_field == editTimeConfirm) {
edit_field = editTimeModeSetTime;
edit_field_state = SET_NONE;
} else if (edit_field == editTimeCancel) {
edit_field = editTimeConfirm;
}
} else if (down_event == KEY_EVENT_CLICK) {
if (edit_field == editTimeModeSetTime) {
if (edit_field_state == SET_NONE) {
edit_field = editTimeConfirm;
} else if (edit_field_state == SET_YEAR) {
setTime.tm_year--;
if (setTime.tm_year < 0) {
setTime.tm_year = 2099;
}
} else if (edit_field_state == SET_MONTH) {
setTime.tm_mon--;
if (setTime.tm_mon < 0) {
setTime.tm_mon = 11;
}
} else if (edit_field_state == SET_DAY) {
setTime.tm_mday--;
//2月
if (setTime.tm_mon == 1) {
if (rtc_is_leap_year(setTime.tm_year + 1900)) {
if (setTime.tm_mday < 1) {
setTime.tm_mday = 29;
}
} else {
if (setTime.tm_mday < 1) {
setTime.tm_mday = 28;
}
}
//大月
} else if (setTime.tm_mon == 0 || setTime.tm_mon == 2 || setTime.tm_mon == 4 ||
setTime.tm_mon == 6 || setTime.tm_mon == 7 || setTime.tm_mon == 9 ||
setTime.tm_mon == 11) {
if (setTime.tm_mday < 1) {
setTime.tm_mday = 31;
}
//小月
} else {
if (setTime.tm_mon < 1) {
setTime.tm_mday = 30;
}
}
} else if (edit_field_state == SET_HOUR) {
setTime.tm_hour--;
if (setTime.tm_hour < 0) {
setTime.tm_hour = 23;
}
} else if (edit_field_state == SET_MINUTE) {
setTime.tm_min--;
if (setTime.tm_min < 0) {
setTime.tm_min = 59;
}
}
} else if (edit_field == editTimeConfirm) {
edit_field = editTimeCancel;
} else if (edit_field == editTimeCancel) {
edit_field = editTimeModeSetTime;
edit_field_state = SET_NONE;
}
} else if (enter_event == KEY_EVENT_CLICK) {
if (edit_field == editTimeModeSetTime) {
if (edit_field_state == SET_NONE) {
current_state == STATE_MAIN;
} else if (edit_field_state == SET_YEAR) {
edit_field_state = SET_NONE;
} else if (edit_field_state == SET_MONTH) {
edit_field_state = SET_NONE;
} else if (edit_field_state == SET_DAY) {
edit_field_state = SET_NONE;
} else if (edit_field_state == SET_HOUR) {
edit_field_state = SET_NONE;
} else if (edit_field_state == SET_MINUTE) {
edit_field_state = SET_NONE;
}
} else if (edit_field == editTimeConfirm) {
current_state == STATE_MAIN;
} else if (edit_field == editTimeCancel) {
current_state == STATE_MAIN;
}
} else if (enter_event == KEY_EVENT_DOUBLE_CLICK) {
if (edit_field == editTimeModeSetTime) {
if (edit_field_state == SET_NONE) {
edit_field_state = SET_YEAR;
} else if (edit_field_state == SET_YEAR) {
edit_field_state = SET_MONTH;
} else if (edit_field_state == SET_MONTH) {
edit_field_state = SET_DAY;
} else if (edit_field_state == SET_DAY) {
edit_field_state = SET_HOUR;
} else if (edit_field_state == SET_HOUR) {
edit_field_state = SET_MINUTE;
} else if (edit_field_state == SET_MINUTE) {
edit_field_state = SET_NONE;
}
} else if (edit_field == editTimeConfirm) {
//设置时间
KK_RTC_SetTime(&setTime);
current_state = STATE_MAIN;
} else if (edit_field == editTimeCancel) {
current_state = STATE_MAIN;
}
}
}
}
void System_Display()
{
switch (current_state) {
case STATE_MAIN:
Display_MainScreen();
break;
case STATE_MODE_SELECT:
Display_ModeSelect();
break;
case STATE_TIMER_LIST:
Display_TimerList();
break;
case STATE_TIMER_EDIT:
Display_TimerEdit(selected_index);
break;
case STATE_TIME_EDIT:
Display_TimeEdit();
break;
default:
break;
}
}
// 不定长数据接收完成回调函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
static uint8_t preMode = 0;
if (huart->Instance == USART2) {
if (esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口被刷爆
memcpy(&esp8266_buf[esp8266_cnt], uart2_rx, Size);
// HAL_UART_Transmit_IT(&huart1, (uint8_t *) uart2_rx, Size);
esp8266_cnt += Size;
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uart2_rx, sizeof(uart2_rx));
__HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT);
} else if (huart->Instance == USART3) {
HAL_UART_Transmit_IT(&huart1, (uint8_t *) uart3_rx, Size);
if (uart3_rx[0] == 'o' && uart3_rx[1] == 'p' && uart3_rx[2] == 'e' && uart3_rx[3] == 'n') {//开启加热
total_power = 1;
} else if (uart3_rx[0] == 'c' && uart3_rx[1] == 'l' && uart3_rx[2] == 'o' && uart3_rx[3] == 's' &&
uart3_rx[4] == 'e') {//关闭加热
total_power = 0;
}
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, uart3_rx, sizeof(uart3_rx));
__HAL_DMA_DISABLE_IT(huart3.hdmarx, DMA_IT_HT);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) {
}
}
void delay_us(uint32_t us)
{
__HAL_TIM_SET_COUNTER(&htim1, 0); // 重置计数器
while (__HAL_TIM_GET_COUNTER(&htim1) < us); // 等待计数达到目标值
}
void TDS_Value_Conversion()
{
// 获取ADC值
ADC_VALUE = HAL_ADC_GetValue(&hadc1);
ADC_ConvertedValueLocal =
((float) ADC_VALUE / 4096 * 3.3) * (1.0 + 0.02 * (temperature_f / 10 - 25.0)); //AD转换
TDS_value = (66.71 * ADC_ConvertedValueLocal * ADC_ConvertedValueLocal * ADC_ConvertedValueLocal -
127.93 * ADC_ConvertedValueLocal * ADC_ConvertedValueLocal + 428.7 * ADC_ConvertedValueLocal) * kValue;
if ((TDS_value <= 0)) { TDS_value = 0; }
if ((TDS_value > 1400)) { TDS_value = 1400; }
}
//获取水位
void ObtainTheWaterLevel()
{
low_water = HAL_GPIO_ReadPin(LOW_WATER_GPIO_Port, LOW_WATER_Pin);
high_water = HAL_GPIO_ReadPin(HIGH_WATER_GPIO_Port, HIGH_WATER_Pin);
if (low_water == 0 && high_water == 1) {
waterlevel = NOMAL_WATER;
} else if (low_water == 1 && high_water == 1) {
waterlevel = LOW_WATER;
} else if (low_water == 0 && high_water == 0) {
waterlevel = HIGH_WATER;
}
}
/* 自动模式 */
void Auto_Mode_Handler(void)
{
if(total_power == 1){
// 简单逻辑:根据时间自动调整目标温度
if (nowTime.tm_hour >= 6 && nowTime.tm_hour <= 9) { // 早高峰
if (temperature_f < target_temp - 5 ) {
current_power_state = POWER_ON;
} else if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
}
} else if (nowTime.tm_hour >= 18 && nowTime.tm_hour <= 22) { // 晚高峰
if (temperature_f < target_temp - 5 ) {
current_power_state = POWER_ON;
} else if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
}
} else { // 其他时间
if (temperature_f < target_temp - 10) {
current_power_state = POWER_ON;
} else if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
}
}
}else{
current_power_state = POWER_OFF;
}
}
/* 经济模式 */
void Eco_Mode_Handler()
{
if(total_power == 1){
// 谷电时段:22:00-6:00
if (nowTime.tm_hour >= 22 || nowTime.tm_hour < 6) {
if (temperature_f < target_temp - 5 ) {
current_power_state = POWER_ON;
} else if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
}
} else {
if (temperature_f < target_temp - 15 ) {
current_power_state = POWER_ON;
} else if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
}
}
}else{
current_power_state = POWER_OFF;
}
}
/* 定时模式 */
void Timer_Mode_Handler()
{
static uint32_t flag = 1;
if(total_power == 1){
// 检查是否到达定时时间
for (int i = 0; i < 3; i++) {
if (nowTime.tm_hour == timers[i].hour && nowTime.tm_min == timers[i].minute && timers[i].state) {
target_temp = timers[i].target_temp;
flag =0;
//开始加热
}
}
//加热一次就不加热了
if (temperature_f >= target_temp && flag == 0) {
current_power_state = POWER_OFF;
flag = 1;
}
if (temperature_f < target_temp && flag == 0) {
current_power_state = POWER_ON;
}
}else{
current_power_state = POWER_OFF;
}
}
/* 手动模式 */
void Manual_Mode_Handler(void)
{
if(total_power == 1){
if (temperature_f >= target_temp) {
current_power_state = POWER_OFF;
} else {
current_power_state = POWER_ON;
}
}else{
current_power_state = POWER_OFF;
}
}
//控制加热
void ControlHeating()
{
switch (current_mode) {
case MODE_AUTO://小于目标值10度 则加热 大于等于目标值则关闭
Auto_Mode_Handler();
break;
case MODE_ECO:
Eco_Mode_Handler();
break;
case MODE_MANUAL:
Manual_Mode_Handler();
break;
case MODE_TIMER:
Timer_Mode_Handler();
break;
}
if(warn_flag){
current_power_state = POWER_OFF;
}
if (current_power_state == POWER_ON) {
HAL_GPIO_WritePin(HEATER_GPIO_Port, HEATER_Pin, GPIO_PIN_RESET);
} else if (current_power_state == POWER_OFF) {
HAL_GPIO_WritePin(HEATER_GPIO_Port, HEATER_Pin, GPIO_PIN_SET);
}
}
void save_timers_to_flash()
{
norflash_write((uint8_t *) timers, 0, sizeof(TimerTask) * 3);
}
void get_timers_from_flash()
{
norflash_read((uint8_t *) timers, 0, sizeof(TimerTask) * 3);
}
void led_on(uint8_t on_off){
if(on_off){
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
}else{
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
}
}
void Beep_on(uint8_t on_off){
if(on_off){
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
}else{
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
}
void ControlBeep(){
// //水质
// if(TDS_value > 1500){
// led_on(1);
// Beep_on(1);
// }else{
// led_on(0);
// Beep_on(0);
// }
//水位
if(waterlevel == HIGH_WATER || waterlevel == LOW_WATER || TDS_value > 60 || temperature_f > 65){
led_on(1);
Beep_on(1);
warn_flag = 1;
}else{
led_on(0);
Beep_on(0);
warn_flag = 0;
}
// //高温报
// if(temperature_f > 65){
// led_on(1);
// Beep_on(1);
// }else{
// led_on(0);
// Beep_on(0);
// }
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t flashsize;
uint16_t id = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_RTC_Init();
MX_I2C2_Init();
MX_TIM5_Init();
MX_TIM1_Init();
MX_ADC1_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
//打开串口中断
HAL_UART_Receive_IT(&huart1, uart1_rx, 2);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uart2_rx, sizeof(uart2_rx));
__HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT);
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, uart3_rx, sizeof(uart3_rx));
__HAL_DMA_DISABLE_IT(huart3.hdmarx, DMA_IT_HT);
HAL_Delay(20); // 单片机启动比OLED上电快,需要延迟等待一下
OLED_Init();
norflash_init(); /* 初始化NORFLASH */
HAL_TIM_Base_Start_IT(&htim5);//用于按键检测
HAL_TIM_Base_Start_IT(&htim1);//用于us定时
while (ds18b20_init()) /* DS18B20初始化 */
{
printf("DS18B20 INIT ERROR\r\n");
HAL_Delay(500);
}
id = norflash_read_id(); /* 读取FLASH ID */
while ((id == 0) || (id == 0XFFFF)) /* 检测不到FLASH芯片 */
{
printf("FLASH Check Failed!\r\n");
HAL_Delay(300);
}
printf("SPI FLASH Ready!\r\n");
flashsize = 16 * 1024 * 1024; /* FLASH 大小为16M字节 */
printf("hardware init finish\r\n");
// 启动连续ADC转换
HAL_ADC_Start(&hadc1);
// 等待ADC稳定
HAL_Delay(500);
get_timers_from_flash();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//获取温度
temperature = ds18b20_get_temperature();
temperature_f = temperature / 10 + (temperature % 10 / 10.0);
//获取水质
TDS_Value_Conversion();
//获取当前时间
nowTime = *KK_RTC_GetTime();
//获取水位
ObtainTheWaterLevel();
//控制蜂鸣器
ControlBeep();
//控制加热
ControlHeating();
//按键状态及输入处理
System_ProcessInput();
//显示
System_Display();
// printf("temp = %f, power = %d, target_temp = %d\r\n", temperature_f, current_power_state, target_temp);
HAL_Delay(300);//500ms刷新一次
if (connectFlag == 0) {
Usart_SendString(USART2, (unsigned char *) cmd, strlen((const char *) cmd));
ESP8266_Init(); //ESP8266初始化
}
if (connectFlag == 1) {
static int cnt = 0;
if (cnt == 2) {
ESP8266_SendData();
printf("Heart\r\n");
}
cnt++;
if (cnt > 2) {
cnt = 0;
}
ESP8266_GetIPD(10);
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_ADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1) {
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
根据这串代码画有YN的流程图,这是基于stm32智能热水器控制系统