|
|
爱科技、爱创意、爱折腾、爱极致,我们都是技术控
您需要 登录 才可以下载或查看,没有账号?立即注册
x
代码基本完成了,在调试中遇到把校准值改后,能储存,就是再开机又恢复到之前值了,不知道什么原因
把代码贴出来,请大哥帮忙看看什么原因,都是AI写的,用ai改还是老问题
链接:https://pan.baidu.com/s/1rl3O5jmmQwThJziH4ZE25g 提取码:10vf
- /****************************************************************************
- * STC8H3K64S2-TSSOP20 库仑计主程序 (大字体版)
- *
- * 修改版本 V2.1-board2:
- * 适配新板子引脚定义:
- * - KEYS (菜单/切换键) → P3.0
- * - KEYA (加一键) → P3.1
- * - KEYD (减一键) → P3.2
- * - LCD_DAT (SDA) → P3.7
- * - LCD_CLK (SCL) → P3.6
- * - LCD_RS (A0/DC) → P3.5
- * - LCD_RST → P3.4
- * - LCD_CS → P5.5
- * - CURRENT2 (电流采样) → ADC0 (P1.0)
- * - VOLTAGE2 (电压采样) → ADC6 (P1.6)
- * - TEMPERATURE → ADC7 (P1.7)
- *
- * 编译环境: Keil C51 V9.60+
- * 晶振: 内部IRC 35MHz
- ****************************************************************************/
- #include <reg51.h>
- #include <intrins.h>
- // ============================================================================
- // 宏定义
- // ============================================================================
- #define VERSION "V2.1-board2"
- // 时钟配置 (内部IRC 35MHz)
- #define TIMER0_RELOAD_H 0xF4
- #define TIMER0_RELOAD_L 0xCC
- // ADC配置
- #define ADC_VREF 3300
- #define ADC_RESOLUTION 4096
- // 电压检测参数
- #define VOLTAGE_DIV_R1 300000UL
- #define VOLTAGE_DIV_R2 10000UL
- #define VOLTAGE_RATIO 31
- // 电流检测参数
- #define SHUNT_RESISTOR 2
- #define INA199_GAIN 100
- #define INA199_VREF 1650
- // 容量参数
- #define DEFAULT_CAPACITY 10000UL
- #define CAPACITY_MIN 100UL
- #define CAPACITY_MAX 999900UL
- // 滤波参数
- #define ADC_FILTER_LEN 8
- // 温度检测
- #define TEMPERATURE_CHANNEL 7 // ADC7 = P1.7 NTC热敏电阻
- #define NTC_B_VALUE 3950 // B值
- #define NTC_R25 10000 // 25度时电阻10K
- #define NTC_PULLUP 10000 // 上拉电阻10K
- // EEPROM地址
- #define EEPROM_ADDR_CAPACITY 0x0000
- #define EEPROM_ADDR_REMAINING 0x0004
- // ============================================================================
- // STC8H3K64S2 扩展SFR定义
- // ============================================================================
- sfr P1M0 = 0x92;
- sfr P1M1 = 0x91;
- sfr P3M0 = 0xB2;
- sfr P3M1 = 0xB1;
- sfr P5 = 0xC8;
- sbit P54 = P5^4;
- sfr P5M0 = 0xCA;
- sfr P5M1 = 0xC9;
- sfr AUXR = 0x8E;
- sfr ADC_CONTR = 0xBC;
- sfr ADC_RES = 0xBD;
- sfr ADC_RESL = 0xBE;
- sfr ADCCFG = 0xDE;
- #define ADC_POWER 0x80
- #define ADC_START 0x40
- #define ADC_FLAG 0x20
- sfr IAP_DATA = 0xC2;
- sfr IAP_ADDRH = 0xC3;
- sfr IAP_ADDRL = 0xC4;
- sfr IAP_CMD = 0xC5;
- sfr IAP_TRIG = 0xC6;
- sfr IAP_CONTR = 0xC7;
- #define IAP_EN 0x80
- // ============================================================================
- // 【修改】LCD引脚定义 - 按新板子
- // ============================================================================
- sbit LCD_RST = P3^4; // 改: P3.4 (原P3.0)
- sbit LCD_SCL = P3^6; // 改: P3.6 (原P3.2)
- sbit LCD_SDA = P3^7; // 改: P3.7 (原P3.3)
- sbit LCD_CS = P5^5; // 改: P5.5 (原P3.4)
- sbit LCD_A0 = P3^5; // 不变: P3.5
- // ============================================================================
- // 【修改】按键引脚定义 - 换到独立引脚,避免与LCD冲突
- // ============================================================================
- sbit KEY_MENU = P5^4; // 菜单/切换键 → P5.4 (独立引脚)
- sbit KEY_UP = P1^1; // 加一键 → P1.1 (独立引脚)
- sbit KEY_DOWN = P1^2; // 减一键 → P1.2 (独立引脚)
- // ============================================================================
- // 全局变量 - 全部放xdata
- // ============================================================================
- unsigned int xdata adc_voltage_buf[ADC_FILTER_LEN];
- unsigned int xdata adc_current_buf[ADC_FILTER_LEN];
- unsigned int xdata adc_temp_buf[ADC_FILTER_LEN];
- unsigned char xdata adc_buf_index = 0;
- unsigned long xdata voltage_x100;
- long xdata current_x100;
- unsigned long xdata power_x10;
- unsigned long xdata wh_x100;
- unsigned char xdata temperature_x10 = 0;
- unsigned int xdata adc_temp_raw = 0; // 温度ADC原始值
- unsigned long xdata total_capacity;
- long xdata remaining_capacity;
- unsigned char xdata percentage = 0;
- long xdata coulomb_accumulator = 0;
- unsigned char xdata sys_running = 0;
- unsigned char xdata display_mode = 0;
- unsigned int xdata timer1ms_cnt = 0;
- unsigned int xdata timer10ms_cnt = 0;
- unsigned int xdata timer100ms_cnt = 0;
- unsigned int xdata timer500ms_cnt = 0;
- unsigned long xdata run_seconds = 0;
- bit bdata flag_adc_sample = 0;
- bit bdata flag_coulomb_int = 0;
- bit bdata flag_display_refresh = 0;
- bit bdata flag_key_scan = 0;
- unsigned char xdata key_state = 0;
- unsigned char xdata key_press = 0;
- unsigned int xdata key_hold_cnt = 0;
- unsigned char xdata lcd_buffer[1024];
- unsigned long xdata temp_capacity = 0; // 设置模式临时容量
- // ============================================================================
- // 校准参数
- // ============================================================================
- unsigned int xdata cal_voltage_beiShu = 2082; // 电压倍率校准 2.082 * 1000
- unsigned char xdata cal_voltage_lingDian = 3; // 电压零点校准
- unsigned int xdata cal_current_beiShu = 1273; // 电流倍率校准 1.273 * 1000
- unsigned char xdata cal_current_lingDian = 5; // 电流零点校准
- unsigned char xdata cal_menu = 0; // 校准菜单项 0-3
- unsigned char xdata cal_mode = 0; // 0=正常显示 1=校准模式
- bit bdata flag_cal_save = 0; // 保存校准标志
- // ============================================================================
- // 6x8 ASCII字库 - code区
- // ============================================================================
- unsigned char code font_6x8[][6] = {
- {0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20 space
- {0x00,0x00,0x5F,0x00,0x00,0x00}, // !
- {0x00,0x07,0x00,0x07,0x00,0x00}, // "
- {0x14,0x7F,0x14,0x7F,0x14,0x00}, // #
- {0x24,0x2A,0x7F,0x2A,0x12,0x00}, // $
- {0x23,0x13,0x08,0x64,0x62,0x00}, // %
- {0x36,0x49,0x55,0x22,0x50,0x00}, // &
- {0x00,0x05,0x03,0x00,0x00,0x00}, // \'
- {0x00,0x1C,0x22,0x41,0x00,0x00}, // (
- {0x00,0x41,0x22,0x1C,0x00,0x00}, // )
- {0x08,0x2A,0x1C,0x2A,0x08,0x00}, // *
- {0x08,0x08,0x3E,0x08,0x08,0x00}, // +
- {0x00,0x50,0x30,0x00,0x00,0x00}, // ,
- {0x08,0x08,0x08,0x08,0x08,0x00}, // -
- {0x00,0x60,0x60,0x00,0x00,0x00}, // .
- {0x20,0x10,0x08,0x04,0x02,0x00}, // /
- {0x3E,0x51,0x49,0x45,0x3E,0x00}, // 0
- {0x00,0x42,0x7F,0x40,0x00,0x00}, // 1
- {0x42,0x61,0x51,0x49,0x46,0x00}, // 2
- {0x21,0x41,0x45,0x4B,0x31,0x00}, // 3
- {0x18,0x14,0x12,0x7F,0x10,0x00}, // 4
- {0x27,0x45,0x45,0x45,0x39,0x00}, // 5
- {0x3C,0x4A,0x49,0x49,0x30,0x00}, // 6
- {0x01,0x71,0x09,0x05,0x03,0x00}, // 7
- {0x36,0x49,0x49,0x49,0x36,0x00}, // 8
- {0x06,0x49,0x49,0x29,0x1E,0x00}, // 9
- {0x00,0x36,0x36,0x00,0x00,0x00}, // :
- {0x00,0x56,0x36,0x00,0x00,0x00}, // ;
- {0x00,0x08,0x14,0x22,0x41,0x00}, // <
- {0x14,0x14,0x14,0x14,0x14,0x00}, // =
- {0x41,0x22,0x14,0x08,0x00,0x00}, // >
- {0x02,0x01,0x51,0x09,0x06,0x00}, // ?
- {0x32,0x49,0x79,0x41,0x3E,0x00}, // @
- {0x7E,0x11,0x11,0x11,0x7E,0x00}, // A
- {0x7F,0x49,0x49,0x49,0x36,0x00}, // B
- {0x3E,0x41,0x41,0x41,0x22,0x00}, // C
- {0x7F,0x41,0x41,0x22,0x1C,0x00}, // D
- {0x7F,0x49,0x49,0x49,0x41,0x00}, // E
- {0x7F,0x09,0x09,0x01,0x01,0x00}, // F
- {0x3E,0x41,0x41,0x51,0x32,0x00}, // G
- {0x7F,0x08,0x08,0x08,0x7F,0x00}, // H
- {0x00,0x41,0x7F,0x41,0x00,0x00}, // I
- {0x20,0x40,0x41,0x3F,0x01,0x00}, // J
- {0x7F,0x08,0x14,0x22,0x41,0x00}, // K
- {0x7F,0x40,0x40,0x40,0x40,0x00}, // L
- {0x7F,0x02,0x04,0x02,0x7F,0x00}, // M
- {0x7F,0x04,0x08,0x10,0x7F,0x00}, // N
- {0x3E,0x41,0x41,0x41,0x3E,0x00}, // O
- {0x7F,0x09,0x09,0x09,0x06,0x00}, // P
- {0x3E,0x41,0x51,0x21,0x5E,0x00}, // Q
- {0x7F,0x09,0x19,0x29,0x46,0x00}, // R
- {0x46,0x49,0x49,0x49,0x31,0x00}, // S
- {0x01,0x01,0x7F,0x01,0x01,0x00}, // T
- {0x3F,0x40,0x40,0x40,0x3F,0x00}, // U
- {0x1F,0x20,0x40,0x20,0x1F,0x00}, // V
- {0x7F,0x20,0x18,0x20,0x7F,0x00}, // W
- {0x63,0x14,0x08,0x14,0x63,0x00}, // X
- {0x03,0x04,0x78,0x04,0x03,0x00}, // Y
- {0x61,0x51,0x49,0x45,0x43,0x00}, // Z
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x00,0x00,0x00,0x00,0x00,0x00},
- {0x20,0x54,0x54,0x54,0x78,0x00}, // a
- {0x7F,0x48,0x44,0x44,0x38,0x00}, // b
- {0x38,0x44,0x44,0x44,0x20,0x00}, // c
- {0x38,0x44,0x44,0x48,0x7F,0x00}, // d
- {0x38,0x54,0x54,0x54,0x18,0x00}, // e
- {0x08,0x7E,0x09,0x01,0x02,0x00}, // f
- {0x08,0x14,0x54,0x54,0x3C,0x00}, // g
- {0x7F,0x08,0x04,0x04,0x78,0x00}, // h
- {0x00,0x44,0x7D,0x40,0x00,0x00}, // i
- {0x20,0x40,0x44,0x3D,0x00,0x00}, // j
- {0x00,0x7F,0x10,0x28,0x44,0x00}, // k
- {0x00,0x41,0x7F,0x40,0x00,0x00}, // l
- {0x7C,0x04,0x18,0x04,0x78,0x00}, // m
- {0x7C,0x08,0x04,0x04,0x78,0x00}, // n
- {0x38,0x44,0x44,0x44,0x38,0x00}, // o
- {0x7C,0x14,0x14,0x14,0x08,0x00}, // p
- {0x08,0x14,0x14,0x18,0x7C,0x00}, // q
- {0x7C,0x08,0x04,0x04,0x08,0x00}, // r
- {0x48,0x54,0x54,0x54,0x20,0x00}, // s
- {0x04,0x3F,0x44,0x40,0x20,0x00}, // t
- {0x3C,0x40,0x40,0x20,0x7C,0x00}, // u
- {0x1C,0x20,0x40,0x20,0x1C,0x00}, // v
- {0x3C,0x40,0x30,0x40,0x3C,0x00}, // w
- {0x44,0x28,0x10,0x28,0x44,0x00}, // x
- {0x0C,0x50,0x50,0x50,0x3C,0x00}, // y
- {0x44,0x64,0x54,0x4C,0x44,0x00}, // z
- };
- // ============================================================================
- // 大字体字模 (10x24像素,纵向取模,字节倒序)
- // ============================================================================
- unsigned char code num0[] = {
- 0xFC,0xFE,0xFF,0x0F,0x07,0x07,0x0F,0xFF,0xFE,0xFC,
- 0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,
- 0x0F,0x1F,0x3F,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code num1[] = {
- 0x00,0x18,0x18,0x1C,0xFE,0xFF,0xFF,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,
- 0x00,0x00,0x38,0x38,0x3F,0x3F,0x3F,0x38,0x38,0x00
- };
- unsigned char code num2[] = {
- 0x3C,0x3E,0x3F,0x0F,0x07,0x07,0x8F,0xFF,0xFE,0xFC,
- 0x00,0x00,0x80,0xE0,0xF8,0x7E,0x1F,0x07,0x01,0x00,
- 0x38,0x3E,0x3F,0x3F,0x39,0x38,0x38,0x38,0x38,0x38
- };
- unsigned char code num3[] = {
- 0x3C,0x3E,0x3F,0x0F,0x07,0x07,0x0F,0xFF,0xFE,0xFC,
- 0x00,0x00,0x00,0x00,0x0E,0x0E,0x1F,0xFF,0xFB,0xF1,
- 0x0E,0x1E,0x3E,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code num4[] = {
- 0x00,0x00,0x00,0xC0,0xF8,0xFF,0xFF,0xFF,0x00,0x00,
- 0x80,0xF0,0xFE,0x3F,0x07,0xFF,0xFF,0xFF,0x00,0x00,
- 0x07,0x07,0x07,0x07,0x07,0x3F,0x3F,0x3F,0x07,0x07
- };
- unsigned char code num5[] = {
- 0xFF,0xFF,0xFF,0x87,0x87,0x87,0x87,0x87,0x07,0x07,
- 0x0F,0x0F,0x0F,0x07,0x03,0x03,0x07,0xFF,0xFF,0xFE,
- 0x0E,0x1E,0x3E,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code num6[] = {
- 0xFC,0xFE,0xFF,0x0F,0x07,0x07,0x0F,0x3F,0x3E,0x3C,
- 0xFF,0xFF,0xFF,0x0F,0x07,0x07,0x0F,0xFF,0xFE,0xFC,
- 0x0F,0x1F,0x3F,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code num7[] = {
- 0x07,0x07,0x07,0x07,0x07,0x07,0xE7,0xFF,0xFF,0x3F,
- 0x00,0x00,0x00,0xC0,0xF8,0xFF,0x1F,0x03,0x00,0x00,
- 0x00,0x00,0x00,0x3F,0x3F,0x3F,0x00,0x00,0x00,0x00
- };
- unsigned char code num8[] = {
- 0xFC,0xFE,0xFF,0x0F,0x07,0x07,0x0F,0xFF,0xFE,0xFC,
- 0xFB,0xFF,0xFF,0x1F,0x0E,0x0E,0x1F,0xFF,0xFF,0xFB,
- 0x0F,0x1F,0x3F,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code num9[] = {
- 0xFC,0xFE,0xFF,0x0F,0x07,0x07,0x0F,0xFF,0xFE,0xFC,
- 0x0F,0x1F,0x3F,0x3C,0x38,0x38,0x3C,0xFF,0xFF,0xFF,
- 0x0F,0x1F,0x3F,0x3C,0x38,0x38,0x3C,0x3F,0x1F,0x0F
- };
- unsigned char code *big_num[] = {num0, num1, num2, num3, num4, num5, num6, num7, num8, num9};
- unsigned char code strV[] = {
- 0x30,0xF0,0x80,0x00,0x80,0xF0,0x30,0x00,
- 0x00,0x01,0x0F,0x3C,0x0F,0x01,0x00,0x00
- };
- unsigned char code strA[] = {
- 0x00,0x00,0xC0,0xF0,0xC0,0x00,0x00,0x00,
- 0x30,0x3E,0x07,0x04,0x07,0x3E,0x30,0x00
- };
- unsigned char code strW[] = {
- 0xF0,0xF0,0x00,0x00,0x00,0xF0,0xF0,0x00,
- 0x0F,0x3F,0x38,0x0E,0x38,0x3F,0x0F,0x00
- };
- // 温度符号 8x2(大尺寸,和大字体单位配套)
- unsigned char code strDegreeC[] = {
- 0x06,0x09,0x06,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x00
- };
- unsigned char code strPoint[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00
- };
- // ============================================================================
- // NTC温度查找表 (MF52E 10K B=3950, ADC 12bit, 上拉10K)
- // ADC值对应温度(-40~120度), 索引=温度+40, 值=ADC读数
- // ============================================================================
- unsigned int code temp_table[] = {
- 140,149,159,168,178,188,199,210,222,233,
- 246,259,272,286,301,317,333,349,367,385,
- 403,423,443,464,486,509,533,558,583,610,
- 638,667,696,727,758,791,824,858,893,929,
- 965,1003,1041,1080,1119,1160,1201,1243,1285,1328,
- 1371,1414,1459,1503,1548,1593,1638,1684,1730,1775,
- 1821,1867,1912,1958,2003,2048,2093,2137,2182,2225,
- 2269,2312,2354,2397,2438,2479,2519,2559,2598,2637,
- 2675,2712,2748,2784,2819,2853,2887,2920,2952,2984,
- 3014,3044,3073,3102,3130,3157,3183,3209,3234,3259,
- 3283,3306,3328,3351,3372,3393,3413,3432,3452,3470,
- 3488,3506,3523,3539,3555,3571,3586,3601,3615,3628,
- 3642,3655,3667,3679,3691,3702,3714,3724,3735,3745,
- 3754,3764,3773,3782,3791,3799,3807,3815,3822,3830,
- 3837,3844,3850,3857,3863,3869,3875,3881,3887,3892,
- 3897,3902,3907,3912,3917,3921,3926,3930,3934,3938,3942
- };
- // ============================================================================
- // 函数声明
- // ============================================================================
- void System_Init(void);
- void Clock_Init(void);
- void GPIO_Init(void);
- void Timer0_Init(void);
- void ADC_Init(void);
- void UART1_Init(void);
- void UART1_SendByte(unsigned char dat);
- void UART1_SendString(unsigned char *str);
- void UART1_SendNumber(unsigned long num);
- void UART1_SendHex(unsigned char hex);
- void UART1_SendCRLF(void);
- void LCD_Init(void);
- void LCD_WriteCmd(unsigned char cmd);
- void LCD_WriteData(unsigned char dat);
- void LCD_Clear(void);
- void LCD_SetPos(unsigned char page, unsigned char col);
- void LCD_Refresh(void);
- void LCD_ShowChar(unsigned char page, unsigned char col, unsigned char ch);
- void LCD_ShowString(unsigned char page, unsigned char col, unsigned char *str);
- void LCD_ShowNumber(unsigned char page, unsigned char col, unsigned long num, unsigned char len);
- void LCD_ShowSignedFloat(unsigned char page, unsigned char col, long num_x100, unsigned char int_len, unsigned char dec_len);
- void LCD_ShowFloat(unsigned char page, unsigned char col, unsigned long num_x100, unsigned char int_len, unsigned char dec_len);
- void LCD_ShowBigPic(unsigned char page, unsigned char col, unsigned char width, unsigned char height, unsigned char code *pic);
- void LCD_ShowBigNum(unsigned char page, unsigned char col, unsigned char num);
- void LCD_ShowBigSignedFloat(unsigned char page, unsigned char col, long num_x100, unsigned char int_digits, unsigned char dec_digits);
- void LCD_ShowBigFloat(unsigned char page, unsigned char col, unsigned long num_x100, unsigned char int_digits, unsigned char dec_digits);
- void LCD_Update_Normal(void);
- void LCD_Update_Setting(void);
- void LCD_Update_Calibration(void);
- unsigned int ADC_Read(unsigned char channel);
- unsigned int ADC_GetAverage(unsigned int *buf);
- void ADC_Sample(void);
- void Calculate_Voltage(void);
- void Calculate_Current(void);
- void Calculate_Power(void);
- void Coulomb_Integrate(void);
- void Calculate_Percentage(void);
- void Calculate_Temperature(void);
- unsigned int get_temperature_adc(unsigned int adc);
- void Key_Scan(void);
- void Key_Process(void);
- void EEPROM_Read(unsigned int addr, unsigned char *buf, unsigned char len);
- void EEPROM_Write(unsigned int addr, unsigned char *buf, unsigned char len);
- void Load_Parameters(void);
- void Save_Parameters(void);
- void Delay_ms(unsigned int ms);
- // ============================================================================
- // 主函数
- // ============================================================================
- void main(void)
- {
- System_Init();
- UART1_SendString("BOOT ");
- UART1_SendString((unsigned char *)VERSION);
- UART1_SendCRLF();
- Load_Parameters();
- UART1_SendString("CAP=");
- UART1_SendNumber(total_capacity);
- UART1_SendString(" CAL=");
- UART1_SendNumber((unsigned long)cal_voltage_beiShu);
- UART1_SendString(",");
- UART1_SendNumber((unsigned long)cal_current_beiShu);
- UART1_SendCRLF();
- LCD_Init();
- LCD_Clear();
- LCD_ShowString(3, 20, "Coulometer");
- LCD_ShowString(5, 40, VERSION);
- LCD_Refresh();
- Delay_ms(1500);
- LCD_Clear();
- LCD_Refresh();
- sys_running = 1;
- while(1)
- {
- if(flag_adc_sample)
- {
- flag_adc_sample = 0;
- ADC_Sample();
- }
- if(flag_coulomb_int)
- {
- flag_coulomb_int = 0;
- Calculate_Voltage();
- Calculate_Current();
- Calculate_Power();
- Calculate_Temperature();
- Coulomb_Integrate();
- Calculate_Percentage();
- }
- if(flag_key_scan)
- {
- flag_key_scan = 0;
- Key_Scan();
- Key_Process();
- }
- if(flag_display_refresh)
- {
- flag_display_refresh = 0;
- if(cal_mode == 1)
- LCD_Update_Calibration();
- else if(display_mode == 0)
- LCD_Update_Normal();
- else
- LCD_Update_Setting();
- }
- _nop_();
- }
- }
- // ============================================================================
- // 系统初始化
- // ============================================================================
- void System_Init(void)
- {
- Clock_Init();
- GPIO_Init();
- Timer0_Init();
- ADC_Init();
- UART1_Init();
- EA = 1;
- }
- void Clock_Init(void)
- {
- }
- // ============================================================================
- // 【修改】GPIO初始化 - 按键换到独立引脚
- // ============================================================================
- void GPIO_Init(void)
- {
- // P1口: P1.0=电流ADC0, P1.1=KEY_UP, P1.2=KEY_DOWN, P1.6=电压ADC6, P1.7=温度ADC7
- // 0xC7 = 1100 0111b → P1.0, P1.1, P1.2, P1.6, P1.7 高阻输入
- P1M1 = 0xC7;
- P1M0 = 0x00;
- // P3口配置:
- // 全部输出(强推挽): P3.4=LCD_RST, P3.5=LCD_A0, P3.6=LCD_SCL, P3.7=LCD_SDA
- // P3.0-P3.3 未使用,设为输出避免悬空
- // P3M1 = 0x00
- // P3M0 = 0xFF = 1111 1111b → P3全部强推挽输出
- P3M1 = 0x00;
- P3M0 = 0xFF;
- // P5口: P5.4=KEY_MENU(输入), P5.5=LCD_CS(输出)
- // P5M1 = 0x10 = 0001 0000b → P5.4 高阻输入
- // P5M0 = 0x20 = 0010 0000b → P5.5 强推挽输出
- P5M1 = 0x10;
- P5M0 = 0x20;
- LCD_CS = 1;
- LCD_A0 = 0;
- LCD_SCL = 0;
- LCD_SDA = 0;
- LCD_RST = 1;
- KEY_MENU = 1;
- KEY_UP = 1;
- KEY_DOWN = 1;
- }
- void Timer0_Init(void)
- {
- AUXR &= 0x7F;
- TMOD &= 0xF0;
- TMOD |= 0x00;
- TL0 = TIMER0_RELOAD_L;
- TH0 = TIMER0_RELOAD_H;
- TF0 = 0;
- TR0 = 1;
- ET0 = 1;
- }
- void ADC_Init(void)
- {
- ADCCFG = 0x00;
- ADC_CONTR = 0x00;
- Delay_ms(1);
- ADC_CONTR = ADC_POWER;
- Delay_ms(1);
- }
- // ============================================================================
- // 【修复】串口初始化 - 修正波特率9600@35MHz
- // ============================================================================
- // 35MHz, T1x12=1, SMOD=0, 定时器1模式2(8位自动重装)
- // Baud = (1/32) * 35000000 / (256-TH1) = 9600
- // TH1 = 256 - 35000000/32/9600 = 256 - 114 = 142 = 0x8E
- // ============================================================================
- void UART1_Init(void)
- {
- SCON = 0x50; // 模式1, 允许接收
- AUXR |= 0x40; // T1x12=1, 定时器1时钟=Fosc/1
- AUXR &= 0xFE; // S1ST2=0, 串口1选定时器1
- TMOD &= 0x0F; // 清定时器1模式位
- TMOD |= 0x20; // 定时器1模式2(8位自动重装)
- TH1 = 0x8E; // 9600bps [url=home.php?mod=space&uid=3057940]@[/url] 35MHz
- TL1 = 0x8E;
- TR1 = 1;
- ES = 1;
- }
- // ============================================================================
- // 【新增】串口调试函数
- // ============================================================================
- void UART1_SendByte(unsigned char dat)
- {
- SBUF = dat;
- while(!TI);
- TI = 0;
- }
- void UART1_SendString(unsigned char *str)
- {
- while(*str != '\0')
- {
- UART1_SendByte(*str);
- str++;
- }
- }
- void UART1_SendNumber(unsigned long num)
- {
- unsigned char buf[12];
- unsigned char i = 0;
- if(num == 0)
- {
- UART1_SendByte('0');
- return;
- }
- while(num > 0)
- {
- buf[i++] = num % 10 + '0';
- num /= 10;
- }
- while(i > 0)
- {
- UART1_SendByte(buf[--i]);
- }
- }
- void UART1_SendHex(unsigned char hex)
- {
- unsigned char h = hex >> 4;
- unsigned char l = hex & 0x0F;
- UART1_SendByte(h < 10 ? h + '0' : h - 10 + 'A');
- UART1_SendByte(l < 10 ? l + '0' : l - 10 + 'A');
- }
- void UART1_SendCRLF(void)
- {
- UART1_SendByte('\r');
- UART1_SendByte('\n');
- }
- // ============================================================================
- // 定时器0中断 (1ms)
- // ============================================================================
- void Timer0_ISR(void) interrupt 1
- {
- static unsigned int sec_cnt = 0;
- timer1ms_cnt++;
- timer10ms_cnt++;
- timer100ms_cnt++;
- timer500ms_cnt++;
- sec_cnt++;
- if(sec_cnt >= 1000)
- {
- sec_cnt = 0;
- run_seconds++;
- }
- if(timer10ms_cnt >= 10)
- {
- timer10ms_cnt = 0;
- flag_adc_sample = 1;
- }
- if(timer1ms_cnt % 20 == 0)
- {
- flag_key_scan = 1;
- }
- if(timer100ms_cnt >= 100)
- {
- timer100ms_cnt = 0;
- flag_coulomb_int = 1;
- }
- if(timer500ms_cnt >= 500)
- {
- timer500ms_cnt = 0;
- flag_display_refresh = 1;
- }
- }
- // ============================================================================
- // ADC操作
- // ============================================================================
- unsigned int ADC_Read(unsigned char channel)
- {
- unsigned int adc_value;
- ADC_CONTR = ADC_POWER | ADC_START | (channel & 0x0F);
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- while(!(ADC_CONTR & ADC_FLAG));
- ADC_CONTR &= ~ADC_FLAG;
- adc_value = (ADC_RES & 0x0F) << 8;
- adc_value |= ADC_RESL;
- return adc_value;
- }
- unsigned int ADC_GetAverage(unsigned int *buf)
- {
- unsigned long sum = 0;
- unsigned char i;
- for(i = 0; i < ADC_FILTER_LEN; i++)
- {
- sum += buf[i];
- }
- return (unsigned int)(sum >> 3);
- }
- // ============================================================================
- // 【修改】ADC采样 - 电流ADC0(P1.0), 电压ADC6(P1.6), 温度ADC7(P1.7)
- // ============================================================================
- void ADC_Sample(void)
- {
- // 【修改】电流→ADC0(P1.0), 电压→ADC6(P1.6) 互换
- adc_current_buf[adc_buf_index] = ADC_Read(0); // 电流采样 → ADC0
- adc_voltage_buf[adc_buf_index] = ADC_Read(6); // 电压采样 → ADC6
- adc_temp_buf[adc_buf_index] = ADC_Read(TEMPERATURE_CHANNEL); // 温度 → ADC7
- adc_buf_index++;
- if(adc_buf_index >= ADC_FILTER_LEN)
- {
- adc_buf_index = 0;
- }
- }
- // ============================================================================
- // 测量计算
- // ============================================================================
- void Calculate_Voltage(void)
- {
- unsigned int adc_avg;
- long voltage_mv;
- long temp;
- adc_avg = ADC_GetAverage(adc_voltage_buf);
- // 应用零点校准
- if(adc_avg >= cal_voltage_lingDian)
- adc_avg -= cal_voltage_lingDian;
- else
- adc_avg = 0;
- // 计算电压值 (mV)
- voltage_mv = (long)adc_avg * ADC_VREF / ADC_RESOLUTION;
- // 应用分压比和倍率校准
- temp = voltage_mv * VOLTAGE_RATIO;
- temp = temp * (long)cal_voltage_beiShu / 1000L;
- voltage_x100 = (unsigned long)(temp / 10);
- if(voltage_x100 > 9900) voltage_x100 = 9900;
- }
- void Calculate_Current(void)
- {
- unsigned int adc_avg;
- unsigned long voltage_mv;
- long current_ma;
- adc_avg = ADC_GetAverage(adc_current_buf);
- voltage_mv = (unsigned long)adc_avg * ADC_VREF / ADC_RESOLUTION;
- if(voltage_mv >= INA199_VREF)
- {
- current_ma = (long)(voltage_mv - INA199_VREF) * 5;
- }
- else
- {
- current_ma = -(long)(INA199_VREF - voltage_mv) * 5;
- }
- current_x100 = current_ma / 10;
- if(current_x100 > 1500) current_x100 = 1500;
- if(current_x100 < -1500) current_x100 = -1500;
- }
- void Calculate_Power(void)
- {
- long power;
- power = (long)voltage_x100 * current_x100 / 1000;
- if(power < 0) power = -power;
- power_x10 = (unsigned long)power;
- wh_x100 = power_x10 * 100 / 36000;
- if(wh_x100 > 999999) wh_x100 = 999999;
- }
- void Coulomb_Integrate(void)
- {
- long dQ_ma_ms;
- dQ_ma_ms = current_x100 * 10 * 100;
- coulomb_accumulator += dQ_ma_ms;
- while(coulomb_accumulator >= 3600000L)
- {
- coulomb_accumulator -= 3600000L;
- remaining_capacity--;
- }
- while(coulomb_accumulator <= -3600000L)
- {
- coulomb_accumulator += 3600000L;
- remaining_capacity++;
- }
- if(remaining_capacity > (long)total_capacity)
- remaining_capacity = (long)total_capacity;
- if(remaining_capacity < 0)
- remaining_capacity = 0;
- }
- void Calculate_Percentage(void)
- {
- if(total_capacity > 0)
- {
- percentage = (unsigned char)(remaining_capacity * 100 / (long)total_capacity);
- }
- else
- {
- percentage = 0;
- }
- if(percentage > 100) percentage = 100;
- }
- // ============================================================================
- // 温度计算
- // ============================================================================
- unsigned int get_temperature_adc(unsigned int adc)
- {
- unsigned char min, max, mid;
- unsigned int result;
- if(adc < temp_table[0]) return 0xFFFE;
- if(adc > temp_table[160]) return 0xFFFF;
- min = 0;
- max = 160;
- while(min < max)
- {
- mid = (min + max) >> 1;
- if(adc <= temp_table[mid])
- max = mid;
- else
- min = mid + 1;
- }
- result = (unsigned int)(min - 40) * 10;
- return result;
- }
- void Calculate_Temperature(void)
- {
- unsigned int adc_avg;
- unsigned int temp_result;
- adc_avg = ADC_GetAverage(adc_temp_buf);
- adc_temp_raw = adc_avg;
- temp_result = get_temperature_adc(adc_avg);
- if(temp_result == 0xFFFE)
- temperature_x10 = 0;
- else if(temp_result == 0xFFFF)
- temperature_x10 = 255;
- else
- temperature_x10 = (unsigned char)(temp_result / 10);
- }
- // ============================================================================
- // LCD驱动 (ST7567 4线SPI)
- // ============================================================================
- void SPI_WriteByte(unsigned char dat)
- {
- unsigned char i;
- for(i = 0; i < 8; i++)
- {
- LCD_SCL = 0;
- if(dat & 0x80)
- LCD_SDA = 1;
- else
- LCD_SDA = 0;
- LCD_SCL = 1;
- dat <<= 1;
- }
- LCD_SCL = 0;
- }
- void LCD_WriteCmd(unsigned char cmd)
- {
- LCD_CS = 0;
- LCD_A0 = 0;
- SPI_WriteByte(cmd);
- LCD_CS = 1;
- }
- void LCD_WriteData(unsigned char dat)
- {
- LCD_CS = 0;
- LCD_A0 = 1;
- SPI_WriteByte(dat);
- LCD_CS = 1;
- }
- void LCD_Init(void)
- {
- LCD_RST = 0;
- Delay_ms(10);
- LCD_RST = 1;
- Delay_ms(10);
- LCD_WriteCmd(0xE2);
- Delay_ms(10);
- LCD_WriteCmd(0xA2);
- LCD_WriteCmd(0xA0);
- LCD_WriteCmd(0xC8);
- LCD_WriteCmd(0x2F);
- Delay_ms(50);
- LCD_WriteCmd(0x24);
- LCD_WriteCmd(0x81);
- LCD_WriteCmd(0x25);
- LCD_WriteCmd(0x40);
- LCD_WriteCmd(0xAF);
- LCD_Clear();
- }
- void LCD_Clear(void)
- {
- unsigned int i;
- for(i = 0; i < 1024; i++)
- {
- lcd_buffer[i] = 0x00;
- }
- }
- void LCD_SetPos(unsigned char page, unsigned char col)
- {
- LCD_WriteCmd(0xB0 + page);
- LCD_WriteCmd(0x10 + (col >> 4));
- LCD_WriteCmd(0x00 + (col & 0x0F));
- }
- // ============================================================================
- // LCD显示函数 (6x8)
- // ============================================================================
- void LCD_ShowChar(unsigned char page, unsigned char col, unsigned char ch)
- {
- unsigned char i;
- unsigned char index;
- if(ch < 0x20 || ch > 0x7A)
- ch = 0x20;
- index = ch - 0x20;
- for(i = 0; i < 6; i++)
- {
- if(col + i < 128)
- {
- lcd_buffer[page * 128 + col + i] = font_6x8[index][i];
- }
- }
- }
- void LCD_ShowString(unsigned char page, unsigned char col, unsigned char *str)
- {
- while(*str != '\0')
- {
- LCD_ShowChar(page, col, *str);
- col += 6;
- str++;
- }
- }
- void LCD_ShowNumber(unsigned char page, unsigned char col, unsigned long num, unsigned char len)
- {
- unsigned char buf[10];
- unsigned char i;
- for(i = 0; i < len; i++)
- {
- buf[len - 1 - i] = num % 10 + '0';
- num /= 10;
- }
- for(i = 0; i < len; i++)
- {
- LCD_ShowChar(page, col + i * 6, buf[i]);
- }
- }
- void LCD_ShowSignedFloat(unsigned char page, unsigned char col, long num_x100, unsigned char int_len, unsigned char dec_len)
- {
- unsigned char buf[12];
- unsigned char i = 0;
- unsigned char pos = 0;
- unsigned long abs_val;
- if(num_x100 < 0)
- {
- buf[pos++] = '-';
- abs_val = (unsigned long)(-num_x100);
- }
- else
- {
- buf[pos++] = ' ';
- abs_val = (unsigned long)num_x100;
- }
- {
- unsigned long div = 1;
- unsigned char j;
- unsigned char leading_zero = 1;
- for(j = 1; j < int_len; j++)
- div *= 10;
- for(j = 0; j < int_len; j++)
- {
- unsigned char digit = abs_val / div / 100;
- if(digit > 0 || !leading_zero || j == int_len - 1)
- {
- buf[pos++] = digit + '0';
- leading_zero = 0;
- }
- else
- {
- buf[pos++] = ' ';
- }
- abs_val %= div * 100;
- div /= 10;
- }
- }
- buf[pos++] = '.';
- {
- unsigned long frac = abs_val % 100;
- unsigned char digit1 = frac / 10;
- unsigned char digit2 = frac % 10;
- if(dec_len >= 1) buf[pos++] = digit1 + '0';
- if(dec_len >= 2) buf[pos++] = digit2 + '0';
- }
- for(i = 0; i < pos; i++)
- {
- LCD_ShowChar(page, col + i * 6, buf[i]);
- }
- }
- void LCD_ShowFloat(unsigned char page, unsigned char col, unsigned long num_x100, unsigned char int_len, unsigned char dec_len)
- {
- LCD_ShowSignedFloat(page, col, (long)num_x100, int_len, dec_len);
- }
- void LCD_Refresh(void)
- {
- unsigned char page;
- unsigned char col;
- for(page = 0; page < 8; page++)
- {
- LCD_SetPos(page, 0);
- for(col = 0; col < 128; col++)
- {
- LCD_WriteData(lcd_buffer[page * 128 + col]);
- }
- }
- }
- // ============================================================================
- // 大字体显示函数 (10x24)
- // ============================================================================
- void LCD_ShowBigPic(unsigned char page, unsigned char col, unsigned char width, unsigned char height, unsigned char code *pic)
- {
- unsigned char i, j;
- unsigned char idx = 0;
- for(j = 0; j < height; j++)
- {
- for(i = 0; i < width; i++)
- {
- if(col + i < 128 && page + j < 8)
- {
- lcd_buffer[(page + j) * 128 + col + i] = pic[idx++];
- }
- else
- {
- idx++;
- }
- }
- }
- }
- void LCD_ShowBigNum(unsigned char page, unsigned char col, unsigned char num)
- {
- if(num > 9) return;
- LCD_ShowBigPic(page, col, 10, 3, big_num[num]);
- }
- void LCD_ShowBigSignedFloat(unsigned char page, unsigned char col, long num_x100, unsigned char int_digits, unsigned char dec_digits)
- {
- unsigned char pos = 0;
- unsigned char i;
- unsigned long abs_val;
- unsigned char current_col = col;
- if(num_x100 < 0)
- {
- LCD_ShowChar(page + 1, current_col, '-');
- current_col += 6;
- abs_val = (unsigned long)(-num_x100);
- }
- else
- {
- abs_val = (unsigned long)num_x100;
- }
- {
- unsigned long div = 1;
- unsigned char j;
- unsigned char leading_zero = 1;
- for(j = 1; j < int_digits; j++)
- div *= 10;
- for(j = 0; j < int_digits; j++)
- {
- unsigned char digit = abs_val / div / 100;
- if(digit > 0 || !leading_zero || j == int_digits - 1)
- {
- LCD_ShowBigNum(page, current_col, digit);
- current_col += 10;
- leading_zero = 0;
- }
- else
- {
- current_col += 10;
- }
- abs_val %= div * 100;
- div /= 10;
- }
- }
- LCD_ShowBigPic(page + 1, current_col, 8, 2, strPoint);
- current_col += 8;
- {
- unsigned long frac = abs_val % 100;
- unsigned char digit1 = frac / 10;
- unsigned char digit2 = frac % 10;
- if(dec_digits >= 1)
- {
- LCD_ShowBigNum(page, current_col, digit1);
- current_col += 10;
- }
- if(dec_digits >= 2)
- {
- LCD_ShowBigNum(page, current_col, digit2);
- current_col += 10;
- }
- }
- }
- void LCD_ShowBigFloat(unsigned char page, unsigned char col, unsigned long num_x100, unsigned char int_digits, unsigned char dec_digits)
- {
- LCD_ShowBigSignedFloat(page, col, (long)num_x100, int_digits, dec_digits);
- }
- // ============================================================================
- // 显示界面更新 - 大字体版
- // ============================================================================
- void LCD_Update_Normal(void)
- {
- unsigned char col;
- unsigned long cap_for_display;
- LCD_Clear();
- // 第1行: 电压 (Page 0-2, 左)
- LCD_ShowBigFloat(0, 0, voltage_x100, 2, 2);
- LCD_ShowBigPic(1, 50, 8, 2, strV);
- // 第1行: 容量Ah (Page 0-2, 右)
- cap_for_display = (unsigned long)(remaining_capacity / 10);
- LCD_ShowBigFloat(0, 66, cap_for_display, 2, 2);
- LCD_ShowString(2, 116, "Ah");
- // 第2行: 功率 (Page 3-5, 左)
- LCD_ShowBigFloat(3, 0, power_x10, 3, 1);
- LCD_ShowBigPic(4, 50, 8, 2, strW);
- // 第2行: 电流 (Page 3-5, 右)
- LCD_ShowBigSignedFloat(3, 66, current_x100, 2, 2);
- LCD_ShowBigPic(4, 120, 8, 2, strA);
- // ========== 第3行: 电池百分比 (Page 6, 6x8小字体) ==========
- {
- LCD_ShowString(6, 0, "BAT");
- LCD_ShowNumber(6, 24, percentage, 3);
- LCD_ShowChar(6, 42, '%');
- }
- // ========== 第4行: 时间和温度 (Page 7, 6x8小字体) ==========
- {
- unsigned long rs = run_seconds;
- unsigned char hours = rs / 3600;
- unsigned char minutes = (rs % 3600) / 60;
- unsigned char seconds = rs % 60;
- // 时间显示
- LCD_ShowNumber(7, 0, hours, 2);
- LCD_ShowChar(7, 12, ':');
- LCD_ShowNumber(7, 18, minutes, 2);
- LCD_ShowChar(7, 30, ':');
- LCD_ShowNumber(7, 36, seconds, 2);
- LCD_ShowChar(7, 48, 'T');
- // 温度显示 - 纯6x8小字体
- {
- unsigned char buf[8];
- unsigned char t = temperature_x10;
- unsigned char i = 0;
- if(t >= 100) {
- buf[i++] = t / 100 + '0';
- t %= 100;
- }
- if(t >= 10) {
- buf[i++] = t / 10 + '0';
- } else {
- buf[i++] = '0';
- }
- buf[i++] = t % 10 + '0';
- buf[i++] = '.';
- buf[i++] = '0';
- buf[i++] = 'C';
- buf[i] = '\0';
- LCD_ShowString(7, 72, buf);
- }
- }
- LCD_Refresh();
- }
- void LCD_Update_Setting(void)
- {
- LCD_Clear();
- LCD_ShowString(4, 20, "Set Capacity");
- LCD_ShowString(5, 0, "Capacity:");
- LCD_ShowFloat(6, 0, (unsigned long)(temp_capacity / 10), 4, 2);
- LCD_ShowString(6, 54, "Ah");
- LCD_ShowString(7, 0, "+ OK -");
- LCD_Refresh();
- }
- // ============================================================================
- // 校准界面显示 - 大字体
- // ============================================================================
- void LCD_Update_Calibration(void)
- {
- unsigned long display_val;
- LCD_Clear();
- if(cal_menu <= 1)
- {
- LCD_ShowString(0, 0, "U CAL");
- if(cal_menu == 0) LCD_ShowString(0, 40, "ZERO");
- else LCD_ShowString(0, 40, "RATE");
- if(cal_menu == 0)
- {
- display_val = (unsigned long)cal_voltage_lingDian * 100;
- LCD_ShowBigFloat(1, 0, display_val, 2, 2);
- }
- else
- {
- display_val = (unsigned long)cal_voltage_beiShu;
- LCD_ShowBigFloat(1, 0, display_val, 4, 0);
- }
- }
- else
- {
- LCD_ShowString(0, 0, "U NOW");
- LCD_ShowBigFloat(1, 0, voltage_x100, 2, 2);
- LCD_ShowBigPic(2, 50, 8, 2, strV);
- }
- if(cal_menu >= 2)
- {
- LCD_ShowString(4, 0, "I CAL");
- if(cal_menu == 2) LCD_ShowString(4, 40, "ZERO");
- else LCD_ShowString(4, 40, "RATE");
- if(cal_menu == 2)
- {
- display_val = (unsigned long)cal_current_lingDian * 100;
- LCD_ShowBigFloat(5, 0, display_val, 2, 2);
- }
- else
- {
- display_val = (unsigned long)cal_current_beiShu;
- LCD_ShowBigFloat(5, 0, display_val, 4, 0);
- }
- }
- else
- {
- LCD_ShowString(4, 0, "I NOW");
- LCD_ShowBigSignedFloat(5, 0, current_x100, 2, 2);
- LCD_ShowBigPic(6, 116, 8, 2, strA);
- }
- LCD_ShowString(7, 0, "+ SAVE -");
- if(cal_menu == 0) LCD_ShowString(7, 60, "<U0>");
- else if(cal_menu == 1) LCD_ShowString(7, 60, "<Ub>");
- else if(cal_menu == 2) LCD_ShowString(7, 60, "<I0>");
- else LCD_ShowString(7, 60, "<Ib>");
- LCD_Refresh();
- }
- // ============================================================================
- // 【修改】按键扫描 - 适配新按键引脚
- // ============================================================================
- void Key_Scan(void)
- {
- unsigned char key_temp = 0;
- // 【修改】按键引脚: P1.1=KEY_UP(加一), P5.4=KEY_MENU(菜单), P1.2=KEY_DOWN(减一)
- if(KEY_UP == 0) key_temp |= 0x01; // 加一键 P1.1
- if(KEY_MENU == 0) key_temp |= 0x02; // 菜单/切换键 P5.4
- if(KEY_DOWN == 0) key_temp |= 0x04; // 减一键 P1.2
- if(key_temp != key_state)
- {
- key_state = key_temp;
- key_hold_cnt = 0;
- }
- else
- {
- if(key_hold_cnt < 65535)
- key_hold_cnt++;
- }
- // 【修改】长按检测:加一键(KEY_UP/P3.1)长按3秒进入校准模式
- if(cal_mode == 0 && display_mode == 0 && (key_state & 0x01) && key_hold_cnt >= 150)
- {
- cal_mode = 1;
- cal_menu = 0;
- key_hold_cnt = 0;
- key_press = 0;
- return;
- }
- if(key_hold_cnt == 2)
- {
- key_press = key_state;
- }
- else
- {
- key_press = 0;
- }
- }
- // ============================================================================
- // 【修改】按键处理 - 适配新按键布局
- // ============================================================================
- void Key_Process(void)
- {
- static unsigned char xdata setting_item = 0;
- if(key_press == 0) return;
- // 校准模式按键处理
- if(cal_mode == 1)
- {
- if(key_press & 0x01) // 加一键(KEY_UP)
- {
- switch(cal_menu)
- {
- case 0:
- if(cal_voltage_lingDian < 100) cal_voltage_lingDian++;
- break;
- case 1:
- cal_voltage_beiShu += 10;
- if(cal_voltage_beiShu > 5000) cal_voltage_beiShu = 5000;
- break;
- case 2:
- if(cal_current_lingDian < 100) cal_current_lingDian++;
- break;
- case 3:
- cal_current_beiShu += 10;
- if(cal_current_beiShu > 5000) cal_current_beiShu = 5000;
- break;
- }
- }
- else if(key_press & 0x04) // 减一键(KEY_DOWN)
- {
- switch(cal_menu)
- {
- case 0:
- if(cal_voltage_lingDian > 0) cal_voltage_lingDian--;
- break;
- case 1:
- if(cal_voltage_beiShu >= 10) cal_voltage_beiShu -= 10;
- break;
- case 2:
- if(cal_current_lingDian > 0) cal_current_lingDian--;
- break;
- case 3:
- if(cal_current_beiShu >= 10) cal_current_beiShu -= 10;
- break;
- }
- }
- else if(key_press & 0x02) // 菜单键(KEY_MENU) - 切换菜单项或保存
- {
- if(cal_menu < 3)
- {
- cal_menu++;
- }
- else
- {
- cal_menu = 0;
- cal_mode = 0;
- Save_Parameters();
- }
- }
- return;
- }
- // 正常模式按键处理
- switch(display_mode)
- {
- case 0:
- if(key_press & 0x02) // 菜单键(KEY_MENU)短按 - 进入容量设置
- {
- display_mode = 1;
- setting_item = 0;
- temp_capacity = total_capacity;
- }
- break;
- case 1:
- if(key_press & 0x01) // 加一键(KEY_UP)
- {
- if(setting_item == 0)
- {
- temp_capacity += 100;
- if(temp_capacity > CAPACITY_MAX)
- temp_capacity = CAPACITY_MAX;
- }
- }
- else if(key_press & 0x04) // 减一键(KEY_DOWN)
- {
- if(setting_item == 0)
- {
- if(temp_capacity >= 100)
- temp_capacity -= 100;
- }
- }
- else if(key_press & 0x02) // 菜单键(KEY_MENU) - 保存并退出
- {
- total_capacity = temp_capacity;
- remaining_capacity = total_capacity;
- Save_Parameters();
- display_mode = 0;
- }
- break;
- default:
- display_mode = 0;
- break;
- }
- }
- // ============================================================================
- // 【终极修复】EEPROM操作 - STC官方标准时序
- // ============================================================================
- // STC8H3K64S2 IAP参数:
- // - 扇区大小: 512字节
- // - 35MHz时WT: 4 (IAP_CONTR = 0x84)
- // - 字节编程: 约30-40us
- // - 扇区擦除: 约5-10ms
- // ============================================================================
- void IAP_SectorErase(unsigned int addr)
- {
- unsigned int sector;
- sector = addr & 0xFE00; // 512字节扇区对齐
- EA = 0;
- IAP_CONTR = 0x84; // 使能IAP, WT=4 (35MHz)
- IAP_CMD = 0x02; // 扇区擦除命令
- IAP_ADDRH = (unsigned char)(sector >> 8);
- IAP_ADDRL = (unsigned char)(sector);
- IAP_TRIG = 0x5A;
- IAP_TRIG = 0xA5;
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- IAP_CONTR = 0x00;
- IAP_CMD = 0x00;
- EA = 1;
- }
- void IAP_ByteRead(unsigned int addr, unsigned char *buf, unsigned char len)
- {
- unsigned char i;
- EA = 0;
- for(i = 0; i < len; i++)
- {
- IAP_CONTR = 0x84;
- IAP_CMD = 0x01; // 字节读
- IAP_ADDRH = (unsigned char)(addr >> 8);
- IAP_ADDRL = (unsigned char)(addr);
- IAP_TRIG = 0x5A;
- IAP_TRIG = 0xA5;
- _nop_();
- _nop_();
- buf[i] = IAP_DATA;
- addr++;
- }
- IAP_CONTR = 0x00;
- IAP_CMD = 0x00;
- EA = 1;
- }
- void IAP_ByteWrite(unsigned int addr, unsigned char *buf, unsigned char len)
- {
- unsigned char i;
- EA = 0;
- for(i = 0; i < len; i++)
- {
- IAP_CONTR = 0x84;
- IAP_CMD = 0x03; // 字节编程
- IAP_ADDRH = (unsigned char)(addr >> 8);
- IAP_ADDRL = (unsigned char)(addr);
- IAP_DATA = buf[i];
- IAP_TRIG = 0x5A;
- IAP_TRIG = 0xA5;
- _nop_();
- _nop_();
- addr++;
- }
- IAP_CONTR = 0x00;
- IAP_CMD = 0x00;
- EA = 1;
- }
- // 兼容原函数名
- #define EEPROM_Read IAP_ByteRead
- #define EEPROM_Write IAP_ByteWrite
- // ============================================================================
- // 【修复】参数加载
- // ============================================================================
- void Load_Parameters(void)
- {
- unsigned char buf[24];
- unsigned char i;
- IAP_ByteRead(0x0000, buf, 24);
- // 调试输出原始数据
- UART1_SendString("LOAD:");
- for(i = 0; i < 24; i++)
- {
- UART1_SendByte(' ');
- UART1_SendHex(buf[i]);
- }
- UART1_SendCRLF();
- // 容量
- total_capacity = ((unsigned long)buf[0] << 24) | ((unsigned long)buf[1] << 16) |
- ((unsigned long)buf[2] << 8) | buf[3];
- if(total_capacity == 0xFFFFFFFF || total_capacity == 0)
- {
- total_capacity = DEFAULT_CAPACITY;
- UART1_SendString("CAP DEFAULT");
- UART1_SendCRLF();
- }
- // 剩余容量
- remaining_capacity = ((long)buf[4] << 24) | ((long)buf[5] << 16) |
- ((long)buf[6] << 8) | buf[7];
- if(remaining_capacity < 0 || remaining_capacity > (long)total_capacity)
- {
- remaining_capacity = total_capacity;
- }
- // 校准参数 (buf[16]~buf[23])
- if(buf[22] == 0xAA && buf[23] == 0x55)
- {
- cal_voltage_beiShu = ((unsigned int)buf[16] << 8) | buf[17];
- cal_voltage_lingDian = buf[18];
- cal_current_beiShu = ((unsigned int)buf[19] << 8) | buf[20];
- cal_current_lingDian = buf[21];
- UART1_SendString("CAL OK");
- UART1_SendCRLF();
- }
- else
- {
- UART1_SendString("CAL INVALID");
- UART1_SendCRLF();
- }
- }
- // ============================================================================
- // 【修复】参数保存 - 合并写入避免互相覆盖
- // ============================================================================
- void Save_Parameters(void)
- {
- unsigned char buf[24];
- unsigned char i;
- // 组装所有数据 (0x0000-0x0017)
- buf[0] = (unsigned char)(total_capacity >> 24);
- buf[1] = (unsigned char)(total_capacity >> 16);
- buf[2] = (unsigned char)(total_capacity >> 8);
- buf[3] = (unsigned char)(total_capacity);
- buf[4] = (unsigned char)(remaining_capacity >> 24);
- buf[5] = (unsigned char)(remaining_capacity >> 16);
- buf[6] = (unsigned char)(remaining_capacity >> 8);
- buf[7] = (unsigned char)(remaining_capacity);
- buf[8] = 0xFF; buf[9] = 0xFF;
- buf[10] = 0xFF; buf[11] = 0xFF;
- buf[12] = 0xFF; buf[13] = 0xFF;
- buf[14] = 0xFF; buf[15] = 0xFF;
- buf[16] = (unsigned char)(cal_voltage_beiShu >> 8);
- buf[17] = (unsigned char)(cal_voltage_beiShu);
- buf[18] = cal_voltage_lingDian;
- buf[19] = (unsigned char)(cal_current_beiShu >> 8);
- buf[20] = (unsigned char)(cal_current_beiShu);
- buf[21] = cal_current_lingDian;
- buf[22] = 0xAA;
- buf[23] = 0x55;
- // 调试输出
- UART1_SendString("SAVE:");
- for(i = 0; i < 24; i++)
- {
- UART1_SendByte(' ');
- UART1_SendHex(buf[i]);
- }
- UART1_SendCRLF();
- // 先擦除扇区
- IAP_SectorErase(0x0000);
- Delay_ms(15); // 擦除需要5-10ms,给15ms保险
- // 写入数据
- IAP_ByteWrite(0x0000, buf, 24);
- Delay_ms(5); // 24字节编程约需1ms,给5ms保险
- // 读取验证
- {
- unsigned char readbuf[24];
- unsigned char ok = 1;
- IAP_ByteRead(0x0000, readbuf, 24);
- for(i = 0; i < 24; i++)
- {
- if(buf[i] != readbuf[i])
- {
- ok = 0;
- break;
- }
- }
- UART1_SendString(ok ? "SAVE OK" : "SAVE FAIL");
- UART1_SendCRLF();
- }
- }
- // ============================================================================
- // 延时函数
- // ============================================================================
- void Delay_ms(unsigned int ms)
- {
- unsigned int i, j;
- for(i = 0; i < ms; i++)
- {
- for(j = 0; j < 1200; j++)
- {
- _nop_();
- }
- }
- }
- // ============================================================================
- // 串口中断
- // ============================================================================
- void UART1_ISR(void) interrupt 4
- {
- if(RI)
- {
- RI = 0;
- }
- if(TI)
- {
- TI = 0;
- }
- }
复制代码
|
|