Files
JYF_STC15W4K_wireless_charge/Src/main.c
2025-03-21 03:34:06 +08:00

326 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// System
#include <STC15.H>
#include <stdint.h>
#include <stdio.h>
// Config
#include "config.h"
// Driver
#include "iic.h"
#include "timer.h"
#include "uart.h"
// Lib
#include "delay.h"
#include "ina226.h"
#include "keyscan.h"
// #include "dht10.h"
#include "oled12864_drv.h"
// 系统状态枚举
typedef enum
{
MODE_AUTO_OFF, // 自动断电模式
MODE_MANUAL, // 手动模式
MODE_FIXED_TIME // 固定时长模式
} ChargeMode;
typedef struct
{
ChargeMode mode;
uint8_t is_charging;
uint16_t charge_duration; // 单位sec
uint32_t start_time;
uint32_t stop_time;
} ChargeSys;
ChargeSys sys_state = { MODE_MANUAL, 0, 10, 0, 0 }; // 系统状态结构体
ChargeSys last_sys_state
= { MODE_MANUAL, 0, 10, 0, 0 }; // 上一次系统状态结构体
// 函数声明
void packDataAndSent (uint16_t vol, uint16_t cur, uint16_t pwr, uint16_t tmp,
uint16_t hum); // 数据打包函数
void Process_Keys_Event (u8 key_pressed); // 按键处理函数
void StartCharge (); // 开始充电
void StopCharge (); // 停止充电
void
SystemClock_Init (void)
{
// 烧录时选择30M主频
CLK_DIV = 0x00; // 时钟不分频30MHz直接输出
}
// INA226数据
u16 ina226_voltage = 0;
u16 ina226_current = 0;
u16 ina226_power = 0;
/*******************************************
* 主函数
*******************************************/
void
main ()
{
uint32_t last_round_time = 0;
uint32_t this_round_time = 0;
char *p_json_str = NULL;
SystemClock_Init (); // 时钟配置
Timer_Init (); // 初始化定时器
EA = 1; // 开总中断
Delay_Init ();
Uart1_Init ();
IIC_Init ();
OLED_Init ();
INA226_Init (0.005f, 2.0f);
// DHT10_Init ();
Key_Init ();
DelayMs (100); // 初始化延时
// OLED显示固定信息
OLED_ShowPrintf (0, 0, "Wireless Charge", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_SHOW);
OLED_ShowPrintf (0, 2, "V", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL, OLED_SHOW);
OLED_ShowPrintf (64, 2, "A", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL, OLED_SHOW);
OLED_ShowPrintf (0, 4, "P", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL, OLED_SHOW);
// OLED_ShowPrintf (64, 4, "T", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_SHOW);
// OLED_ShowPrintf (64, 5, "H", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_SHOW);
OLED_ShowPrintf (32, 3, ".", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowPrintf (96, 3, ".", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowPrintf (32, 5, ".", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_CLS);
// OLED_ShowPrintf (96, 4, ".", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_CLS);
// OLED_ShowPrintf (96, 5, ".", OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowPrintf (16, 6, "MANUAL", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS); // 初始化为手动模式
P2M1 &= 0xFE; // P20为推挽输出
P2M0 |= 0x01;
P20 = 1; // P20为推挽输出
sys_state.mode = MODE_AUTO_OFF; // 初始化为常闭模式
StopCharge (); // 停止充电
while (1)
{
ina226_voltage = (int16_t)(INA226_ReadBusVoltage () * 100);
OLED_ShowNum (16, 2, ina226_voltage / 100, 2, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowNum (40, 2, ina226_voltage, 2, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
ina226_current = (int16_t)(INA226_ReadCurrent () * 100);
OLED_ShowNum (80, 2, ina226_current / 100, 2, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowNum (104, 2, ina226_current, 2, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
ina226_power
= (int16_t)((ina226_current / 10.0f) * (ina226_voltage / 10.0f));// 功率
OLED_ShowNum (16, 4, ina226_power / 100, 2, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
OLED_ShowNum (40, 4, ina226_power, 2, OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS);
// 取消温湿度功能
// DHT10_ReadData ();
// OLED_ShowNum (80, 4, DHT10_GetTemperature () / 100, 2,
// OLED_FONT_EIGHT,
// OLED_LEFT_ROLL, OLED_CLS);
// OLED_ShowNum (104, 4, DHT10_GetTemperature (), 2, OLED_FONT_EIGHT,
// OLED_LEFT_ROLL, OLED_CLS);
// OLED_ShowNum (80, 5, DHT10_GetHumidity () / 100, 2, OLED_FONT_EIGHT,
// OLED_LEFT_ROLL, OLED_CLS);
// OLED_ShowNum (104, 5, DHT10_GetHumidity (), 2, OLED_FONT_EIGHT,
// OLED_LEFT_ROLL, OLED_CLS);
// DelayMs (100); // 初始化延时
// last_round_time = this_round_time;
// this_round_time = GetUpTime_10Ms ();
// OLED_ShowNum (4, 7, this_round_time - last_round_time, 3,
// OLED_FONT_EIGHT, OLED_LEFT_ROLL, OLED_SHOW);
packDataAndSent (ina226_voltage, // 电压
ina226_current, // 电流
ina226_power, // 功率
0x0CA2, // 温度
0x0BF6 // 湿度
);
Key_Scan ();
Process_Keys_Event (Get_KeyEvents ());
}
}
// 数据打包函数
void
packDataAndSent (uint16_t vol, uint16_t cur, uint16_t pwr, uint16_t tmp,
uint16_t hum)
{
char txBuffer[29]; // 固定长度发送缓冲区
sprintf (txBuffer, "{%04X,%04X,%04X,%04X,%04X}\r\n", vol, cur, pwr, tmp,
hum); // 固定4字符HEX格式
printf (txBuffer); // 输出到串口
}
void
Uart1_Isr (void) interrupt 4
{
if (TI) // 检测串口1发送中断
{
TI = 0; // 清除串口1发送中断请求位
}
if (RI) // 检测串口1接收中断
{
RI = 0; // 清除串口1接收中断请求位
}
}
/*******************************************
* 按键处理函数
* 需在主循环中调用
*******************************************/
void
Process_Keys_Event (u8 key_pressed)
{
static u8 key_pressed_last = 0;
if (key_pressed)
{
// KEY1处理启动/停止充电
if (key_pressed & 0x08)
{
sys_state.is_charging ^= 1; // 充电状态切换
if (sys_state.mode == MODE_FIXED_TIME && sys_state.is_charging == 1)
// 定实模式下切换进充电状态时 记录相关时间点
{
sys_state.start_time = GetUpTime ();
sys_state.stop_time
= sys_state.start_time + sys_state.charge_duration;
StartCharge ();
}
else if ((sys_state.mode == MODE_FIXED_TIME)
&& (sys_state.is_charging == 0))
// 定实模式下切换出充电状态时 记录剩余时间
{
sys_state.charge_duration = GetUpTime () - sys_state.start_time;
StopCharge ();
}
}
// KEY2处理模式切换
if (key_pressed & 0x04)
{
if (++sys_state.mode > MODE_FIXED_TIME)
{
sys_state.mode = MODE_AUTO_OFF;
}
}
// KEY3/KEY4处理时间调整仅在固定模式下有效
if (sys_state.mode == MODE_FIXED_TIME)
{
if (key_pressed & 0x02)
{ // KEY3增加时间
if (sys_state.charge_duration < 1440)
{ // 24小时上限
sys_state.charge_duration += 10;
}
}
if (key_pressed & 0x01)
{ // KEY4减少时间
if (sys_state.charge_duration > 1)
{
sys_state.charge_duration -= 10;
}
}
}
}
if (last_sys_state.mode != sys_state.mode) // 模式切换
{
OLED_Row_Clear (6, 2, OLED_CLS); // 清除状态栏显示
OLED_ShowPrintf (0, 6, "M", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_SHOW);
switch (sys_state.mode)
{
case MODE_AUTO_OFF:
OLED_ShowPrintf (16, 6, "AUTO_OFF", OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
break;
case MODE_MANUAL:
OLED_ShowPrintf (16, 6, "MANUAL", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS);
break;
case MODE_FIXED_TIME:
OLED_ShowPrintf (16, 6, "TIME Sec", OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_CLS);
}
last_sys_state.mode = sys_state.mode; // 更新状态
}
if (sys_state.mode == MODE_FIXED_TIME) // 固定时间模式下显示时间
{
if (sys_state.is_charging == 1) // 充电中 显示时间
{
if (sys_state.stop_time < GetUpTime ()) // 充电时间已到 停止充电
{
OLED_ShowNum (56, 6, 0x00, 4, OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS); // 显示 0 sec
sys_state.is_charging = 0; // 停止充电
}
else // 充电中 显示剩余时间 单位:秒
{
OLED_ShowNum (56, 6, sys_state.stop_time - GetUpTime (), 4,
OLED_FONT_SIXTEEN, OLED_LEFT_ROLL, OLED_CLS);
}
}
else // 未启动充电 加深时间文字 表示正在设置充电时间
{
OLED_ShowNum (56, 6, sys_state.charge_duration, 4, OLED_FONT_SIXTEEN,
OLED_LEFT_ROLL, OLED_SHOW);
}
}
else if (sys_state.mode == MODE_AUTO_OFF)
{ // 自动停止充电模式
static uint8_t power_under_limite_times = 0; // 充电功率低于阈值次数
if (ina226_power < AUTO_STOP_POWER) // 充电功率低于阈值
{
power_under_limite_times++;
}
if (power_under_limite_times >= 100)
{ // 充电功率低于阈值100次
StopCharge (); // 停止充电
power_under_limite_times = 0; // 重置次数
}
}
if (sys_state.is_charging != last_sys_state.is_charging) // 充电状态切换
{
sys_state.is_charging ? StartCharge () : StopCharge (); // 启动/停止充电
last_sys_state.is_charging = sys_state.is_charging; // 更新状态
}
}
void
StartCharge (void)
{
OLED_ShowPrintf (64, 4, "Runing ", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS);
P20 = 1; // 启动充电
}
void
StopCharge (void)
{
OLED_ShowPrintf (64, 4, "Stopnow", OLED_FONT_SIXTEEN, OLED_LEFT_ROLL,
OLED_CLS);
P20 = 0; // 停止充电
}