2026-07-28 18:03:20 +08:00
|
|
|
|
#include "system.h"
|
|
|
|
|
|
#include "rgb.h"
|
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
|
#include "clock.h"
|
|
|
|
|
|
#include "../Drivers/lcd.h"
|
|
|
|
|
|
#include "../Drivers/rf.h"
|
|
|
|
|
|
#include "../Drivers/adc.h"
|
|
|
|
|
|
#include "../Drivers/pcf8563.h"
|
|
|
|
|
|
#include "intrins.h"
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 引用 main.c <20><>的全<E79A84><E585A8>唤醒与运行状态变<E68081><E58F98>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
extern volatile u8 p0_wakeup_flag;
|
|
|
|
|
|
extern volatile u8 p2_wakeup_flag;
|
|
|
|
|
|
extern volatile u8 p3_wakeup_flag;
|
|
|
|
|
|
extern volatile u8 rf_wakeup_flag;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 系统 GPIO <EFBFBD><EFBFBD>口模式初始化
|
|
|
|
|
|
* @details 配置各引脚的推挽输出、高阻输入及准双向模式,建立系统初<EFBFBD><EFBFBD>电气环境<EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void GPIO_Init(void)
|
|
|
|
|
|
{
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 使能访问扩展特殊功能寄存<E5AF84><E5AD98> XSFR
|
2026-07-28 18:03:20 +08:00
|
|
|
|
EAXFR = 1;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 1. 配置 PWR_HOLD (P0.0) 为推挽输出模<E587BA><E6A8A1> (P0M1 bit0=0, P0M0 bit0=1)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P0M1 &= ~(1 << 0);
|
|
|
|
|
|
P0M0 |= (1 << 0);
|
2026-07-30 15:25:44 +08:00
|
|
|
|
PWR_HOLD = 1; // 上电<E4B88A><E794B5><EFBFBD><EFBFBD>时间拉高,锁存电源保持供<E68C81><E4BE9B>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 2. 配置 KEY_UP (P0.1), KEY_CONFIRM (P0.2) 为高阻输<E998BB><E8BE93>/带上拉准双向
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P0M1 &= ~((1 << 1) | (1 << 2));
|
|
|
|
|
|
P0M0 &= ~((1 << 1) | (1 << 2));
|
|
|
|
|
|
KEY_UP = 1;
|
|
|
|
|
|
KEY_CONFIRM = 1;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 3. 初<><E5889D>化 STC32G <20><><EFBFBD><EFBFBD> ADC 模块 (其中<E585B6><E4B8AD>动配<E58AA8><E9858D> P0.3 <20><> P1.3 为高阻输入模<E585A5><E6A8A1>)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
ADC_Init();
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 4. 配置 PCF8563 I2C 管脚 P3.2 (SCL) <20><> P3.3 (SDA) 为准双向口模式,并开上拉
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P3M1 &= ~((1 << 2) | (1 << 3));
|
|
|
|
|
|
P3M0 &= ~((1 << 2) | (1 << 3));
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P3PU |= (1 << 2) | (1 << 3); // <20><><EFBFBD><EFBFBD> P3.2 <20><> P3.3 的内<E79A84><E58685> 4.7K 上拉电阻
|
2026-07-28 18:03:20 +08:00
|
|
|
|
RTC_SCL = 1;
|
|
|
|
|
|
RTC_SDA = 1;
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 配置推挽输出引脚:
|
|
|
|
|
|
// MOTOR (P2.5), RGB_DIN (P2.3) -> P2M1 bit5,3=0; P2M0 bit5,3=1
|
|
|
|
|
|
P2M1 &= ~((1 << 5) | (1 << 3));
|
|
|
|
|
|
P2M0 |= ((1 << 5) | (1 << 3));
|
|
|
|
|
|
MOTOR = 0;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
RGB_DIN = 0; // P2.3 初<><E5889D>拉低,防<EFBC8C>上电期间 WS2812B <20><>触发
|
2026-07-28 18:03:20 +08:00
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 配置 KEY_SOS (P2.6) 为带上拉准双向口模式以确保输入稳<E585A5><E7A8B3>
|
2026-07-29 09:57:36 +08:00
|
|
|
|
P2M1 &= ~(1 << 6);
|
|
|
|
|
|
P2M0 &= ~(1 << 6);
|
|
|
|
|
|
KEY_SOS = 1;
|
|
|
|
|
|
(*(unsigned char volatile xdata *)0xFE12) |= (1 << 6); // 使能 P2.6 的强内部上拉电阻 (P2PU = 0xFE12)
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// SGM_CTRL (P1.7), LCD 控制管脚 (P1.0, P1.1, P1.4, P1.5, P1.6) <20><>为推挽输<E68CBD><E8BE93>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P1M1 &= ~((1 << 7) | (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6));
|
|
|
|
|
|
P1M0 |= ((1 << 7) | (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6));
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// SHUT (P3.5) 射<>/外<><E5A496>开<EFBFBD><E5BC80>使能脚置为推挽输<E68CBD><E8BE93>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P3M1 &= ~(1 << 5);
|
|
|
|
|
|
P3M0 |= (1 << 5);
|
2026-07-30 15:25:44 +08:00
|
|
|
|
SHUT = 0; // 低电平开<E5B9B3><E5BC80>工作
|
2026-07-28 18:03:20 +08:00
|
|
|
|
|
|
|
|
|
|
// 7. 配置 CHRG_DET (P1.2) 为高阻输入模式,适配 DET 模拟 ADC 通道 2
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 由于<E794B1><E4BA8E>精密模拟电平<E794B5><E5B9B3>测,切勿<E58887><E58BBF><EFBFBD><EFBFBD>引脚内部上拉电阻
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P1M1 |= (1 << 2);
|
|
|
|
|
|
P1M0 &= ~(1 << 2);
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// P1PU 在扩<E59CA8><E689A9> XSFR 空间<E7A9BA><E997B4>没有<E6B2A1><E69C89>定义的话<E79A84><E8AF9D>以用 P1 <20><>口寄存器或<E599A8><E68896>是关闭上拉<E4B88A><E68B89>
|
|
|
|
|
|
// STC32G <20><><EFBFBD><EFBFBD>口上拉寄存器<E5AD98><E599A8> P1PU (FE11H),因为是 XSFR 我们<E68891><E4BBAC> config.h 里有 extern 或直接操<E68EA5><E6938D>
|
|
|
|
|
|
// 扩展 XSFR P1PU 地址<E59CB0><E59D80> 0xFE11
|
2026-07-28 18:03:20 +08:00
|
|
|
|
(*(unsigned char volatile xdata *)0xFE11) &= ~(1 << 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 初<EFBFBD><EFBFBD>化 UART1 串口通信
|
|
|
|
|
|
* @details 设定波特<EFBFBD><EFBFBD> 115200 (使用 Timer2 作为发生<EFBFBD><EFBFBD><EFBFBD><EFBFBD>24.0MHz 晶振)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart1_Init(void)
|
|
|
|
|
|
{
|
2026-07-30 15:25:44 +08:00
|
|
|
|
SCON = 0x50; // 8 位数<E4BD8D><E695B0>, <20><>变波特率
|
|
|
|
|
|
AUXR |= 0x01; // 串口 1 选择 Timer2 做波特率发生<E58F91><E7949F>
|
|
|
|
|
|
AUXR |= 0x04; // Timer2 时钟<E697B6><E9929F> 1T 模式
|
|
|
|
|
|
T2L = 0xCC; // 24MHz / 115200 = 208 (0xD0), 对应 reload <20><> 65536 - 52 = 0xFFCC
|
2026-07-28 18:03:20 +08:00
|
|
|
|
T2H = 0xFF;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
AUXR |= 0x10; // <20><><EFBFBD><EFBFBD> Timer2 运<>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD><EFBFBD>单字节数据
|
2026-07-28 18:03:20 +08:00
|
|
|
|
* @param dat 待发送的字节
|
|
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendByte(u8 dat)
|
|
|
|
|
|
{
|
|
|
|
|
|
SBUF = dat;
|
|
|
|
|
|
while (!TI);
|
|
|
|
|
|
TI = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD><EFBFBD>字符串
|
|
|
|
|
|
* @param s 字<EFBFBD><EFBFBD>串指针
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendString(char *s)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (*s) {
|
|
|
|
|
|
Uart_SendByte(*s++);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 非阻塞接收字<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @return char 接收到的字<EFBFBD><EFBFBD>,若无接收数据则返<EFBFBD><EFBFBD> '\0'
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
char Uart_RxChar(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (RI) {
|
|
|
|
|
|
RI = 0;
|
|
|
|
|
|
return SBUF;
|
|
|
|
|
|
}
|
|
|
|
|
|
return '\0';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 阻<EFBFBD><EFBFBD><EFBFBD>秒延<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @param ms <EFBFBD><EFBFBD>秒数
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Delay_ms(u16 ms)
|
|
|
|
|
|
{
|
|
|
|
|
|
u16 i, j;
|
|
|
|
|
|
for (i = 0; i < ms; i++) {
|
|
|
|
|
|
for (j = 0; j < 2000; j++) {
|
|
|
|
|
|
_nop_();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 阻<EFBFBD><EFBFBD>微秒延<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @param us <EFBFBD><EFBFBD>秒数
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Delay_us(u16 us)
|
|
|
|
|
|
{
|
|
|
|
|
|
u16 i;
|
|
|
|
|
|
for (i = 0; i < us; i++) {
|
|
|
|
|
|
_nop_(); _nop_(); _nop_(); _nop_();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 系统<EFBFBD><EFBFBD>机上电硬件自<EFBFBD><EFBFBD>函数
|
|
|
|
|
|
* @details <EFBFBD><EFBFBD><EFBFBD><EFBFBD> PWR_HOLD 锁存状<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ADC 采样基准与串口<EFBFBD><EFBFBD><EFBFBD>,输出完整自<EFBFBD><EFBFBD> report
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Self_Test(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u16 key_down_adc;
|
|
|
|
|
|
u16 vbat_mv;
|
|
|
|
|
|
u16 batt_adc_raw;
|
|
|
|
|
|
u8 percent;
|
|
|
|
|
|
|
|
|
|
|
|
Uart_SendString("\r\n========================================\r\n");
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] System Power-On Self Test...\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 执<> I2C 总线器件<E599A8><E4BBB6>描,查找 RTC <20><>否物理响<E79086><E5938D>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
PCF8563_ScanDiagnostic();
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 0. I2C <20><>件脚电平诊断测试 (验证引脚<E5BC95><E8849A>控<EFBFBD><E68EA7>与<EFBFBD><E4B88E><EFBFBD><EFBFBD>)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
Uart_SendString("[I2C-DIAG] Pin Level Test Starting...\r\n");
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><> 1 测试 (准双<E58786><E58F8C>+上拉)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
P3M1 &= ~((1 << 2) | (1 << 3));
|
|
|
|
|
|
P3M0 &= ~((1 << 2) | (1 << 3));
|
|
|
|
|
|
P3PU |= (1 << 2) | (1 << 3);
|
|
|
|
|
|
RTC_SCL = 1;
|
|
|
|
|
|
RTC_SDA = 1;
|
|
|
|
|
|
Delay_ms(10);
|
|
|
|
|
|
Uart_SendString("[I2C-DIAG] Write SCL=1, SDA=1 -> Real Level: SCL=");
|
|
|
|
|
|
Uart_SendByte((u8)(RTC_SCL ? '1' : '0'));
|
|
|
|
|
|
Uart_SendString(", SDA=");
|
|
|
|
|
|
Uart_SendByte((u8)(RTC_SDA ? '1' : '0'));
|
|
|
|
|
|
Uart_SendString("\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><> 0 测试
|
2026-07-28 18:03:20 +08:00
|
|
|
|
RTC_SCL = 0;
|
|
|
|
|
|
RTC_SDA = 0;
|
|
|
|
|
|
Delay_ms(10);
|
|
|
|
|
|
Uart_SendString("[I2C-DIAG] Write SCL=0, SDA=0 -> Real Level: SCL=");
|
|
|
|
|
|
Uart_SendByte((u8)(RTC_SCL ? '1' : '0'));
|
|
|
|
|
|
Uart_SendString(", SDA=");
|
|
|
|
|
|
Uart_SendByte((u8)(RTC_SDA ? '1' : '0'));
|
|
|
|
|
|
Uart_SendString("\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 0.2 执<> RTC 底层单独试<E78BAC><E8AF95>测<EFBFBD><E6B58B>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
PCF8563_TryReadDiagnostic();
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 1. 验证 PWR_HOLD 锁存状<E5AD98>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
if (PWR_HOLD == 1) {
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] PWR_HOLD Pin State: HIGH [OK]\r\n");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] PWR_HOLD Pin State: LOW [FAIL]\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 2. <20><><EFBFBD><EFBFBD> P0.3 ADC 按键基准常<E58786><E5B8B8>电<EFBFBD><E794B5>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
key_down_adc = ADC_ReadFiltered(ADC_CHANNEL_KEY_DOWN);
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] KEY_DOWN (P0.3) ADC Raw Value: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (key_down_adc / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (key_down_adc / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (key_down_adc / 10) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (key_down_adc % 10)));
|
|
|
|
|
|
Uart_SendString(" [OK]\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 2.2 <20><><EFBFBD><EFBFBD> KEY_SOS (P2.6) 物理电平常<E5B9B3>
|
2026-07-29 10:04:00 +08:00
|
|
|
|
Uart_SendString("[SELF-TEST] KEY_SOS (P2.6) Pin Level: ");
|
|
|
|
|
|
Uart_SendByte((u8)(KEY_SOS ? '1' : '0'));
|
|
|
|
|
|
Uart_SendString("\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 3. <20><><EFBFBD><EFBFBD> P1.3 电池电压<E794B5><E58E8B>测与百分<E799BE><E58886>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
vbat_mv = ADC_GetBatteryVoltage_mV();
|
|
|
|
|
|
percent = ADC_GetBatteryPercent();
|
|
|
|
|
|
batt_adc_raw = ADC_ReadFiltered(ADC_CHANNEL_BATTERY);
|
|
|
|
|
|
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] Battery Raw ADC: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (batt_adc_raw / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (batt_adc_raw / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (batt_adc_raw / 10) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (batt_adc_raw % 10)));
|
|
|
|
|
|
|
|
|
|
|
|
Uart_SendString(" -> Voltage: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (vbat_mv / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte('.');
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (vbat_mv / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (vbat_mv / 10) % 10));
|
|
|
|
|
|
|
|
|
|
|
|
Uart_SendString(" V, Capacity: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (percent / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (percent / 10) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (percent % 10)));
|
|
|
|
|
|
Uart_SendString("% [OK]\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 4. <20><>查充电状<E794B5><E78AB6>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
{
|
|
|
|
|
|
u16 det_adc = ADC_ReadFiltered(ADC_CHANNEL_CHRG_DET);
|
|
|
|
|
|
u16 det_mv = (det_adc * 3300UL) / 4095UL;
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] CHRG_DET (P1.2) ADC: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_adc / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_adc / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_adc / 10) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_adc % 10)));
|
|
|
|
|
|
Uart_SendString(" -> Voltage: ");
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_mv / 1000) % 10));
|
|
|
|
|
|
Uart_SendByte('.');
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_mv / 100) % 10));
|
|
|
|
|
|
Uart_SendByte((u8)('0' + (det_mv / 10) % 10));
|
|
|
|
|
|
Uart_SendString(" V -> ");
|
|
|
|
|
|
if (det_mv >= 800 && det_mv <= 1800) {
|
|
|
|
|
|
Uart_SendString("CHARGING [OK]\r\n");
|
|
|
|
|
|
} else if (det_mv >= 2200 && det_mv <= 2800) {
|
|
|
|
|
|
Uart_SendString("FULLY CHARGED [OK]\r\n");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Uart_SendString("NOT CHARGING [OK]\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Uart_SendString("[SELF-TEST] Self Test Completed Successfully!\r\n");
|
|
|
|
|
|
Uart_SendString("========================================\r\n\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 执<EFBFBD><EFBFBD>关机断电流<EFBFBD><EFBFBD>
|
|
|
|
|
|
* @details 关断外<EFBFBD><EFBFBD><EFBFBD><EFBFBD>震动提示并拉低 PWR_HOLD 引脚切断总电<EFBFBD><EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Power_Off(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendString("[SYS] Executing Power Off sequence...\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><>达震动反<E58AA8><E58F8D> 100ms
|
2026-07-28 18:03:20 +08:00
|
|
|
|
MOTOR = 1;
|
|
|
|
|
|
Delay_ms(100);
|
|
|
|
|
|
MOTOR = 0;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 关断屏幕背光<E8838C><E58589> RGB <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
SGM_CTRL = 1; // 高电平断电,关闭背光<E8838C><E58589><EFBFBD><EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 拉低 PWR_HOLD 切断电源锁存使<E5AD98><E4BDBF>电源关<E6BA90><E585B3>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
PWR_HOLD = 0;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 进入死循<E6ADBB><E5BEAA>等待电源物理切断
|
2026-07-28 18:03:20 +08:00
|
|
|
|
while (1) {
|
|
|
|
|
|
PWR_HOLD = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 系统切入低功耗停机休眠模<EFBFBD><EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Enter_Low_Power_Sleep(void)
|
|
|
|
|
|
{
|
2026-07-28 18:22:04 +08:00
|
|
|
|
Uart_SendString("[SYS] Entering low power sleep...\r\n");
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 1. 关闭/熄灭 RGB <20><>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 2. <20><> LCD <20><>片写<E78987><E58699> Display OFF 指令 (0x28) 关显<E585B3><E698BE>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
WriteComm(0x28);
|
|
|
|
|
|
Delay_ms(20);
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 3. <20><> LCD <20><>片写<E78987><E58699> Sleep In 指令 (0x10) 关内部电荷泵
|
2026-07-28 18:22:04 +08:00
|
|
|
|
WriteComm(0x10);
|
|
|
|
|
|
Delay_ms(20);
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 4. 关闭背光(高电平<E794B5><E5B9B3>电,关闭背光<E8838C><E58589>屏)
|
2026-07-28 18:22:04 +08:00
|
|
|
|
SGM_CTRL = 1;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 5. 屏幕接口防漏电<E6BC8F><E794B5>理
|
2026-07-28 18:22:04 +08:00
|
|
|
|
LCD_CS = 1;
|
|
|
|
|
|
LCD_RST = 1;
|
|
|
|
|
|
LCD_DCX = 0;
|
|
|
|
|
|
LCD_SCL = 0;
|
|
|
|
|
|
LCD_SDI = 0;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 6. 射<><E5B084><EFBFBD><EFBFBD>置为关<E4B8BA><E585B3>接收模式(低功<E4BD8E><E58A9F>,SHUT=0, RF_SetMode(0)<29><>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
RF_SetMode(0);
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 使能访问扩展特殊功能寄存<E5AF84><E5AD98>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P_SW2 |= 0x80;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 7. 配置 Port0 <20><><EFBFBD><EFBFBD>唤醒<E594A4><E98692> (KEY_UP=P0.1, KEY_CONFIRM=P0.2, KEY_DOWN=P0.3)
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P0IM1 |= 0x0E;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P0IM0 &= ~0x0E; // 下降沿触<E6B2BF><E8A7A6>
|
|
|
|
|
|
P0INTF = 0x00; // 清除挂起的中<E79A84><E4B8AD>标志
|
|
|
|
|
|
P0INTE |= 0x0E; // <20><><EFBFBD><EFBFBD> P0.1, P0.2, P0.3 <20><><EFBFBD><EFBFBD>允<EFBFBD>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P0WKUE |= 0x0E; // 使能 P0.1, P0.2, P0.3 掉电唤醒
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 8. 配置 Port2 <20><><EFBFBD><EFBFBD>唤醒<E594A4><E98692> (SOS=P2.6)
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P2IM1 |= 0x40;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P2IM0 &= ~0x40; // 下降沿触<E6B2BF><E8A7A6>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P2INTF = 0x00; // 清除挂起标志
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P2INTE |= 0x40; // <20><><EFBFBD><EFBFBD> P2.6 <20><><EFBFBD><EFBFBD>允<EFBFBD>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P2WKUE |= 0x40; // 使能 P2.6 掉电唤醒
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 9. 配置 Port3 <20><><EFBFBD><EFBFBD>唤醒<E594A4><E98692> (RF_RX_DATA=P3.6)
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P3IM1 |= 0x40;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P3IM0 |= 0x40; // 双边沿触<E6B2BF><E8A7A6>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P3INTF = 0x00; // 清除挂起标志
|
2026-07-30 15:25:44 +08:00
|
|
|
|
P3INTE |= 0x40; // <20><><EFBFBD><EFBFBD> P3.6 <20><><EFBFBD><EFBFBD>允<EFBFBD>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P3WKUE |= 0x40; // 使能 P3.6 掉电唤醒
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><>保引脚上拉和输入使能,防止因<E6ADA2><E59BA0>空产生的功<E79A84><E58A9F>泄<EFBFBD><E6B384>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P2PU |= 0x40;
|
|
|
|
|
|
P2IE |= 0x40;
|
|
|
|
|
|
P3PU &= ~0x40;
|
|
|
|
|
|
P3IE |= 0x40;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 清零各个唤醒<E594A4><E98692>测标志位
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P0INTF = 0x00;
|
|
|
|
|
|
P2INTF = 0x00;
|
|
|
|
|
|
P3INTF = 0x00;
|
|
|
|
|
|
|
|
|
|
|
|
p0_wakeup_flag = 0;
|
|
|
|
|
|
p2_wakeup_flag = 0;
|
|
|
|
|
|
p3_wakeup_flag = 0;
|
|
|
|
|
|
rf_wakeup_flag = 0;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 10. 关闭系统滴答定时<E5AE9A><E697B6> Timer1 <20><><EFBFBD><EFBFBD>,防<EFBC8C><E998B2>休眠时<E79CA0>定时器<E697B6>唤醒
|
2026-07-28 18:22:04 +08:00
|
|
|
|
ET1 = 0;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
EA = 1; // <20><><EFBFBD><EFBFBD>全局<E585A8><E5B180><EFBFBD><EFBFBD>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
|
|
|
|
|
|
// 配置 PCON 挂起单片机,切入停机 (Power Down) 模式
|
|
|
|
|
|
PCON |= 0x02; // PD = 1
|
2026-07-28 18:03:20 +08:00
|
|
|
|
_nop_(); _nop_(); _nop_(); _nop_();
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// ====== <20><>外部<E5A496><E983A8><EFBFBD><EFBFBD>唤醒后,在<EFBC8C><E59CA8><EFBFBD><EFBFBD>继<EFBFBD><E7BBA7>运<EFBFBD> ======
|
2026-07-28 18:03:20 +08:00
|
|
|
|
Wakeup_Restore();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 休眠唤醒恢<EFBFBD>
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Wakeup_Restore(void)
|
|
|
|
|
|
{
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD>㰴<EFBFBD><E3B0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>/<2F><><EFBFBD><EFBFBD>˲̬<CBB2><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>³<EFBFBD><C2B3><EFBFBD><EFBFBD>ػ<EFBFBD>
|
|
|
|
|
|
extern volatile u16 key_up_hold;
|
|
|
|
|
|
extern volatile u16 key_down_hold;
|
|
|
|
|
|
extern volatile u16 key_confirm_hold;
|
|
|
|
|
|
extern volatile u16 key_sos_hold;
|
|
|
|
|
|
extern volatile u16 comb_hold;
|
|
|
|
|
|
|
|
|
|
|
|
key_up_hold = 0;
|
|
|
|
|
|
key_down_hold = 0;
|
|
|
|
|
|
key_confirm_hold = 0;
|
|
|
|
|
|
key_sos_hold = 0;
|
|
|
|
|
|
comb_hold = 0;
|
|
|
|
|
|
|
2026-07-28 18:22:04 +08:00
|
|
|
|
EAXFR = 1;
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 1. 立即关闭<E585B3><E997AD>有掉电<E68E89><E794B5>部<EFBFBD><E983A8><EFBFBD><EFBFBD>允<EFBFBD><E58581>与唤醒允<E98692><E58581>,防<EFBC8C><E998B2>重<EFBFBD><E9878D>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
P0INTE = 0x00;
|
|
|
|
|
|
P2INTE = 0x00;
|
|
|
|
|
|
P3INTE = 0x00;
|
|
|
|
|
|
P0WKUE = 0x00;
|
|
|
|
|
|
P2WKUE = 0x00;
|
|
|
|
|
|
P3WKUE = 0x00;
|
|
|
|
|
|
P0INTF = 0x00;
|
|
|
|
|
|
P2INTF = 0x00;
|
|
|
|
|
|
P3INTF = 0x00;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 2. 清零掉电唤醒定时<E5AE9A><E697B6>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
WKTCH = 0x00;
|
|
|
|
|
|
WKTCL = 0x00;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 3. <20><><EFBFBD><EFBFBD>全局<E585A8><E5B180><EFBFBD><EFBFBD>并重<E5B9B6><E9878D>系统滴答定时<E5AE9A><E697B6>
|
|
|
|
|
|
// 3. <20>жϿ<D0B6><CFBF><EFBFBD>״̬<D7B4>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><C4BB>ʼ<EFBFBD><CABC>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 4. 恢<><E681A2>射频芯片工作模<E4BD9C><E6A8A1>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
RF_SetMode(1);
|
|
|
|
|
|
|
|
|
|
|
|
// 打印唤醒调试日志
|
|
|
|
|
|
if ((p0_wakeup_flag & 0x0E) || (p2_wakeup_flag & 0x40)) {
|
|
|
|
|
|
Uart_SendString("[WR] Woken by KEY (P0=");
|
|
|
|
|
|
Uart_SendHex8(p0_wakeup_flag);
|
|
|
|
|
|
Uart_SendString(", P2=");
|
|
|
|
|
|
Uart_SendHex8(p2_wakeup_flag);
|
|
|
|
|
|
Uart_SendString(")\r\n");
|
|
|
|
|
|
} else if ((p3_wakeup_flag & 0x40) || rf_wakeup_flag) {
|
|
|
|
|
|
rf_wakeup_flag = 1;
|
|
|
|
|
|
Uart_SendString("[WR] Woken by RF (P3.6)!\r\n");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Uart_SendString("[WR] Woken by TIMER/Other\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 5. 恢<><E681A2>屏幕供电与背光(低电平上电,恢复背光亮屏)
|
2026-07-28 18:22:04 +08:00
|
|
|
|
SGM_CTRL = 0;
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// 6. 延时 200ms 等待液晶稳压板上电稳定后,重新<E9878D> LCD 寄存器初始化
|
2026-07-28 18:22:04 +08:00
|
|
|
|
Delay_ms(200);
|
|
|
|
|
|
LCD_Init();
|
|
|
|
|
|
|
2026-07-30 15:25:44 +08:00
|
|
|
|
// <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>ж<EFBFBD><D0B6><EFBFBD> Timer1 <20>δ<EFBFBD><CEB4><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>жϣ<D0B6><CFA3><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD>ڵ<EFBFBD>ѹ<EFBFBD>ȶ<EFBFBD><C8B6><EFBFBD><EFBFBD>ſ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
EA = 1;
|
|
|
|
|
|
ET1 = 1;
|
|
|
|
|
|
// 7. 充零闲置计时<E8AEA1><E697B6>
|
2026-07-28 18:22:04 +08:00
|
|
|
|
inactivity_timer = 0;
|
2026-07-28 18:03:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 安全获取 Timer0 计数器<EFBFBD> (防高字节滚动跳变)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
u16 GetTimer0_Safe(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u8 high1, high2, low;
|
|
|
|
|
|
do {
|
|
|
|
|
|
high1 = TH0;
|
|
|
|
|
|
low = TL0;
|
|
|
|
|
|
high2 = TH0;
|
|
|
|
|
|
} while (high1 != high2);
|
|
|
|
|
|
return (((u16)high1 << 8) | low);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD> 4 位十<EFBFBD><EFBFBD>进制字<EFBFBD> (0x0~0xF)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendHex4(u8 val)
|
|
|
|
|
|
{
|
|
|
|
|
|
val &= 0x0F;
|
|
|
|
|
|
if (val < 10) {
|
|
|
|
|
|
Uart_SendByte('0' + val);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Uart_SendByte('A' + (val - 10));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD> 8 位十<EFBFBD><EFBFBD>进制 (0x00~0xFF)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendHex8(u8 val)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendHex4(val >> 4);
|
|
|
|
|
|
Uart_SendHex4(val);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD> 16 位十<EFBFBD><EFBFBD>进制 (0x0000~0xFFFF)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendHex16(u16 val)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendHex8((u8)(val >> 8));
|
|
|
|
|
|
Uart_SendHex8((u8)val);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD> 20 位十<EFBFBD><EFBFBD>进制 (用于射<EFBFBD> 5 <EFBFBD><EFBFBD> ID 打印)
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendHex20(u32 val)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendHex4((u8)(val >> 16));
|
|
|
|
|
|
Uart_SendHex16((u16)val);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2026-07-30 15:25:44 +08:00
|
|
|
|
* @brief 串口 1 发<EFBFBD> 32 位十<EFBFBD><EFBFBD>进制
|
2026-07-28 18:03:20 +08:00
|
|
|
|
*/
|
|
|
|
|
|
void Uart_SendHex32(u32 val)
|
|
|
|
|
|
{
|
|
|
|
|
|
Uart_SendHex16((u16)(val >> 16));
|
|
|
|
|
|
Uart_SendHex16((u16)val);
|
|
|
|
|
|
}
|