Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+323
View File
@@ -0,0 +1,323 @@
#ifndef _PUBLIC_DEFINE_H_
#define _PUBLIC_DEFINE_H_
/***************************************系统相关-开始*******************************/
/* 系统类型宏 */
#define SYSTEM_TYPE_CCU601E_D 0 /* STM32H5xx */
#define SYSTEM_TYPE_CCU621_M 1 /* GD32H7xx */
#define SYSTEM_TYPE_CCU601_M 2 /* 预留 */
#ifndef SYSTEM_TYPE
#define SYSTEM_TYPE SYSTEM_TYPE_CCU621_M
#endif
/* POS VTK 串口结算功能使能:1=编译 VTK 相关代码;0=完全关闭 */
#ifndef POS_VTK_EN
#define POS_VTK_EN 0
#endif
/***************************************系统相关-结束*******************************/
/***************************************充电枪相关-开始*******************************/
#ifndef GUN_MAX_CNT
#define GUN_MAX_CNT 2 //充电枪最大数量
#endif
#ifndef CAN_PLC_FLAG
#define CAN_PLC_FLAG 0 //欧标CAN转PLC使能标志 0不使能 1使能
#endif
/* 抢连接状态通信使能:1=编译 STM32072 抢连接/DI 状态 CAN 通信相关代码;0=关闭 */
#ifndef GUN_LINK_COMM_EN
#define GUN_LINK_COMM_EN 0
#endif
/***************************************充电枪相关-结束*******************************/
/***************************************调试测试相关-开始*******************************/
#ifndef MY_SHELL_EN
#define MY_SHELL_EN 1 //shell 命令功能使能
#endif
/* printf 与 shell 共用调试串口配置。
* - 取值:0/2/3/4/5/6/7(对应 E_USART_ID
* - 禁用:使用 0xFF(等效于 NULL,不进行对应串口收发配置)
*/
#ifndef DEBUG_SHELL_USART_NULL
#define DEBUG_SHELL_USART_NULL (0xFFU)
#endif
/* Shell 调试串口:不同系统硬件接线不同 */
#ifndef DEBUG_SHELL_USART_ID
#if SYSTEM_TYPE == SYSTEM_TYPE_CCU601E_D
#define DEBUG_SHELL_USART_ID (1U) /* [CCU601E_D] USART1 */
#elif SYSTEM_TYPE == SYSTEM_TYPE_CCU621_M
#define DEBUG_SHELL_USART_ID (2U) /* [CCU621_M] USART2 */
#else
#define DEBUG_SHELL_USART_ID (2U) /* 默认 */
#endif
#endif
/***************************************调试测试相关-结束*******************************/
/***************************************电表通信相关-开始*******************************/
#ifndef METER_MAX_CNT
#define METER_MAX_CNT (4) //电表最大数量
#endif
#ifndef METER_COMM_TYPE_CNT
#define METER_COMM_TYPE_CNT (3) //电表通信数据类型数量 3分别为电量、电压、电流
#endif
#ifndef METER_RECV_TIMEOUT_MS
#define METER_RECV_TIMEOUT_MS (600) //电表数据接收超时时间 600ms
#endif
#ifndef METER_COMM_MAX_CNT
#define METER_COMM_MAX_CNT (2) //单路通信口 电表最大数量 - 一路485口最大有几个电表
#endif
#ifndef METER_TIMEOUT_CNT
#define METER_TIMEOUT_CNT (20*1000) //通讯超时时间 -单位 ms
#endif
#ifndef METER_BAUD_FLAG
#define METER_BAUD_FLAG 1 //电表波特率 0-9600 1-2400
#endif
/***************************************电表通信相关-结束*******************************/
/***************************************UI显示相关-开始*******************************/
#ifndef UI_LANGUAGE_MAX_NUM
#define UI_LANGUAGE_MAX_NUM (3) //UI界面 最大支持语言数量 默认2 中文、英文
#endif
#ifndef UI_COMM_TIME_OUT_TIME
#define UI_COMM_TIME_OUT_TIME (1000 * 30) //UI界面通信超时时间 单位 ms - 65535 最大60秒
#endif
#ifndef UI_FREE_CHANGE_TIME
#define UI_FREE_CHANGE_TIME (60*5) //空闲时待机跳转屏保时间
#endif
/***************************************UI显示相关-结束*******************************/
/***************************************充电模块相关-开始*******************************/
#ifndef MDU_MAX_NUM
#define MDU_MAX_NUM 10 //最大模块数量
#endif
#ifndef MDU_PARA_READ_EN
#define MDU_PARA_READ_EN 1 //模块参数读取使能
#endif
#ifndef MDU_TEMP_READ_EN
#define MDU_TEMP_READ_EN 1 //模块温度读取使能
#endif
#ifndef MDU_UULN_EN
#define MDU_UULN_EN 0 //优优绿能模块使能 0=不编译
#endif
/***************************************充电模块相关-结束*******************************/
/***************************************平台联网相关宏定义-开始*******************************/
#ifndef MAX_BS_NUM
#define MAX_BS_NUM 2 //最大同时连接两个平台
#endif
#ifndef BS_RECV_BUF_LEN
#define BS_RECV_BUF_LEN (1024*3) //接收数据大小
#endif
/* 由于系统后续需要添加多个平台,无法实现同一份代码的兼容,因此使用宏定义预编译的方式 进行平台选择和配置。
配置原则:
(1)平台相关宏至少使能一个平台,使能平台宏跟随平台连接配置,不需要连接的平台必须关闭宏
(2)相关平台宏预编译内容包含此平台的所有变量定义、函数定义、库文件调用等,按照联网框架增加相关内容的预编译效果
(3)平台相关宏相互独立,要确保每个宏的开关不影响其他功能的使用
*/
#ifndef BS_IES_EN
#define BS_IES_EN (0) //积成平台连接使能
#endif
#ifndef BS_GWSDK_EN
#define BS_GWSDK_EN (1) //国网sdk平台连接使能
#endif
#ifndef BS_OCPP_EN
#define BS_OCPP_EN (0) //OCPP平台连接使能
#endif
/* OCPP 时间戳输出时区:0=东八区格式 +08:00;1=零时区(UTC)格式 后缀 Z。GetCurrentTime 为东八区时间 */
#ifndef OCPP_TIMESTAMP_UTC_OUTPUT
#define OCPP_TIMESTAMP_UTC_OUTPUT (1)
#endif
/* OCPP MeterValues充电数据中 是否上送需求电压 需求电流数据 (需求电压需求电流数据为非标准OCPP 1.6规定 部分客户要求上送(白俄客户))*/
#ifndef OCPP_METERVALUES_VOL_CUR_REQUEST_EN
#define OCPP_METERVALUES_VOL_CUR_REQUEST_EN (0) //
#endif
#ifndef LWIP_FTP_UPGRADE_ENABLE
#define LWIP_FTP_UPGRADE_ENABLE (0) //LwIP 网线 FTP 固件升级使能,0=关闭 1=开启
#endif
/* 4G 模块选型:0=EC200A(默认), 1=WH-GM5
根据实际硬件选型修改 FOURG_MODULE_TYPE 即可自动切换:
- EC200A:编译 ec200a_4g.c / ec200a_4g_ftp.c
- WH-GM5:编译 bs_wh_gm5.c
具体对应关系见 4g_module/4G模块AT指令配置功能说明.md */
#ifndef FOURG_MODULE_TYPE
#define FOURG_MODULE_TYPE (1) // 4G模块类型:0=EC200A, 1=WH-GM5
#endif
#if FOURG_MODULE_TYPE == 0
#ifndef EC200A_4G_EN
#define EC200A_4G_EN (1) // EC200A 4G模块使能
#endif
#ifndef WH_GM5_EN
#define WH_GM5_EN (0) // WH-GM5 4G模块使能
#endif
#elif FOURG_MODULE_TYPE == 1
#ifndef EC200A_4G_EN
#define EC200A_4G_EN (0)
#endif
#ifndef WH_GM5_EN
#define WH_GM5_EN (1) // WH-GM5 4G模块使能
#endif
#else
#error "FOURG_MODULE_TYPE invalid: must be 0 (EC200A) or 1 (WH-GM5)"
#endif
/* 平台 TLS 加密使能:1=编译基于 mbedtls 的 TLS 封装及 wss 支持;0=完全关闭,走纯明文 ws */
#ifndef BS_TLS_MBEDTLS_EN
#define BS_TLS_MBEDTLS_EN (0)
#endif
/***************************************平台联网相关宏定义-结束*******************************/
/***************************************故障信息相关-开始*******************************/
#ifndef CURR_FAULT_MAX_CNT
#define CURR_FAULT_MAX_CNT 15 //当前故障最大数量
#endif
#ifndef CURR_ALARM_MAX_CNT
#define CURR_ALARM_MAX_CNT 5 //当前告警最大数量
#endif
#ifndef HIS_FAULT_MAX_CNT
#define HIS_FAULT_MAX_CNT 300 //历史告警最大数量
#endif
#ifndef FAULT_GET_MAG_MAX_LEN
#define FAULT_GET_MAG_MAX_LEN (64) //故障信息获取最大长度
#endif
#ifndef FAULT_GUN_NOLINK_RES_TIME
#define FAULT_GUN_NOLINK_RES_TIME (5*60) //故障拔枪恢复、充电完成恢复时间 单位秒
#endif
#ifndef FUALT_INFO_PRINT_TIME
#define FUALT_INFO_PRINT_TIME (60*5) //故障信息打印周期 单位 秒
#endif
/***************************************故障信息相关-结束*******************************/
/***************************************flash存储相关-开始*******************************/
#ifndef RECORD_ZERO_SAVE
#define RECORD_ZERO_SAVE 0x7FFF //标明充电记录/告警记录为0,未存储
#endif
#ifndef RECORD_HEADER
#define RECORD_HEADER 0x55 //每条记录头字节
#endif
#ifndef FATFS_EN
#define FATFS_EN 0 // FATFS文件系统模块使能,0=不编译 1=编译
#endif
/* TF/SD 卡:diskio 驱动 + app_sdmmc / sd_cfg 等;0=整段不编译,节省 Flash/RAM */
#ifndef SD_CARD_EN
#define SD_CARD_EN 0
#endif
/* NAND Flash (外部FMC NAND) 使能:0=不编译相关驱动/初始化/测试;1=编译 */
#ifndef NAND_FLASH_EN
#define NAND_FLASH_EN 0
#endif
/* FATFS 子功能开关(原位于 BSP/app_fatfs/fatfs_features.h */
#ifndef FATFS_ENABLE_LOG
#define FATFS_ENABLE_LOG 1
#endif
#ifndef FATFS_ENABLE_CARD
#define FATFS_ENABLE_CARD 0
#endif
#ifndef FATFS_ENABLE_FAULT
#define FATFS_ENABLE_FAULT 0
#endif
#ifndef FATFS_ENABLE_ORDER
#define FATFS_ENABLE_ORDER 0
#endif
/***************************************flash存储相关-结束*******************************/
/***************************************其他功能宏定义-开始*******************************/
#ifndef TASK_RUN_PRINT_TIME
#define TASK_RUN_PRINT_TIME (60*10) //任务运行打印时间 单位秒-- 用于周期打印任务信息,证明任务运行正常
#endif
#ifndef HTTP_DEBUG_EN
#define HTTP_DEBUG_EN 0 //HTTP调试界面使能,默认使能,当不使能时HTTP相关的代码都不被编译
#endif
#ifndef TCP_DEBUG_EN
#define TCP_DEBUG_EN 1 //TCP调试服务器使能
#endif
#if TCP_DEBUG_EN
#define TCP_DEBUG_PORT 9699 //TCP服务器端口号
#define TCP_DEBUG_MAX_CLIENTS 1 //最大客户端连接数(仅支持一个客户端)
#endif
#if HTTP_DEBUG_EN
#define HTTP_DEBUG_SYSTEM_INFO (1) //系统信息显示
#define HTTP_DEBUG_SYSTEM_MONITOR (0) //线程信息监控
#define HTTP_DEBUG_CHARGING_INFO (1) //充电信息显示控制
#define HTTP_DEBUG_PARA_CFG (1) //参数配置
#define HTTP_DEBUG_FIRMWARE_UP (0) //固件升级功能
#define HTTP_DEBUG_FILE_DOWNLOAD (0) //文件交互(已禁用)
#endif
#ifndef PAPRA_SETTING_EN
#define PAPRA_SETTING_EN 0 // 网络调试助手参数读写/充电启停,0=不编译 1=编译
#endif
/* 蓝牙调试(FC41D,可选):1=编译 BLE 链路代码;0=整文件不编入有效代码,节省 Flash/RAM
* - 依赖 TCP_DEBUG_EN=1(协议/任务与 TCP 调试共用 tcp_server
* - 运行时:副板 DIP1 选物理链路 — 0=以太网 TCP 上位机,1=蓝牙上位机(仅宏为 1 时有效)
* - 无 FC41D 或未贴模组:保持 BLE_DEBUG_EN=0,拨码仅影响 TCP 模式下的预留行为 */
#ifndef BLE_DEBUG_EN
#define BLE_DEBUG_EN 1
#endif
#if (BLE_DEBUG_EN != 0) && (TCP_DEBUG_EN == 0)
#error BLE_DEBUG_EN requires TCP_DEBUG_EN
#endif
#if TCP_DEBUG_EN
#define TCP_DEBUG_PORT 9699 //TCP服务器端口号
#define TCP_DEBUG_MAX_CLIENTS 1 //最大客户端连接数(仅支持一个客户端)
#define TCP_DEBUG_SEND_INTERVAL_MS 5000 //发送hello消息间隔(毫秒)
#endif
/***************************************其他功能宏定义-结束*******************************/
#endif
+389
View File
@@ -0,0 +1,389 @@
#include "publicdata/publicdata.h"
#include "app_init/app_init.h"
#include <string.h>
/**
* ************************************************************************
* @brief - 全局应用函数接口文件--用于汇总所有公共函数
*
* @author jiankalka
* @date 2025-09-12
* ************************************************************************
*/
const char *success = "success";
const char *failure = "failure";
#if 1 //数据校验函数
//CRC校验驱动表
const U8_T aucCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};
const U8_T aucCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};
//计算累加和校验
U16_T u16_crc_checksum(U8_T *p, U16_T u16_len)
{
U16_T i;
U16_T u16_sum = 0;
for (i=0; i<u16_len; i++)
u16_sum += *(p+i);
return u16_sum;
}
//modbus crc16校验函数
U16_T u16_modbus_crc16( U8_T * pucFrame, U16_T usLen )
{
U8_T ucCRCHi = 0xFF;
U8_T ucCRCLo = 0xFF;
int iIndex;
while( usLen-- )
{
iIndex = ucCRCLo ^ *( pucFrame++ );
ucCRCLo = ( U8_T )( ucCRCHi ^ aucCRCHi[iIndex] );
ucCRCHi = aucCRCLo[iIndex];
}
return ( U16_T )( ucCRCHi << 8 | ucCRCLo );
}
U8_T u8_calculate_bcc(U8_T *pu8_data, U16_T u16_len) //BCC异或校验
{
U32_T i;
U8_T u8_ret = 0;
for (i=0; i<u16_len; i++)
u8_ret ^= *pu8_data++;
return u8_ret;
}
#endif
#if 1 //时间戳、时间数据计算函数
/**
* @brief 获取系统运行总毫秒数(从启动开始)
* @return uint64_t 当前毫秒数(自动处理32位tick溢出)
*/
uint64_t u64_get_current_millis(void) {
static uint32_t overflow_count = 0;
static TickType_t last_tick = 0;
// 进入临界区保护静态变量
taskENTER_CRITICAL();
TickType_t current_tick = xTaskGetTickCount();
// 检测tick计数器溢出(0xFFFFFFFF → 0
if (current_tick < last_tick) {
overflow_count++;
}
last_tick = current_tick;
taskEXIT_CRITICAL();
// 计算总毫秒数 = (溢出次数 * 周期毫秒) + 当前tick转换的毫秒
const uint64_t period_ms = ((uint64_t)0xFFFFFFFF * 1000) / configTICK_RATE_HZ;
uint64_t current_ms = (uint64_t)current_tick * 1000 / configTICK_RATE_HZ;
return (overflow_count * period_ms) + current_ms;
}
/**
* @brief 计算当前时间与上次时间的毫秒数差值(自动处理64位溢出)
* @param last_millis 上次记录的时间戳(毫秒)
* @return uint64_t 距离上次时间的毫秒数差值(总是正数)
*/
uint64_t u64_safe_millis_since(uint64_t last_millis) {
uint64_t current_millis = u64_get_current_millis();
// 处理毫秒计数器自增特性(时间不会回退)
if (current_millis >= last_millis) {
return current_millis - last_millis;
} else {
// 发生错误时返回0(如传入未来时间或时间重置)
return 0;
}
}
/**
* @brief 获取系统运行总秒数(从启动开始)
* @return uint32_t 当前秒数(自动处理32位tick溢出)
*/
uint32_t get_current_seconds(void) {
return (uint32_t)(u64_get_current_millis() / 1000);
}
/**
* @brief 计算当前时间与上次时间的秒数差值(无符号,自动处理溢出)
* @param last_sec 上次记录的时间戳(秒)
* @return uint32_t 距离上次时间的秒数差值(总是正数)
*/
uint32_t u32_safe_seconds_since(uint32_t last_sec) {
// 获取当前秒数(基于系统tick,含溢出处理)
uint32_t current_sec = get_current_seconds(); // 使用前文定义的get_current_seconds()
// 计算差值(自动处理32位溢出)
return (current_sec >= last_sec) ? (current_sec - last_sec) :
(0xFFFFFFFF - last_sec + current_sec + 1);
}
#endif
#if 1 //数据进制转换函数-BCD转换
// 十进制转BCD
uint8_t dec_to_bcd(uint8_t dec) {
return ((dec / 10) << 4) | (dec % 10);
}
// BCD转十进制
uint8_t bcd_to_dec(uint8_t bcd) {
return ((bcd >> 4) * 10) + (bcd & 0x0F);
}
/**
* @brief 将BCD码转换为ASCII字符串
* @param bcd_data BCD码数据数组
* @param bcd_len BCD数据长度(字节数)
* @param ascii_str 输出ASCII字符串缓冲区
* @param ascii_buf_len 输出缓冲区大小 要大于bcd_len*2+1
* @return 成功返回0,失败返回-1
*/
int bcd_to_ascii(const U8_T *bcd_data, U8_T bcd_len,
char *ascii_str, U8_T ascii_buf_len)
{
if (bcd_data == NULL || ascii_str == NULL) {
return -1;
}
// 确保缓冲区足够大(每个BCD字节可以转换为2个ASCII字符)
if (ascii_buf_len < bcd_len * 2 + 1) {
return -1;
}
int i, j = 0;
for (i = 0; i < bcd_len; i++) {
// 提取高4位和低4位BCD码
U8_T high_nibble = (bcd_data[i] >> 4) & 0x0F;
U8_T low_nibble = bcd_data[i] & 0x0F;
// 转换为ASCII字符
if (high_nibble < 10) {
ascii_str[j++] = high_nibble + '0'; // 数字0-9
} else if (high_nibble == 0x0A) {
ascii_str[j++] = 'A'; // 可选的十六进制表示
} else if (high_nibble == 0x0B) {
ascii_str[j++] = 'B';
} else if (high_nibble == 0x0C) {
ascii_str[j++] = 'C';
} else if (high_nibble == 0x0D) {
ascii_str[j++] = 'D';
} else if (high_nibble == 0x0E) {
ascii_str[j++] = 'E';
} else if (high_nibble == 0x0F) {
ascii_str[j++] = 'F';
}
if (low_nibble < 10) {
ascii_str[j++] = low_nibble + '0';
} else if (low_nibble == 0x0A) {
ascii_str[j++] = 'A';
} else if (low_nibble == 0x0B) {
ascii_str[j++] = 'B';
} else if (low_nibble == 0x0C) {
ascii_str[j++] = 'C';
} else if (low_nibble == 0x0D) {
ascii_str[j++] = 'D';
} else if (low_nibble == 0x0E) {
ascii_str[j++] = 'E';
} else if (low_nibble == 0x0F) {
ascii_str[j++] = 'F';
}
}
ascii_str[j] = '\0'; // 字符串结束符
return 0;
}
#endif
#if 1 //系统重启
void v_sys_reboot()
{
printf("sys reboot\r\n");
mSleep(2000);
//重启
__set_FAULTMASK(1); //关闭所有中断
NVIC_SystemReset(); //复位函数
}
#endif
#if 1 //Base64编码解码函数
/**
* @brief BASE64编码函数
* @param input 二进制数据输入
* @param input_len 输入数据长度
* @param output 输出缓冲区(Base64字符串)
* @param output_size 输出缓冲区大小
* @return 编码后的字符串长度,-1表示错误
*/
int base64_encode(const uint8_t *input, uint32_t input_len,
char *output, uint32_t output_size)
{
static const char base64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (input == NULL || output == NULL || output_size == 0) {
return -1;
}
uint32_t i = 0, j = 0;
uint32_t output_len = ((input_len + 2) / 3) * 4; /* Base64编码后的长度 */
if (output_len + 1 > output_size) {
return -1;
}
while (i < input_len) {
uint32_t octet_a = i < input_len ? input[i++] : 0;
uint32_t octet_b = i < input_len ? input[i++] : 0;
uint32_t octet_c = i < input_len ? input[i++] : 0;
uint32_t triple = (octet_a << 16) | (octet_b << 8) | octet_c;
output[j++] = base64_table[(triple >> 18) & 0x3F];
output[j++] = base64_table[(triple >> 12) & 0x3F];
output[j++] = base64_table[(triple >> 6) & 0x3F];
output[j++] = base64_table[triple & 0x3F];
}
/* 添加填充字符 */
if (input_len % 3 == 1) {
output[j - 2] = '=';
output[j - 1] = '=';
} else if (input_len % 3 == 2) {
output[j - 1] = '=';
}
output[j] = '\0';
return j;
}
/**
* @brief BASE64解码函数
* @param input Base64编码字符串输入
* @param output 输出缓冲区(二进制数据)
* @param output_size 输出缓冲区大小
* @return 解码后的数据长度,-1表示错误
*/
int base64_decode(const char *input, uint8_t *output, uint32_t output_size)
{
static const int8_t base64_reverse_table[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
};
if (input == NULL || output == NULL || output_size == 0) {
return -1;
}
uint32_t input_len = strlen(input);
uint32_t i = 0, j = 0;
uint32_t output_len = (input_len * 3) / 4; /* 最大可能的输出长度 */
if (output_len > output_size) {
return -1;
}
/* 跳过末尾的填充字符 */
while (input_len > 0 && input[input_len - 1] == '=') {
input_len--;
}
/* 解码过程 */
while (i < input_len) {
int8_t sextet_a = (i < input_len) ? base64_reverse_table[(uint8_t)input[i++]] : -1;
int8_t sextet_b = (i < input_len) ? base64_reverse_table[(uint8_t)input[i++]] : -1;
int8_t sextet_c = (i < input_len) ? base64_reverse_table[(uint8_t)input[i++]] : -1;
int8_t sextet_d = (i < input_len) ? base64_reverse_table[(uint8_t)input[i++]] : -1;
if (sextet_a == -1 || sextet_b == -1) {
return -1; /* 无效的Base64字符 */
}
uint32_t triple = (sextet_a << 18) | (sextet_b << 12);
if (sextet_c != -1) {
triple |= sextet_c << 6;
}
if (sextet_d != -1) {
triple |= sextet_d;
}
output[j++] = (triple >> 16) & 0xFF;
if (sextet_c != -1) {
output[j++] = (triple >> 8) & 0xFF;
}
if (sextet_d != -1) {
output[j++] = triple & 0xFF;
}
}
return j;
}
#endif /* Base64编码解码函数 */
+549
View File
@@ -0,0 +1,549 @@
#include "publicdata/publicdata.h"
#include "flash_external_data.h"
#include "app_init/task_lock.h"
#include <string.h>
#include <stdio.h>
SHARE_DATA_T g_t_share_data; // 全局共享数据定义
static SemaphoreHandle_t g_mut_share_data = NULL; // publicdata独立互斥锁
/* 欧标CAN转PLC 运行时使能:u8_gun_type[gun_no]==0 为欧标使能返回1,否则国标返回0 */
U8_T u8_can_plc_enabled(U8_T gun_no)
{
if (gun_no >= GUN_MAX_CNT)
return 0;
return (CAN_PLC_FLAG && g_t_share_data.t_sys_fix_cfg.u8_gun_type[gun_no] == 0) ? 1 : 0;
}
// 设备型号(字符串常量)
const U8_T Device_Model[] = "IES-M";
const U8_T Software_Version[] = "M_01.00.01"; //主程序版本号用于現場驗收
const U8_T Hardware_Version[] = "CCU621M" ; //
const U8_T Mcu_model[] = "STM32H563IG";
const U8_T Parameter_Version[] = "P_00.00.01" ; //参数版本号
/***************************************
* 函数说明: 线程锁 初始化
*
*
*
****************************************/
U8_T u8_osMutexNew()
{
return u8_task_lock_handle_ctrl(&g_mut_share_data, TASK_LOCK_OP_INIT);
}
/***************************************
* 函数说明: 线程锁 上锁
*
*
*
****************************************/
U8_T u8_mutex_Lock(void)
{
return u8_task_lock_handle_ctrl(&g_mut_share_data, TASK_LOCK_OP_TAKE);
}
/***************************************
* 函数说明: 线程锁 释放锁
*
*
*
****************************************/
void v_mutex_unlock()
{
(void)u8_task_lock_handle_ctrl(&g_mut_share_data, TASK_LOCK_OP_GIVE);
}
/*************************************************************
函数名称: v_fetch_save_var_cfg_data
函数功能: 保存可变配置数据到dataflash,保存三份,具体格式见文件:DATAFLASH空间地址定义
头8字节:魔数+CFG_DATA_VERSION_H/L+长度+CRC
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_flash_save_var_cfg_data(void)
{
U8_T u8_head[8];
U16_T u16_len, u16_crc, i, j;
U32_T u32_addr[3] = { DATAFLASH_VAR_CFG_DATA1_ADDR, DATAFLASH_VAR_CFG_DATA2_ADDR, DATAFLASH_VAR_CFG_DATA3_ADDR };
u16_len = sizeof(SYS_VAR_CFG_T);
u8_head[0] = 0x55;
u8_head[1] = 0xAA;
u8_head[2] = CFG_DATA_VERSION_H;
u8_head[3] = CFG_DATA_VERSION_L;
u8_head[4] = (U8_T)(u16_len >> 8);
u8_head[5] = (U8_T)u16_len;
if(u8_mutex_Lock() == 0) //上锁
return;
for(i=0; i<3; i++)
s32_flash_dataflash_erase_sector(u32_addr[i]); //清空扇区
u16_crc = u16_crc_checksum((U8_T *)(&(g_t_share_data.t_sys_var_cfg)), u16_len);
u8_head[6] = (U8_T)(u16_crc >> 8);
u8_head[7] = (U8_T)u16_crc;
for (i=0; i<3; i++) //写3份数据
{
for (j=0; j<3; j++) //如果写失败,则重试3次
{
if ((s32_flash_dataflash_write(u32_addr[i], u8_head, 8) != 0)
|| (s32_flash_dataflash_write(u32_addr[i]+8, (U8_T *)(&(g_t_share_data.t_sys_var_cfg)), u16_len) != 0))
{
continue;
}
else
{
break;
}
}
}
v_mutex_unlock(); //解锁
}
/*************************************************************
函数名称: s32_fetch_read_var_cfg_data
函数功能: 从dataflash读取可变配置数据,从三份数据中读取正确的数据,并用正确的数据重写不正确的数据
读取时检查 CFG_DATA_VERSION_H/L 版本号
输入参数: 无
输出参数: 无
返回值 :读取成功则返回0,失败返回-1
**************************************************************/
S32_T s32_flash_read_var_cfg_data(void)
{
U8_T u8_head[8];
U16_T u16_len, i, j, k;
U32_T u32_addr[3] = { DATAFLASH_VAR_CFG_DATA1_ADDR, DATAFLASH_VAR_CFG_DATA2_ADDR, DATAFLASH_VAR_CFG_DATA3_ADDR };
u16_len = sizeof(SYS_VAR_CFG_T);
if(u8_mutex_Lock() == 0) //上锁
return 0;
for (i=0; i<3; i++)
{
if ((s32_flash_dataflash_read(u32_addr[i], u8_head, 8) == 0)
&& (s32_flash_dataflash_read(u32_addr[i]+8, (U8_T *)(&(g_t_share_data.t_sys_var_cfg)), u16_len) == 0))
{
if ((u8_head[0] == 0x55)
&& (u8_head[1] == 0xAA)
&& (u8_head[2] == CFG_DATA_VERSION_H)
&& (u8_head[3] == CFG_DATA_VERSION_L)
&& (u16_len == ((u8_head[4]<<8) | u8_head[5]))
&& (((u8_head[6]<<8) | u8_head[7]) == u16_crc_checksum((U8_T *)(&(g_t_share_data.t_sys_var_cfg)), u16_len)))
{
break;
}
}
}
if (i >= 3) //三份配置数据都没有读取成功,则退出
{
v_mutex_unlock(); //解锁 //释放互斥锁
return -1;
}
else if (i == 0) //第一份就读取成功,则退出
{
v_mutex_unlock(); //解锁 //释放互斥锁
return 0;
}
//程序跑到这里,说明己经读取成功,且不是第一份读取成功,需要对读取失败的数据重写(先擦除再写)
for (j=0; j<i; j++)
{
s32_flash_dataflash_erase_sector(u32_addr[j]); //重写前先清空该扇区
for (k=0; k<3; k++) //如果写失败,则重试3次
{
if ((s32_flash_dataflash_write(u32_addr[j], u8_head, 8) != 0)
|| (s32_flash_dataflash_write(u32_addr[j]+8, (U8_T *)(&(g_t_share_data.t_sys_var_cfg)), u16_len) != 0))
{
continue;
}
else
{
break;
}
}
}
v_mutex_unlock(); //解锁 //释放互斥锁
return 0;
}
/*************************************************************
函数名称: v_fetch_save_fix_cfg_data
函数功能: 保存固定配置数据到dataflash,保存三份,具体格式见文件:DATAFLASH空间地址定义
头8字节:魔数+CFG_DATA_VERSION_H/L+长度+CRC
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_flash_save_fix_cfg_data(void)
{
U8_T u8_head[8];
U16_T u16_len, u16_crc, i, j;
U32_T u32_addr[3] = { DATAFLASH_FIX_CFG_DATA1_ADDR, DATAFLASH_FIX_CFG_DATA2_ADDR, DATAFLASH_FIX_CFG_DATA3_ADDR };
u16_len = sizeof(SYS_FIX_CFG_T);
u8_head[0] = 0x55;
u8_head[1] = 0xAA;
u8_head[2] = CFG_DATA_VERSION_H;
u8_head[3] = CFG_DATA_VERSION_L;
u8_head[4] = (U8_T)(u16_len >> 8);
u8_head[5] = (U8_T)u16_len;
if(u8_mutex_Lock() == 0) //上锁
return;
for(i=0; i<3; i++)
s32_flash_dataflash_erase_sector(u32_addr[i]); //清空扇区
u16_crc = u16_crc_checksum((U8_T *)(&(g_t_share_data.t_sys_fix_cfg)), u16_len);
u8_head[6] = (U8_T)(u16_crc >> 8);
u8_head[7] = (U8_T)u16_crc;
for (i=0; i<3; i++) //写3份数据
{
for (j=0; j<3; j++) //如果写失败,则重试3次
{
if ((s32_flash_dataflash_write(u32_addr[i], u8_head, 8) != 0)
|| (s32_flash_dataflash_write(u32_addr[i]+8, (U8_T *)(&(g_t_share_data.t_sys_fix_cfg)), u16_len) != 0))
{
continue;
}
else
{
break;
}
}
}
v_mutex_unlock(); //解锁 //释放互斥锁
}
/*************************************************************
函数名称: s32_fetch_read_fix_cfg_data
函数功能: 从dataflash读取固定配置数据,从三份数据中读取正确的数据,并用正确的数据重写不正确的数据
读取时检查 CFG_DATA_VERSION_H/L 版本号
输入参数: 无
输出参数: 无
返回值 :读取成功则返回0,失败返回-1
**************************************************************/
S32_T s32_flash_read_fix_cfg_data(void)
{
U8_T u8_head[8];
U16_T u16_len, i, j, k;
U32_T u32_addr[3] = { DATAFLASH_FIX_CFG_DATA1_ADDR, DATAFLASH_FIX_CFG_DATA2_ADDR, DATAFLASH_FIX_CFG_DATA3_ADDR };
u16_len = sizeof(SYS_FIX_CFG_T);
if(u8_mutex_Lock() == 0) //上锁
return 0;
for (i=0; i<3; i++)
{
if ((s32_flash_dataflash_read(u32_addr[i], u8_head, 8) == 0)
&& (s32_flash_dataflash_read(u32_addr[i]+8, (U8_T *)(&(g_t_share_data.t_sys_fix_cfg)), u16_len) == 0))
{
if ((u8_head[0] == 0x55)
&& (u8_head[1] == 0xAA)
&& (u8_head[2] == CFG_DATA_VERSION_H)
&& (u8_head[3] == CFG_DATA_VERSION_L)
&& (u16_len == ((u8_head[4]<<8) | u8_head[5]))
&& (((u8_head[6]<<8) | u8_head[7]) == u16_crc_checksum((U8_T *)(&(g_t_share_data.t_sys_fix_cfg)), u16_len)))
{
break;
}
}
}
if (i >= 3) //三份配置数据都没有读取成功,则退出
{
v_mutex_unlock(); //解锁 //释放互斥锁
return -1;
}
else if (i == 0) //第一份就读取成功,则退出
{
v_mutex_unlock(); //解锁 //释放互斥锁
return 0;
}
//程序跑到这里,说明己经读取成功,且不是第一份读取成功,需要对读取失败的数据重写(先擦除再写)
for (j=0; j<i; j++)
{
s32_flash_dataflash_erase_sector(u32_addr[j]); //重写前先清空该扇区
for (k=0; k<3; k++) //如果写失败,则重试3次
{
if ((s32_flash_dataflash_write(u32_addr[j], u8_head, 8) != 0)
|| (s32_flash_dataflash_write(u32_addr[j]+8, (U8_T *)(&(g_t_share_data.t_sys_fix_cfg)), u16_len) != 0))
{
continue;
}
else
{
break;
}
}
}
v_mutex_unlock(); //解锁 //释放互斥锁
return 0;
}
/*************************************************************
函数名称: v_fetch_save_cfg_data
函数功能: 保存配置数据到dataflash,保存三份,具体格式见文件:DATAFLASH空间地址定义
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_flash_save_cfg_data(void)
{
v_flash_save_fix_cfg_data();
v_flash_save_var_cfg_data();
}
/*************************************************************
函数名称: v_public_fix_cfg_data_restore
函数功能: 恢复默认数据,将设置参数恢复到默认值
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_public_fix_cfg_data_restore(void)
{
SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg;
if(u8_mutex_Lock() == 0) //上锁
return;
memset(t_sys_fix_cfg, 0, sizeof(SYS_FIX_CFG_T));
//充电桩资产参数配置
t_sys_fix_cfg->u16_pile_power_limit = 0; //整桩限制功率,(0表示不限制)
strcpy((char *)t_sys_fix_cfg->u8_pwd, "880180"); //维护密码,字符串类型
t_sys_fix_cfg->u8_gunCnt = 2;
t_sys_fix_cfg->u8_terminal[0] = 1; //终端地址
t_sys_fix_cfg->u8_terminal[1] = 2; //终端地址
t_sys_fix_cfg->e_ledType = E_LED_TYPE_1; //灯板类型
t_sys_fix_cfg->e_timeZone = TIMEZONE_UTC_PLUS_8; //系统时区 0-25 默认20 东八区
t_sys_fix_cfg->u8_gun_type[0] = (CAN_PLC_FLAG ? 0 : 1); /* 欧标仅CAN_PLC使能时有效 */ //枪类型 0欧标枪 1国标枪
t_sys_fix_cfg->u8_gun_type[1] = (CAN_PLC_FLAG ? 0 : 1);
t_sys_fix_cfg->u8_gun_power_limit[0] = 0; //枪充电功率限制 0表示不限制 单位kW
t_sys_fix_cfg->u8_gun_power_limit[1] = 0;
//充电桩保护参数设置
t_sys_fix_cfg->u8_threshold_gunTemp = 90; //枪温阈值 90
t_sys_fix_cfg->u8_soc_limit = 100; //SOC上限100
t_sys_fix_cfg->u16_ratePow = 120; //额定功率
t_sys_fix_cfg->u16_min_volt = 200*10; //电压范围-下值
t_sys_fix_cfg->u16_max_volt = 1000*10; //模块/充电机的调压上值/电压上限
t_sys_fix_cfg->u16_max_cur = 250*10; //最大电流
t_sys_fix_cfg->u16_trickle_limit = 10* 10; //涓流停机阈值 10A
//整流模块参数 --
t_sys_fix_cfg->u8_mdu_num = 6; //充电模块数量
t_sys_fix_cfg->u8_MduType = 0; //模块类型 暂未使用
t_sys_fix_cfg->u8_mduTemp_flag = 1; //模块温度获取使能
t_sys_fix_cfg->u8_mdu_rated_pow = 40; //模块额定功率 kw
t_sys_fix_cfg->u16_mdu_max_vol = 1000*10; //模块最大电压 0.1V
t_sys_fix_cfg->u16_mdu_max_cur = 130*10; //模块最大电流 0.1A
//网络参数配置
const U8_T u8_eth_ip[4] = {192,168,1,100};
memcpy(t_sys_fix_cfg->s_net_cfg.u8_eth_ip , u8_eth_ip , 4); //本地IP地址, 默认192.168.1.140
const U8_T u8_eth_mask[4] = {255,255,255,0};
memcpy(t_sys_fix_cfg->s_net_cfg.u8_eth_mask , u8_eth_mask , 4); //地址掩码, 默认255.255.255.0
const U8_T u8_eth_gate[4] = {192,168,1,1};
memcpy(t_sys_fix_cfg->s_net_cfg.u8_eth_gate , u8_eth_gate , 4); //网关, 默认192.168.1.1
const U8_T u8_eth_mac[6] = {0x00,0x0E,0xEA,0x03,0xA0,0x01};
memcpy(t_sys_fix_cfg->s_net_cfg.u8_eth_mac , u8_eth_mac , 6); //MAC地址,默认00:0E:EA:03:A5:01 前3字节:组织唯一标识符​代表设备厂商(00:0E:EA->属于ASUSTek(华硕))。后3字节:设备标识符厂商自主分配,确保同一厂商的产品中不重复。
const U8_T u8_platA_IP[] = "39.104.96.26,8897"; //注意 域名和ip之间使用,分隔 例如39.104.96.26,8897
memcpy(t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name , u8_platA_IP , strlen((char *)u8_platA_IP)); //服务器A域名(IP+端口号) - 最大字符50字节
const U8_T u8_platB_IP[] = "121.89.205.240,41004"; //注意 域名和ip之间使用,分隔 例如39.104.96.26,8897
memcpy(t_sys_fix_cfg->s_net_cfg.u8_serverB_domain_name , u8_platB_IP , strlen((char *)u8_platB_IP)); //服务器B域名(IP+端口号) - 最大字符50字节
const U8_T u8_platA_pileNum[] = "2025090200010001";//"12345678"; //
memcpy(t_sys_fix_cfg->s_net_cfg.u8_platA_pileNum , u8_platA_pileNum , strlen((char *)u8_platA_pileNum)); //平台1桩编号
const U8_T u8_platB_pileNum[] = "12345678"; //
memcpy(t_sys_fix_cfg->s_net_cfg.u8_platB_pileNum , u8_platB_pileNum , strlen((char *)u8_platB_pileNum)); //平台2桩编号
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_program_type = 0; //程序类型 0社会 1sdk
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_netA_type = 0; //联网方式 0:GPRS 1:以太网
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_netB_type = 0; //联网方式 0:GPRS 1:以太网
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platA_en = 1; //平台1使能 默认第三方平台 0不使能 1使能
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_en = 0; //平台2使能 默认积成平台 0不使能 1使能
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platA_type = 0; //平台1类型 0积成 云快充 1...
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_type = 0; //平台1类型 默认积成平台 --非SDK平台时有效,SDK平台时 仅连接SDK
t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_sim_anp_type = 0; //SIM卡 APN类型- 0公网卡 1国网移动 2国网联通 3国网电信
//电表数据初始
t_sys_fix_cfg->s_memter.u8_meter_num = 2;
t_sys_fix_cfg->s_memter.s_data[0].u8_inGun = 1; //归属枪号 0无效,不存在; 1A枪 2B枪
t_sys_fix_cfg->s_memter.s_data[0].u8_highPrec = 1; //是否支持高精度 0 不支持 1支持
t_sys_fix_cfg->s_memter.s_data[0].u8_isAC = 0; //是否为交流电表 0直流表 1交流表
memset(&t_sys_fix_cfg->s_memter.s_data[0].u8_meterAddr[0] , 0xAA, 6); //电表地址
t_sys_fix_cfg->s_memter.s_data[1].u8_inGun = 2; //归属枪号 0无效,不存在; 1A枪 2B枪
t_sys_fix_cfg->s_memter.s_data[1].u8_highPrec = 1; //是否支持高精度 0 不支持 1支持
t_sys_fix_cfg->s_memter.s_data[1].u8_isAC = 0; //是否为交流电表 0直流表 1交流表
memset(&t_sys_fix_cfg->s_memter.s_data[1].u8_meterAddr[0] , 0xAA, 6); //电表地址
t_sys_fix_cfg->u_enable.bit_enable.bit_doorEnable = 1; //门禁使能
t_sys_fix_cfg->u_enable.bit_enable.bit_gunLockEna = 1; // 枪锁使能
t_sys_fix_cfg->u_enable.bit_enable.bit_gunLockNeg = 0; // 枪锁信号取反
t_sys_fix_cfg->u_enable.bit_enable.bit_AcContactEna = 0; // 交流接触器使能
t_sys_fix_cfg->u_enable.bit_enable.bit_gunHoming = 0; // 枪归位信号有无
t_sys_fix_cfg->u_enable.bit_enable.bit_GBEnable = 0; // 国标使能(0:兼容 1:国标)
t_sys_fix_cfg->u_enable.bit_enable.bit_LcdEnable = 1; // 液晶使能,0不使能,1使能
t_sys_fix_cfg->u_enable.bit_enable.bit_auxpower = 0; // 辅助电压返回状态使能
t_sys_fix_cfg->u_enable.bit_enable.bit_reliefen = 1; // 泄放使能
t_sys_fix_cfg->u_enable.bit_enable.bit_YeLenEn = 0; // 液冷通讯使能
t_sys_fix_cfg->u_enable.bit_enable.bit_ABcommEn = 0; // 主副班通讯使能 0 1使能且为1枪 2使能且为2枪
t_sys_fix_cfg->u_enable.bit_enable.bit_ScreenSaverEn = 1; // UI界面屏保使能 0不使能 1使能 2使能轮播
t_sys_fix_cfg->u_enable.bit_enable.bit_PlugEn = 1; //即插即充使能
t_sys_fix_cfg->u_enable.bit_enable.bit_uiEnglishEn = 0; //UI界面 英语使能 0 中文 1英文
t_sys_fix_cfg->u_enable.bit_enable.bit_dcBusEn = 0; // 直流母联接触器使能 0 不使能 1使能
t_sys_fix_cfg->u_enable.bit_enable.bit_gunFanEn = 0; // 枪风扇使能 0 不使能 1使能
t_sys_fix_cfg->u_enable.bit_enable.bit_mduzeropowEn = 0;
t_sys_fix_cfg->u_enable.bit_enable.bit_ledGbEn = 0; //国标指示灯使能 0 待机黄,充电绿,故障红;1 待机绿,充电红,故障黄
v_mutex_unlock();
v_flash_save_fix_cfg_data(); //保存参数到DATAFLASH
}
/*************************************************************
函数名称: v_public_var_cfg_data_restore
函数功能: 恢复默认数据,将设置参数恢复到默认值
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_public_var_cfg_data_restore(void)
{
U8_T i;
if(u8_mutex_Lock() == 0) //上锁
return ;
memset(&(g_t_share_data.t_sys_var_cfg), 0, sizeof(g_t_share_data.t_sys_var_cfg));
//计费模型
g_t_share_data.t_sys_var_cfg.s_fee_model.u8_feeCnt = FEE_MODEL_CNT;
g_t_share_data.t_sys_var_cfg.s_fee_model.s_fee_data[0].u32_rate = 1; //电费
g_t_share_data.t_sys_var_cfg.s_fee_model.s_fee_data[0].u32_sevice = 1; //服务费
for(i=0;i<FEE_MODEL_CNT;i++)
{
g_t_share_data.t_sys_var_cfg.s_fee_model.u8_fee_type[i] = 1; //费率类型 第一个费率类型
}
memcpy(&g_t_share_data.t_sys_var_cfg.s_sdk_data.firmware_version[0], "app-1.0.0-20220502.1000", strlen("app-1.0.0-20220502.1000"));
v_mutex_unlock();
v_flash_save_var_cfg_data(); //保存参数到DATAFLASH
}
/*************************************************************
函数名称: v_public_param_init
函数功能: 参数初始化
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_public_param_init(void)
{
v_public_fix_cfg_data_restore();
v_public_var_cfg_data_restore();
}
/*************************************************************
函数名称: v_public_cfg_data_init
函数功能: 配置数据初始化
输入参数: 无
输出参数: 无
返回值 :无
**************************************************************/
void v_public_cfg_data_init(void)
{
if(u8_osMutexNew() == 0) //创建信号量
{
printf("g_t_share_data is NULL \n");
return;
}
if(u8_mutex_Lock() == 0) //上锁
return;
memset(&g_t_share_data, 0, sizeof(g_t_share_data));
v_mutex_unlock(); //解锁
//强制恢复出厂
// v_public_fix_cfg_data_restore();
// v_public_var_cfg_data_restore();
//读固定配置参数
if (s32_flash_read_fix_cfg_data() == -1)
{
v_public_fix_cfg_data_restore();
printf("public_fix_cfg_data fail,read new\n");
}
//读可变配置参数
if (s32_flash_read_var_cfg_data() == -1)
{
v_public_var_cfg_data_restore();
printf("public_fix_cfg_data fail,read new\n");
}
if(strlen(g_t_share_data.t_sys_var_cfg.custom_ver) == 0) //如果custom_ver版本号为空,则赋默认值
{
memcpy(g_t_share_data.t_sys_var_cfg.custom_ver, Software_Version, sizeof(Software_Version));
}
SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg;
t_sys_fix_cfg->u8_gun_type[0] = 1;
t_sys_fix_cfg->u8_gun_type[1] = 1; //本系统都是国标枪
#if 0 //ocpp 测试
const U8_T u8_platA_IP[] = "ws://182.92.157.86:8088/steve/websocket/CentralSystemService"; //注意 域名和ip之间使用,分隔 例如39.104.96.26,8897
memset(t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name , 0, sizeof(t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name));
memcpy(t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name , u8_platA_IP , strlen((char *)u8_platA_IP)); //服务器A域名(IP+端口号) - 最大字符50字节
const U8_T u8_platA_pileNum[] = "abcd1234"; //
memset(t_sys_fix_cfg->s_net_cfg.u8_platA_pileNum , 0, sizeof(t_sys_fix_cfg->s_net_cfg.u8_platA_pileNum));
memcpy(t_sys_fix_cfg->s_net_cfg.u8_platA_pileNum , u8_platA_pileNum , strlen((char *)u8_platA_pileNum)); //平台1桩编号
g_t_share_data.t_sys_fix_cfg.u_enable.bit_enable.bit_uiEnglishEn = 1;
#endif
#if 0 //sdk测试参数
//接入调试平台 8枪测试桩
strcpy((char *)g_t_share_data.t_sys_var_cfg.s_sdk_data.product_key, "a1q5OZTEiYV"); //产品秘钥
strcpy((char *)g_t_share_data.t_sys_var_cfg.s_sdk_data.device_name, "961758611348789658931728");//资产码
strcpy((char *)g_t_share_data.t_sys_var_cfg.s_sdk_data.device_secret, "5d70d9e838e144e75b4d55ba3b7fe9c7");//设备密钥
strcpy((char *)g_t_share_data.t_sys_var_cfg.s_sdk_data.device_uid, "1049250923019699");//出厂编码
#endif
}
+51
View File
@@ -0,0 +1,51 @@
#ifndef _PUBLIC_DATA_H_
#define _PUBLIC_DATA_H_
#include "main.h"
#include "sys_drv_init.h"
#include "publicdata/sharedatastruct.h"
#include "publicdata/public_define.h"
extern const U8_T Device_Model[] ;
extern const U8_T Software_Version[] ; //软件版本号,用于FOTA升级
extern const U8_T Hardware_Version[] ; //
extern const U8_T Mcu_model[] ;
extern const U8_T Parameter_Version[] ; //参数版本号
extern SHARE_DATA_T g_t_share_data; // 全局共享数据结构
//extern const osMutexAttr_t os_Mutex_attributes;
extern const char *success;
extern const char *failure;
extern U16_T u16_crc_checksum(U8_T *p, U16_T u16_len);
extern U16_T u16_modbus_crc16(U8_T *pucFrame, U16_T usLen);
extern U8_T u8_calculate_bcc(U8_T *pu8_data, U16_T u16_len) ; //BCC异或校验
/* 欧标CAN转PLC 运行时使能:按枪号查 u8_gun_type,0=欧标使能返回11=国标不使能返回0 */
extern U8_T u8_can_plc_enabled(U8_T gun_no);
extern uint64_t u64_get_current_millis(void);
extern uint64_t u64_safe_millis_since(uint64_t last_millis);
extern uint32_t get_current_seconds(void) ; //获取当前秒数
extern uint32_t u32_safe_seconds_since(uint32_t last_sec); //计算时间差值
extern uint8_t dec_to_bcd(uint8_t dec) ;
extern uint8_t bcd_to_dec(uint8_t bcd) ;
extern int bcd_to_ascii(const U8_T *bcd_data, U8_T bcd_len, char *ascii_str, U8_T ascii_buf_len);
/* Base64编码解码函数 */
extern int base64_encode(const uint8_t *input, uint32_t input_len,
char *output, uint32_t output_size);
extern int base64_decode(const char *input, uint8_t *output, uint32_t output_size);
extern void v_flash_save_cfg_data(void);
extern void v_public_cfg_data_init(void);
extern void v_sys_reboot(void);
extern void v_public_param_init(void);
#endif
+33
View File
@@ -0,0 +1,33 @@
# publicdata 模块说明
> 路径:`app/publicdata/`
> 返回主说明:[README](../../README.md)
## 1. 模块职责
- 提供项目公共数据结构与基础类型定义;
- 提供公共工具函数(时间、校验、编码、通用转换等);
- 提供跨模块共享数据访问基础(含 `sharedatastruct`)。
## 2. 关键文件
- `publicdata.c/h`
- `public_func.c`
- `public_define.h`
- `sharedatastruct.h`
- `type.h`
## 3. 对外使用说明
- 业务模块统一通过该目录中的类型/结构做数据交换;
- 公共算法或通用转换优先放在 `public_func.c`,避免重复实现;
- 涉及全局共享结构时,需保持字段定义与实际访问一致。
## 4. 维护建议
- 新增公共结构时同步检查所有引用模块编译影响;
- 避免在该模块引入业务耦合逻辑,保持“基础层”定位。
## 5. 关联文档
- 主索引:[README](../../README.md)
+250
View File
@@ -0,0 +1,250 @@
#ifndef _SHARE_DATA_STRUCT_H_
#define _SHARE_DATA_STRUCT_H_
#include "publicdata/type.h"
#include "publicdata/public_define.h"
/*
缩写 全称 翻译
volt voltage 电压
curr current 电流/现在
res resistance 电阻
batt battery 电池
thr threshold 阀值
in input 输入
out output 输出
insu insulation 绝缘
num number 数量
cfg configure 配置
def default 默认
comm commucation 通信
mgmt management 管理
lang language 语言
ctl control 控制
bms battery monitor system 电池管理系统
dur duration 持续
comp compensation 补偿
dis discharge 放电
pos positive 正
neg negative 负
rt real time 实时
freq frequency 频率
pf power factor 功率因数
temp temperature 温度
*/
//#pragma pack(8)
#pragma pack(push,8)
#define CFG_DATA_VERSION_L 2 //配置数据区版本的低字节
#define CFG_DATA_VERSION_H 0 //配置数据区版本的高字节
#define FEE_MODEL_CNT 96 //计费段数量-新协议
#define FEE_MODEL_TYPE_CNT 30 //费率类型 默认最大费率种类 30
#define IOTX_FIRMWARE_VER_LEN (64) //sdk变量长度结构体
#define IOTX_PRODUCT_KEY_LEN (20)
#define IOTX_DEVICE_UID_LEN (16)
#define IOTX_DEVICE_REG_CODE_LEN (64)
#define IOTX_DEVICE_NAME_LEN (32)
#define IOTX_DEVICE_SECRET_LEN (64)
/* 网络连接方式 */
typedef enum
{
NETWORK_GPRS = 0x00, //4G网络
NETWORK_ETHER, //以太网
}NETWORK_TYPE_E; //通信网络类型
typedef struct //费率存储结构体
{
U32_T u32_rate; //小数点后5位
U32_T u32_sevice;
}S_FEE_DATA;
typedef struct
{
U8_T u8_model_no[17]; //计费模型编号
U8_T u8_feeCnt; //费率条数
S_FEE_DATA s_fee_data[FEE_MODEL_TYPE_CNT]; //费率类型
U8_T u8_fee_type[FEE_MODEL_CNT]; //默认96个时段 费率类型12345.。。
}S_FEE_MODEL;
typedef struct //SDK存储结构体
{
//存储三元组写入的数据
char product_key[IOTX_PRODUCT_KEY_LEN + 1]; //产品秘钥
char device_name[IOTX_DEVICE_NAME_LEN + 1]; //资产码
char device_secret[IOTX_DEVICE_SECRET_LEN + 1]; //设备密钥
char device_reg_code[IOTX_DEVICE_REG_CODE_LEN + 1]; //注册码
char device_uid[IOTX_DEVICE_REG_CODE_LEN + 1]; //出厂编码
char firmware_version[IOTX_FIRMWARE_VER_LEN]; //固件版本信息
}S_SDK_DATA;
typedef union //使能标志位
{
U64_T u64_enable_flag;
struct
{
U64_T bit_doorEnable :2; //门禁使能
U64_T bit_gunLockEna :2; // 枪锁使能
U64_T bit_gunLockNeg :2; // 枪锁信号取反
U64_T bit_AcContactEna :2; // 交流接触器使能
U64_T bit_gunHoming :2; // 枪归位信号有无
U64_T bit_GBEnable :2; // 国标使能(0:兼容 1:国标)
U64_T bit_LcdEnable :2; // 液晶使能,0不使能,1使能
U64_T bit_auxpower :2; // 辅助电压返回状态使能
U64_T bit_reliefen :2; // 泄放使能
U64_T bit_YeLenEn :2; // 液冷通讯使能
U64_T bit_ABcommEn :2; // 主副班通讯使能 0 1使能且为1枪 2使能且为2枪
U64_T bit_ScreenSaverEn :2; // UI界面屏保使能 0不使能 1使能 2使能轮播
U64_T bit_PlugEn :2; //即插即充使能
U64_T bit_uiEnglishEn :2; //UI界面 英语使能 0 中文 1英文 2俄文
U64_T bit_dcBusEn :2; // 直流母联接触器使能 0 不使能 1使能
U64_T bit_gunFanEn :2; // 枪风扇使能 0 不使能 1使能
U64_T bit_mduzeropowEn :2; // 零功控制方式 0普通控制 1脉冲控制(80kW模块)
U64_T bit_ledGbEn :2; //国标指示灯使能 0 待机黄,充电绿,故障红;1 待机绿,充电红,故障黄
U64_T bit_reserve :(64-18*2); // 预留 - 新增数据内容 注意修改 预留字节数量
}bit_enable;
}U_ENABLE_FALG;
typedef enum
{
one_pile_gun_1 = 0x00, //一体一枪
one_pile_gun_2, //一体双枪
split_gun_1, //分体一枪
split_gun_2, //分体双枪
}PILE_TYPE; //桩类型
typedef enum
{
E_LED_TYPE_NULL =0 , //无指示灯
E_LED_TYPE_1, //指示灯类型1 大功率灯板,使用高低电平组成编码-控制灯的动作方式
E_LED_TYPE_2, //指示灯类型2 灯条,不流水显示
E_LED_TYPE_3, //指示灯类型3 灯条,流水显示
E_LED_TYPE_4, //指示灯类型4 欧标灯板 普通方案
E_LED_TYPE_5, //指示灯类型5 欧标灯板 恩普方案
}E_LED_TYPE;
typedef enum
{
GUN_TYPE_EU = 0, //欧标枪
GUN_TYPE_GB = 1, //国标枪
}GUN_TYPE_ENUM;
/******************************** 系统配置参数定义 *********************************/
typedef struct
{
U8_T u8_meter_num; //电表数量
struct
{
U8_T u8_inGun; //归属枪号 0无效,不存在; 1A枪 2B枪
U8_T u8_highPrec; //是否支持高精度 0 不支持 1支持
U8_T u8_isAC; //是否为交流电表 0直流表 1交流表
U8_T u8_meterAddr[6]; //电表地址
}s_data[METER_MAX_CNT]; //最大4个电表 -- 默认顺序,先A枪再B枪,先直流表再交流表 ,即
}S_MEMET_PARA;
typedef union
{
U32_T u32_data;
struct
{
U32_T bit_program_type :2; //程序类型 0社会 1sdk 2ocpp
U32_T bit_netA_type :2; //平台1联网方式 0:以太网 1:GPRS
U32_T bit_netB_type :2; //平台2联网方式 0:以太网 1:GPRS
U32_T bit_platA_en :2; //平台1使能 默认第三方平台 0不使能 1使能
U32_T bit_platB_en :2; //平台2使能 默认积成平台 0不使能 1使能
U32_T bit_platA_type :4; //平台1类型 0云快充 1...
U32_T bit_platB_type :4; //平台1类型 默认积成平台 --非SDK平台时有效,SDK平台时 仅连接SDK
U32_T bit_sim_anp_type :2; //SIM卡 APN类型- 0公网卡 1国网移动 2国网联通 3国网电信
U32_T bit_res :12; //功能预留
}bits;
}U_NET_COMM_PARA; //网路连接参数 用于区分接入平台信息
typedef struct
{
U8_T u8_eth_ip[4]; //IP地址, 默认192.168.1.140
U8_T u8_eth_gate[4]; //网关, 默认192.168.1.254
U8_T u8_eth_mask[4]; //地址掩码, 默认255.255.255.0
U8_T u8_eth_mac[6]; //MAC地址, 默认00:0E:EA:03:A5:01
U8_T u8_serverA_domain_name[NUM_100]; //服务器A域名(IP+端口号) - 最大字符64字节 注意 域名和ip之间使用,分隔 例如39.104.96.26,8897
U8_T u8_serverB_domain_name[NUM_100]; //服务器B域名(IP+端口号) - 最大字符64字节
U8_T u8_platA_pileNum[NUM_32]; //平台1桩编号
U8_T u8_platB_pileNum[NUM_32]; //平台2桩编号
char apn_str[NUM_32]; //apn设置
U_NET_COMM_PARA u_net_comm_para; //网路联网参数
}S_NET_CFG_T;
typedef struct
{
//充电桩资产参数配置
U16_T u16_pile_power_limit; //整桩限制功率 kW
U16_T u16_reserve; //预留
U16_T u16_reserve1; //预留
U16_T u16_reserve2; //预留
U16_T u16_reserve3; //预留
U16_T u16_reserve4; //预留
U8_T u8_reserve[12]; //预留
U8_T u8_pwd[NUM_16]; //维护密码,字符串类型-用户使用
U8_T u8_gunCnt; //枪号
PILE_TYPE u8_pile_type; //指一个终端几把枪!!!!!
U8_T u8_terminal[GUN_MAX_CNT]; //终端地址,0是一体机,1~*是分体机号,一拖几
U8_T u8_gun_type[GUN_MAX_CNT]; //枪类型 0欧标枪 1国标枪
E_LED_TYPE e_ledType; //灯板类型, 0流水灯 1液冷6灯条方案
TIMEZONE_ENUM e_timeZone; //系统时区 0-25 默认20 东八区
U8_T u8_threshold_gunTemp; //枪温阈值 90
U8_T u8_soc_limit; //SOC阈值
U8_T u8_gun_power_limit[GUN_MAX_CNT];//枪充电功率限制 0表示不限制 单位kW
U16_T u16_ratePow; //额定功率 kW
U16_T u16_max_volt; //充电机的调压上值/电压上限 精度 0.1
U16_T u16_min_volt; //充电机的调压下值/电压下限 精度 0.1
U16_T u16_trickle_limit; //涓流充电停机阈值
U16_T u16_max_cur; //最大电流 250A 精度 0.1
//整流模块参数 --
U8_T u8_mdu_num; //充电模块数量
U8_T u8_MduType; //模块类型
U8_T u8_mduTemp_flag; //模块温度获取使能
U8_T u8_mdu_rated_pow; //模块额定功率 kw
U16_T u16_mdu_max_vol; //模块最大电压 0.1V
U16_T u16_mdu_max_cur; //模块最大电流 0.1A
//网络参数配置
S_NET_CFG_T s_net_cfg;
//电表数据
S_MEMET_PARA s_memter;
//使能参数
U_ENABLE_FALG u_enable;
}SYS_FIX_CFG_T;
/* 可变配置数据,后续在这个结构中添加配置数据 */
typedef struct
{
S_FEE_MODEL s_fee_model; //费率类型 - sdk新协议96时段
S_SDK_DATA s_sdk_data; //sdk参数
char QRDisplay[GUN_MAX_CNT][150]; //二维码
char custom_ver[NUM_64]; //自定义版本号字符串 例如 V1.0.0 用于显示
char apn_str[NUM_32]; //apn设置
char ocpp_auth_key[NUM_32]; //OCPP鉴权密钥(AuthorizationKey)
}SYS_VAR_CFG_T;
/************************* 共享数据定义 ***************************************/
typedef struct
{
SYS_FIX_CFG_T t_sys_fix_cfg; //固定配置数据,此结构在最初确定后,不能再添加和减少变量
SYS_VAR_CFG_T t_sys_var_cfg; //可变配置数据,此结构可后续改变其中的变量
}SHARE_DATA_T;
#pragma pack(pop) // 恢复之前的对齐状态
#endif
+4
View File
@@ -0,0 +1,4 @@
#include "type.h"
+186
View File
@@ -0,0 +1,186 @@
#ifndef __TYPE_H_
#define __TYPE_H_
#include <stdbool.h>
#ifndef ULONG
#define ULONG unsigned long
#endif
typedef unsigned char BOOL_T;
typedef unsigned char U8_T;
typedef signed char S8_T;
typedef unsigned short U16_T;
typedef signed short S16_T;
typedef unsigned int U32_T;
typedef signed int S32_T;
typedef unsigned long long U64_T;
typedef signed long long S64_T;
typedef float F32_T;
typedef double F64_T;
typedef char * STR_T;
#ifndef NULL
#define NULL (void *)0
#endif
typedef enum {ST_FALSE = 0, ST_TRUE = !ST_FALSE} ST_BOOL;
typedef enum {CMD_OFF = 0, CMD_ON = !CMD_OFF} E_CMD;
//位宏定义
#define BITSET(var,bit) ((var)|=(1UL<<(bit))) // 设置指定位为1 参数:var - 要操作的变量,bit - 位位置(0~31)
#define BITCLR(var,bit) ((var)&= ~(1UL<<(bit))) // 清除指定位(设为0) 参数:var - 要操作的变量,bit - 位位置(0~31)
#define BITREVER(var,bit) ((var)^= (1UL<<(bit))) // 反转指定位(1变0,0变1) 参数:var - 要操作的变量,bit - 位位置(0~31)
#define ISBITSET(var,bit) (((var) & (1UL<<(bit)))==0?0:1) // 检查指定位是否被置1 返回值:非0表示置1,0表示未置1
#define ISBITCLR(var,bit) (((var) & (1UL<<(bit)))==0) // 检查指定位是否为0 返回值:1表示该位为0,0表示该位为1
// 检查是否所有掩码位都被置1
// 参数:msk - 位掩码(如0x03表示bit0和bit1
// 返回值:1表示所有掩码位都为1,0表示不全是1
#define ISMSKSET(var,msk) (((var) & (msk))==(msk))
// 检查是否所有掩码位都为0
// 返回值:1表示所有掩码位都为0,0表示不全是0
#define ISMSKCLR(var,msk) (((var) & (msk))==0)
// 检查是否有任意掩码位被置1
// 返回值:非0表示至少1个掩码位为1,0表示全为0
#define ISANYSET(var,msk) ((var) & (msk))
// 检查指定位状态(与ISBITSET功能相同)
// 返回值:非0表示置1,0表示未置1
#define CHECKBIT(var,bit) (var & (1UL << bit))
// 交换16位数据的高8位和低8位(字节序转换)
// 示例:0x1234 -> 0x3412
#define SWAP(x) (((x & 0xFF00) >> 8) | \
((x & 0x00FF) << 8))
// 操作宏定义
#define MAX(x,y) ((x>y)?x:y)
#define MIN(x,y) ((x<y)?x:y)
#ifndef GetLow8Bits
#define GetLow8Bits(x) ((U8_T)(x & 0x00FF))
#endif
#ifndef GetHigh24Bits
#define GetHigh24Bits(x) ((U8_T)((x & 0xFF000000) >> 24))
#endif
#ifndef GetHigh16Bits
#define GetHigh16Bits(x) ((U8_T)((x & 0xFF0000) >> 16))
#endif
#ifndef GetHigh8Bits
#define GetHigh8Bits(x) ((U8_T)((x & 0xFF00) >> 8))
#endif
#ifndef GetU16Data
#define GetU16Data(x,y) (U16_T)((x << 8) + (y))
#endif
#ifndef GetU32Data
#define GetU32Data(x,y,a,b) (U32_T)((x << 24) + (y << 16) + (a << 8) + (b))
#endif
#define WHOLE_PILE (0)
#define GUN_A (0)
#define GUN_B (1)
#define NUM_0 (0)
#define NUM_1 (1)
#define NUM_2 (2)
#define NUM_3 (3)
#define NUM_4 (4)
#define NUM_5 (5)
#define NUM_6 (6)
#define NUM_7 (7)
#define NUM_8 (8)
#define NUM_9 (9)
#define NUM_10 (10)
#define NUM_15 (15)
#define NUM_20 (20)
#define NUM_25 (25)
#define NUM_30 (30)
#define NUM_50 (50)
#define NUM_60 (50)
#define NUM_100 (100)
#define NUM_120 (120)
#define NUM_150 (150)
#define NUM_200 (200)
#define NUM_250 (250)
#define NUM_300 (300)
#define NUM_500 (500)
#define NUM_1000 (1000)
#define NUM_2000 (2000)
#define NUM_3000 (3000)
#define NUM_5000 (5000)
#define NUM_10000 (1000*10)
#define NUM_20000 (1000*20)
#define NUM_30000 (1000*30)
#define NUM_50000 (1000*50)
#define NUM_60000 (1000*60)
#define NUM_4 (4)
#define NUM_8 (8)
#define NUM_16 (16)
#define NUM_24 (24)
#define NUM_32 (32)
#define NUM_64 (64)
#define NUM_128 (128)
#define NUM_256 (256)
#define NUM_512 (512)
#define NUM_1024 (1024)
#define NUM_2048 (2048)
typedef union
{
U16_T word;
struct
{
U8_T ucLow;
U8_T ucHi;
}byte;
}WordAlign;
typedef struct __Comm_Time__
{
U16_T iYear; //年
U8_T ucMonth; //月
U8_T ucDay; //日
U8_T ucHour; //时
U8_T ucMin; //分
U8_T ucSec; //秒
}Comm_Time;
// 时区定义(0-25对应UTC-12到UTC+14
typedef enum {
TIMEZONE_UTC_MINUS_12 = 0, // UTC-12
TIMEZONE_UTC_MINUS_11 = 1, // UTC-11
TIMEZONE_UTC_MINUS_10 = 2, // UTC-10
TIMEZONE_UTC_MINUS_9 = 3, // UTC-9
TIMEZONE_UTC_MINUS_8 = 4, // UTC-8
TIMEZONE_UTC_MINUS_7 = 5, // UTC-7
TIMEZONE_UTC_MINUS_6 = 6, // UTC-6
TIMEZONE_UTC_MINUS_5 = 7, // UTC-5
TIMEZONE_UTC_MINUS_4 = 8, // UTC-4
TIMEZONE_UTC_MINUS_3 = 9, // UTC-3
TIMEZONE_UTC_MINUS_2 = 10, // UTC-2
TIMEZONE_UTC_MINUS_1 = 11, // UTC-1
TIMEZONE_UTC = 12, // UTC 0
TIMEZONE_UTC_PLUS_1 = 13, // UTC+1
TIMEZONE_UTC_PLUS_2 = 14, // UTC+2
TIMEZONE_UTC_PLUS_3 = 15, // UTC+3
TIMEZONE_UTC_PLUS_4 = 16, // UTC+4
TIMEZONE_UTC_PLUS_5 = 17, // UTC+5
TIMEZONE_UTC_PLUS_6 = 18, // UTC+6
TIMEZONE_UTC_PLUS_7 = 19, // UTC+7
TIMEZONE_UTC_PLUS_8 = 20, // UTC+8(中国)
TIMEZONE_UTC_PLUS_9 = 21, // UTC+9(日本)
TIMEZONE_UTC_PLUS_10 = 22, // UTC+10
TIMEZONE_UTC_PLUS_11 = 23, // UTC+11
TIMEZONE_UTC_PLUS_12 = 24, // UTC+12
TIMEZONE_UTC_PLUS_13 = 25, // UTC+13
TIMEZONE_UTC_PLUS_14 = 26 // UTC+14
} TIMEZONE_ENUM;
extern const char *success;
extern const char *failure;
#endif