Files
E3/app/app_param_manage.c
2025-10-04 16:06:55 +08:00

494 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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

#include "app_config.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#define E2_RESERVE_COUNT 0x20 //增加IP地址 修改为0x20 20250110
// 待发送的参数请求信号
UnParamRequest un_param_request1 ;
UnParamRequest un_param_request2;
RequestContext request_send ;
RequestContext request_context ;
uint8_t read_write_e2_finished = 0;
// 定义全局信号实例,读写信号现在包括 offset 和 size
ParamSignal param_signal = {
.param_ptr = NULL, // 参数指针初始化为 NULL
.type = READ_OPERATION, // 操作类型设置为读操作
.offset = 0, // 整个数据块的偏移
.size = sizeof(param_manager.arr) // 整个数据块的大小
};
// 全局变量:初始化参数名称结构体
ParamNames param_names = {
#define X(name) .name = #name,
PARAM_LIST
#undef X
};
UnParamManager param_manager ;
static uint8_t is_param_initialized = 0;
// 打印所有参数的名称和值, 每行 4 个参数
void printParams()
{
unsigned int param_count = 0;
#define X(name) \
printf("%-8s: %-8.2f", param_names.name, param_manager.bit_data.name); \
param_count++; \
if (param_count % 4 == 0) { \
printf("\n"); \
} else { \
printf(" "); \
}
PARAM_LIST
#undef X
// 如果最后一行不足 4 个参数, 打印换行
if (param_count % 4 != 0)
{
printf("\n");
}
}
void writeByte24c02(uint16_t addr, uint8_t data)
{
if(0 != wrbyte_24c02(addr,data))
{
printf("E2PROM write error!\n");
}
}
uint8_t readByte24c02(uint16_t addr)
{
return rdbyte_24c02(addr);
}
// 定义一个通用的 EEPROM 访问函数
uint8_t accessEeprom(size_t offset, void *data, size_t size, OperationType type)
{
if (data == NULL || size == 0)
{
return 1; // 返回错误状态,表示无效的参数
}
uint8_t *byte_data = (uint8_t *)data; // 将 void* 转换为 uint8_t*,方便逐字节操作
size_t index;
if (type == WRITE_OPERATION)
{
// 写入操作
for (index = 0; index < size; index++)
{
writeByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT), byte_data[index]);
udelay(4000);//写入一个字节延时4ms
}
// 校验
for (index = 0; index < size; index++)
{
if (readByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT)) != byte_data[index])
{
return 2; // 返回错误状态,表示写入验证失败
}
}
}
else
{
// 读取操作
for (index = 0; index < size; index++)
{
byte_data[index] = readByte24c02((uint16_t)(offset + index + E2_RESERVE_COUNT));
}
}
return 0; // 返回状态,表示成功
}
void handleParamOp(void *data)
{
ParamSignal *signal = (ParamSignal *)data;
if (signal->param_ptr == NULL)
{
// 操作整个参数管理器
if (accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), signal->type) == 0)
{
read_write_e2_finished = 1;
publishMessage(&read_write_e2_finished, 1); // 读写成功
}
else
{
read_write_e2_finished = 2;
publishMessage(&read_write_e2_finished, 1); // 读写失败
}
}
else
{
// 根据信号中的偏移和大小操作单个参数
if (accessEeprom(signal->offset, signal->param_ptr, signal->size, signal->type) == 0)
{
read_write_e2_finished = 1;
publishMessage(&read_write_e2_finished, 1); // 读写成功
}
else
{
read_write_e2_finished = 2;
publishMessage(&read_write_e2_finished, 1); // 读写失败
}
}
}
uint8_t calculateCRC(const uint8_t* data, uint32_t length) {
uint8_t crc = 0;
for (uint32_t i = 0; i < length; ++i) {
crc += data[i]; // 简单的校验和,按字节累加
}
return crc;
}
float readParameter(const char *param_name) {
float float_value = 0;
unsigned int offset = 0;
#define X(name) \
if (strcmp(param_name, param_names.name) == 0) { \
accessEeprom(offset, &param_manager.bit_data.name,sizeof(param_manager.bit_data.name), READ_OPERATION);\
memcpy(&float_value, &param_manager.bit_data.name, sizeof(param_manager.bit_data.name)); \
return float_value; \
} \
offset += 4;
PARAM_LIST
#undef X
printf("Parameter not found: %s\n", param_name);
return 0;
}
void writeParameter(const char *param_name, const uint8_t *data) {
unsigned int offset = 0;
#define X(name) \
if (strcmp(param_name, param_names.name) == 0) { \
memcpy(&param_manager.bit_data.name, data, sizeof(param_manager.bit_data.name)); \
accessEeprom(offset, &param_manager.bit_data.name,sizeof(param_manager.bit_data.name), WRITE_OPERATION);\
return; \
} \
offset += 4;
PARAM_LIST
#undef X
printf("Parameter not found: %s\n", param_name);
}
void sendParamRequestResponse(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port, uint8_t isWriteOperation) {
// 准备响应帧
paramRequest->bit_data.frame_header = 0xFF80;
paramRequest->bit_data.frame_type = 0x002B;
paramRequest->bit_data.frame_length = sizeof(StrParamRequest);
paramRequest->bit_data.accumulated = 0;
paramRequest->bit_data.request_id = isWriteOperation ? 98 : 99;
paramRequest->bit_data.crc = calculateCRC(paramRequest->arr, sizeof(paramRequest->arr) - 1);
request_send.param_request = paramRequest;
request_send.sender_ip = sender_ip;
request_send.sender_port = sender_port;
// 发送信号从UDP发送
publishMessage(&request_send, 1);
}
void processReadAllParams(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
uint8_t allParams[256][4]; // Size based on E2 size
unsigned int i = 0;
float param_value;
uint8_t exceeded_max = 0; // 新增标志变量
// 清零 paramRequest
memset(paramRequest, 0, sizeof(UnParamRequest));
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);
printf("Sending parameter data:\n");
#define X(name) \
if (!exceeded_max) { \
if (i < 256) { \
strncpy((char *)paramRequest->bit_data.param_name[i], #name, sizeof(paramRequest->bit_data.param_name[i]) - 1); \
paramRequest->bit_data.param_name[i][sizeof(paramRequest->bit_data.param_name[i]) - 1] = '\0'; \
memcpy(allParams[i], &param_manager.bit_data.name, sizeof(param_manager.bit_data.name)); \
memcpy(&param_value, allParams[i], sizeof(float)); \
printf("Parameter name: %-20s Value: %f\n", #name, param_value); \
i++; \
} else { \
printf("Warning: Exceeded maximum number of parameters\n"); \
exceeded_max = 1; \
} \
}
PARAM_LIST
#undef X
// Pack all parameter data into paramRequest
memcpy(paramRequest->bit_data.data, allParams, sizeof(allParams));
printf("Total parameters sent: %d\n", i);
// Send response
sendParamRequestResponse(paramRequest, sender_ip, sender_port, 0);
}
void processWriteRequestFrame(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
float value;
printf("Processing write request.\n");
// 先发送信号,然后从结构体读数
for (int i = 0; i < 256; ++i) {
if (strlen((char *)paramRequest->bit_data.param_name[i]) > 0) {
writeParameter(paramRequest->bit_data.param_name[i], paramRequest->bit_data.data[i]);
printf("paramRequest->bit_data.param_name[i]:%s \n",paramRequest->bit_data.param_name[i]);
memcpy(&value, paramRequest->bit_data.data[i], sizeof(float));
printf("paramRequest->bit_data.data[i]:%f \n", value);
}
}
// 发送响应,发送所有参数
processReadAllParams(paramRequest, sender_ip, sender_port);
}
void processReadRequestFrame(UnParamRequest *paramRequest, uint32_t sender_ip, uint16_t sender_port) {
printf("Processing read request.\n");
// 先备份原始请求数据
UnParamRequest originalRequest;
memcpy(&originalRequest, paramRequest, sizeof(UnParamRequest));
// 清零响应数据
memset(paramRequest, 0, sizeof(UnParamRequest));
// 处理客户端请求的参数
for (int i = 0; i < 256; ++i) {
if (strlen((char *)originalRequest.bit_data.param_name[i]) > 0) {
// 复制参数名到响应
strcpy((char *)paramRequest->bit_data.param_name[i],
(char *)originalRequest.bit_data.param_name[i]);
// 读取参数值
float readData = readParameter(originalRequest.bit_data.param_name[i]);
memcpy(paramRequest->bit_data.data[i], &readData, sizeof(float));
printf("Read parameter: %s = %f\n",
originalRequest.bit_data.param_name[i], readData);
}
}
// 发送响应 - 直接传递 paramRequest
sendParamRequestResponse(paramRequest, sender_ip, sender_port, 0);
}
void OnParamSignal(void *data)
{
RequestContext *signal = (RequestContext *)data;
uint8_t *datagram = (uint8_t *)signal->param_request->arr;
uint16_t request_id = ((uint16_t)datagram[7] << 8) | (uint16_t)datagram[8];// 大端模式
// 调试输出
printf("Received request ID: 0x%04X\n", request_id);
// 计算CRC
uint8_t calculatedCrc = calculateCRC(datagram, sizeof(UnParamRequest) - 1);
uint8_t receivedCrc = datagram[sizeof(UnParamRequest) - 1];
// 比较CRC
if (calculatedCrc != receivedCrc)
{
printf("CRC check failed, discarding data\n");
printf("Calculated CRC: 0x%02X, Received CRC: 0x%02X\n", calculatedCrc, receivedCrc);
return;
}
printf("CRC check passed\n");
if (request_id == 100)
{ // 读请求
processReadRequestFrame(signal->param_request, signal->sender_ip, signal->sender_port);
}
else if (request_id == 101)
{ // 写请求
processWriteRequestFrame(signal->param_request, signal->sender_ip, signal->sender_port);
}
else if (request_id == 102)
{ // 读取所有参数
processReadAllParams(signal->param_request, signal->sender_ip, signal->sender_port);
}
else
{
printf("Unknown request ID.\n");
return;
}
}
float getParam(const char *param_name)
{
// 检查是否已初始化
if (!is_param_initialized)
{
printf("Parameters not initialized, reinitializing\n");
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);//Read all parameters from E2
is_param_initialized = 1; // Mark as initialized
printParams();
return 0.0f;
}
// 检查参数名是否为空
if (param_name == NULL)
{
printf("Error: Parameter name is empty\n");
return 0.0f;
}
// 遍历所有参数
#define X(name) \
if (strcmp(param_name, #name) == 0) \
{ \
return param_manager.bit_data.name; \
}
PARAM_LIST
#undef X
// 如果没有找到匹配的参数名
printf("Error: Parameter %s not found\n", param_name);
return 0.0f;
}
// setParam 函数
uint8_t setParam(const char *param_name, float value)
{
// 检查参数名是否为空
if (param_name == NULL)
{
printf("Error: Parameter name is empty\n");
return 2; // 返回错误码
}
// 参数名和值写入EEPROM先转成字节数组
uint8_t data[sizeof(float)];
memcpy(data, &value, sizeof(float));
writeParameter(param_name, data);
// 更新参数
#define X(name) \
if (strcmp(param_name, #name) == 0) \
{ \
memcpy(&param_manager.bit_data.name, data, sizeof(param_manager.bit_data.name)); \
}
PARAM_LIST
#undef X
return 0;
}
void paramAppInit(void)
{
// 初始化全局变量
memset(&un_param_request1, 0, sizeof(UnParamRequest));
memset(&un_param_request2, 0, sizeof(UnParamRequest));
// 正确初始化 RequestContext 结构体
request_send.param_request = &un_param_request1;
request_send.sender_ip = 0;
request_send.sender_port = 0;
request_context.param_request = &un_param_request2;
request_context.sender_ip = 0;
request_context.sender_port = 0;
// 上电读取所有参数
memset(param_manager.arr, 0, sizeof(param_manager.arr));
accessEeprom(0, param_manager.arr, sizeof(param_manager.arr), READ_OPERATION);
// whl_bas 轮胎直径<单位m>
// max_rpm 最大转速<单位rpm/min>
// whl_dia 轴距<单位m>
// max_acc 最大加速度
// spd_kp 遥控速度P
// spd_ki 遥控速度I
// spd_kd 遥控速度D
// spd_il 遥控速度积分限制
// spd_ol 遥控速度PID输出限制
// crv_kp 遥控转弯P
// crv_ki 遥控转弯I
// crv_kd 遥控转弯D
// crv_il 遥控转弯积分限制
// crv_ol 遥控转弯PID输出限制
// brk_on 刹车刹紧时间 单位ms
// brk_off 刹车释放时间 单位ms
// maxTorq 最大扭矩 单位n*m
// feedPwr 最大馈电功率 单位w
// dispPwr 最大放电功率 单位w
// VehMass 车重 单位kg
// gRatio 减速比
// prCTime 预充电时间 单位s
// brk_pos 刹车位置
// pwr_sta 电源状态
// high_sw 高压开关状态
// stop_sw 急停开关状态
// lightSt 灯光状态
// pwr_btn 电源开关状态
// sleepTm 休眠时间 单位min
// wakeTm 唤醒时间 单位min
// Ospd_kp 自主速度P
// Ospd_ki 自主速度I
// Ospd_kd 自主速度D
// Ospd_il 自主速度积分限制
// Ospd_ol 自主速度PID输出限制
// Ocrv_kp 自主转弯P
// Ocrv_ki 自主转弯I
// Ocrv_kd 自主转弯D
// Ocrv_il 自主转弯积分限制
// Ocrv_ol 自主转弯PID输出限制
// minTorq 输出扭矩死区 单位n*m
// brk_rev 刹车方向
// mot_kp 同侧扭矩P参数
// mot_ki 同侧扭矩I参数
// mot_kd 同侧扭矩d参数
// mot_il 同侧扭矩积分限制
// mot_ol 同侧扭矩输出限制
// diff_sp 同侧扭矩速度差阈值
// test 初始化测试参数
// 订阅信号
subscribe(&param_signal, handleParamOp);
subscribe(&request_context, OnParamSignal);// 接收到上位机读写参数信号
printParams();//打印所有参数
is_param_initialized = 1; // 标记初始化完成
printf("paramAPP init OK! %d\n",getCurrentTime());
}