From 9970b66742cf71d3bfc2913677d4fca49549b88d Mon Sep 17 00:00:00 2001 From: cfif Date: Tue, 13 Jan 2026 13:10:18 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CanSpamReceiver.c | 2 +- CanSpamTransmitter.c | 320 +++++++++++++++++++++++++++++++++++++------ CanSpamTransmitter.h | 16 ++- 3 files changed, 292 insertions(+), 46 deletions(-) diff --git a/CanSpamReceiver.c b/CanSpamReceiver.c index 07c9155..276f860 100644 --- a/CanSpamReceiver.c +++ b/CanSpamReceiver.c @@ -13,7 +13,7 @@ void CanSpamReceiver_Init(tCanSpamReceiver *env, env->access = osMutexNew(NULL); - InitThreadAtrStatic(&env->thread.attr, "CanSpamReceiver", env->thread.controlBlock, env->thread.stack, + InitThreadAtrStatic(&env->thread.attr, "CanSpamRec", env->thread.controlBlock, env->thread.stack, osPriorityNormal); } diff --git a/CanSpamTransmitter.c b/CanSpamTransmitter.c index 24ce316..c3df5ef 100644 --- a/CanSpamTransmitter.c +++ b/CanSpamTransmitter.c @@ -7,116 +7,350 @@ #include "CanPorts.h" void CanSpamTransmitter_Init(tCanSpamTransmitter *env, - tSerialPortFrameIO *ioCanFrame) { + tSerialPortFrameIO *ioCanFrame) { env->ioCanFrame = ioCanFrame; env->access = osMutexNew(NULL); - InitThreadAtrStatic(&env->thread.attr, "CanSpamReceiver", env->thread.controlBlock, env->thread.stack, + InitThreadAtrStatic(&env->thread.attr, "CanSpamTrans", env->thread.controlBlock, env->thread.stack, osPriorityNormal); } -static void TransCanSpamTransmitter(tCanSpamTransmitter *env) { - CCU_AC_Ctrl_t CCU_AC_Ctrl; +static void CCU_HVC_Req_Msg(tCanSpamTransmitter *env) { + CCU_HVC_Req_Msg_t *_m = &ccu_candb_tx.CCU_HVC_Req_Msg; + // Compressor target speed: + // 0xFF = Fault value + _m->CCU_eCompSpeedReq_Val_ro = 0; // Bits= 8 Factor= 50 Unit:'rpm' + + // Request to activate air conditioner compressor + // 1 : "Request" + // 0 : "Stop request" + _m->CCU_eCompReq_Stat = 0; // Bits= 1 + + // request to EMS for closing the low temperature circuit valve + // 2 : "Open Valve request" + // 1 : "Close Valve request" + // 0 : "No request" + _m->CCU_LowTempValve_Req = 1; // Bits= 2 + + + // Rolling Counter [0 - 15] + if (_m->CCU_HVC_Req_RC > 15) { + _m->CCU_HVC_Req_RC = 0; // Bits= 4 + } else { + ++_m->CCU_HVC_Req_RC; // Bits= 4 + } + + // Checksum XOR8 of the data field this message + // Checksum computed as per XOR algorithm: + // Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.) + + uint8_t d0 = (uint8_t) ((_m->CCU_eCompSpeedReq_Val_ro & (0xFFU))); + uint8_t d1 = (uint8_t) ((_m->CCU_eCompReq_Stat & (0x01U)) | + ((_m->CCU_LowTempValve_Req & (0x03U)) << 1U) | + ((_m->CCU_HVC_Req_RC & (0x0FU)) << 4U)); + + _m->CCU_HVC_Req_CS = d0 ^ d1; // Bits= 8 +} + +static void CCU_Msg1(tCanSpamTransmitter *env) { + CCU_Msg1_t *_m = &ccu_candb_tx.CCU_Msg1; + + // Request to activate mirrors heating + // 3 : "Error" + // 2 : "Heating off requested" + // 1 : "Heating on requested" + // 0 : "Unknown" + _m->CCU_MirrorHeating_Req = 0; // Bits= 2 + + // Air recirculation LED indicator command + // 1 : "On" + // 0 : "Off" + _m->CCU_RecirculationLed_Cmd = 0; // Bits= 1 + + // Defrost function LED indicator on/off request + // 1 : "On" + // 0 : "Off" + _m->CCU_DefrostLed_Req = 0; // Bits= 1 + + // Request to activate side windows heating + // 3 : "Error" + // 2 : "Heating off requested" + // 1 : "Heating on requested" + // 0 : "Unknown" + _m->CCU_SideWindowHeating_Req = 0; // Bits= 2 + + // Request to activate rear window heating + // 3 : "Error" + // 2 : "Heating off requested" + // 1 : "Heating on requested" + // 0 : "Unknown" + _m->CCU_RearWindowHeating_Req = 0; // Bits= 2 + + // Request to activate front window heating + // 3 : "Error" + // 2 : "Heating off requested" + // 1 : "Heating on requested" + // 0 : "Unknown" + _m->CCU_FrontWindowHeating_Req = 0; // Bits= 2 + + // Status of emergency air cleaning system + // 1 : "Active" + // 0 : "Incative" + _m->CCU_EmergAirCleaning_Stat = 0; // Bits= 1 + + // Status of fire extinguishing system + // 1 : "Active" + // 0 : "Inactive" + _m->CCU_FireExtinguishSys_Stat = 0; // Bits= 1 + + // Automate climate control On/Off LED command + // 1 : "On" + // 0 : "Off" + _m->CCU_FLAutoPsngrLed_Cmd = 0; // Bits= 1 + + // Automate climate control On/Off LED command + // 1 : "On" + // 0 : "Off" + _m->CCU_FRAutoPsngrLed_Cmd = 0; // Bits= 1 + + // Automate climate control On/Off LED command + // 1 : "On" + // 0 : "Off" + _m->CCU_RLAutoPsngrLed_Cmd = 0; // Bits= 1 + + // Automate climate control On/Off LED command + // 1 : "On" + // 0 : "Off" + _m->CCU_RRAutoPsngrLed_Cmd = 0; // Bits= 1 + + // LED indicator command in CCPF when automatic Coditioner with max power is Active + // 1 : "On" + // 0 : "Off" + _m->CCU_AC_MaxLed_Cmd = 0; // Bits= 1 + + // Rolling Counter [0 - 15] + if (_m->CCU_MSG1_RC > 15) { + _m->CCU_MSG1_RC = 0; // Bits= 4 + } else { + ++_m->CCU_MSG1_RC; // Bits= 4 + } + + // Checksum XOR8 of the data field this message + // Checksum computed as per XOR algorithm: + // Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.) + + uint8_t d0 = (uint8_t) ((_m->CCU_MirrorHeating_Req & (0x03U)) | + ((_m->CCU_RecirculationLed_Cmd & (0x01U)) << 2U) | + ((_m->CCU_DefrostLed_Req & (0x01U)) << 3U) | + ((_m->CCU_SideWindowHeating_Req & (0x03U)) << 4U) | + ((_m->CCU_RearWindowHeating_Req & (0x03U)) << 6U)); + uint8_t d1 = (uint8_t) ((_m->CCU_FrontWindowHeating_Req & (0x03U)) | + ((_m->CCU_EmergAirCleaning_Stat & (0x01U)) << 2U) | + ((_m->CCU_FireExtinguishSys_Stat & (0x01U)) << 3U)); + uint8_t d3 = (uint8_t) ((_m->CCU_FLAutoPsngrLed_Cmd & (0x01U)) | + ((_m->CCU_FRAutoPsngrLed_Cmd & (0x01U)) << 1U) | + ((_m->CCU_RLAutoPsngrLed_Cmd & (0x01U)) << 2U) | + ((_m->CCU_RRAutoPsngrLed_Cmd & (0x01U)) << 3U) | + ((_m->CCU_AC_MaxLed_Cmd & (0x01U)) << 4U)); + uint8_t d6 = (uint8_t) (((_m->CCU_MSG1_RC & (0x0FU)) << 4U)); + + _m->CCU_MSG1_CS = d0 ^ d1 ^ d3 ^ d6; +} + +static void CCU_Msg3(tCanSpamTransmitter *env) { + CCU_Msg3_t *_m = &ccu_candb_tx.CCU_Msg3; + + // Indicates the requested FAN speed from CCU system. + // 127 : "Error" + _m->CCU_FAN_Req = 0; // Bits= 7 Unit:'%' + + // CCU REST mode status + // 3 : "Inactive" + // 2 : "Active" + // 1 : "Standby" + // 0 : "Not requested" + _m->CCU_RestMode_Stat = 0; // Bits= 2 + + // Arithmetic mean air temperature inside the car + _m->CCU_IncarTempSum_Val_ro = CANDB_CCU_IncarTempSum_Val_ro_toS( + 23); // Bits= 8 Offset= -50.0 Factor= 0.5 Unit:'�C' + + // Rolling Counter [0 - 15] + if (_m->CCU_MSG3_RC > 15) { + _m->CCU_MSG3_RC = 0; // Bits= 4 + } else { + ++_m->CCU_MSG3_RC; // Bits= 4 + } + + // Checksum XOR8 of the data field this message + // Checksum computed as per XOR algorithm: + // Byte 1 XOR byte 2 .... XOR byte n-1. (n = packet length.) + + uint8_t d0 = (uint8_t) ((_m->CCU_FAN_Req & (0x7FU))); + uint8_t d1 = (uint8_t) ((_m->CCU_RestMode_Stat & (0x03U))); + uint8_t d2 = (uint8_t) ((_m->CCU_IncarTempSum_Val_ro & (0xFFU))); + uint8_t d3 = (uint8_t) ((_m->CCU_MSG3_RC & (0x0FU))); + + _m->CCU_MSG3_CS = d0 ^ d1 ^ d2 ^ d3; +} + +static void sendEventToCan(tCanSpamTransmitter *env) { + if (env->ide) { + env->canFrame.id_type = FLEXCAN_ID_EXT; + env->canFrame.extended_id = env->can_id; + } else { + env->canFrame.id_type = FLEXCAN_ID_STD; + env->canFrame.standard_id = env->can_id; + } + + env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) &env->canFrame.data, env->canFrame.dlc, + env->can_id, env->canFrame.id_type, 100); +} + +static bool isEventTransmitter(tCanSpamTransmitter *env) { uint32_t timeMs = GetSystemTick(); + bool ret = false; + if (env->time_CCU_Stat1_CYC < timeMs) { env->time_CCU_Stat1_CYC = timeMs + CCU_Stat1_CYC; env->can_id = Pack_CCU_Stat1_candb(&ccu_candb_tx.CCU_Stat1, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + sendEventToCan(env); + ret = true; } if (env->time_CCU_Stat2_CYC < timeMs) { env->time_CCU_Stat2_CYC = timeMs + CCU_Stat2_CYC; env->can_id = Pack_CCU_Stat2_candb(&ccu_candb_tx.CCU_Stat2, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + sendEventToCan(env); + ret = true; } if (env->time_CCU_Stat3_CYC < timeMs) { env->time_CCU_Stat3_CYC = timeMs + CCU_Stat3_CYC; env->can_id = Pack_CCU_Stat3_candb(&ccu_candb_tx.CCU_Stat3, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + sendEventToCan(env); + ret = true; } if (env->time_CCU_Errors_CYC < timeMs) { env->time_CCU_Errors_CYC = timeMs + CCU_Errors_CYC; - env->can_id = Pack_CCU_Errors_candb(&ccu_candb_tx.CCU_Errors, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + env->can_id = Pack_CCU_Errors_candb(&ccu_candb_tx.CCU_Errors, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; } if (env->time_CCU_Requests < timeMs) { env->time_CCU_Requests = timeMs + CCU_Requests_CYC; - env->can_id = Pack_CCU_Requests_candb(&ccu_candb_tx.CCU_Requests, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + env->can_id = Pack_CCU_Requests_candb(&ccu_candb_tx.CCU_Requests, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; } + // начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ + // начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ + // начало--------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ if (env->time_CCU_HVC_Req_Msg < timeMs) { env->time_CCU_HVC_Req_Msg = timeMs + CCU_HVC_Req_Msg_CYC; - env->can_id = Pack_CCU_HVC_Req_Msg_candb(&ccu_candb_tx.CCU_HVC_Req_Msg, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; - } + CCU_HVC_Req_Msg(env); + + env->can_id = Pack_CCU_HVC_Req_Msg_candb(&ccu_candb_tx.CCU_HVC_Req_Msg, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; + } + // конец---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ + // конец---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ + // конец---------------------------------------0x310 CCU_HVC_Req_Msg------------------------------------------------ + + // начало--------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- + // начало--------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- + // начало--------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- if (env->time_CCU_VCU_Msg1 < timeMs) { env->time_CCU_VCU_Msg1 = timeMs + CCU_VCU_Msg1_CYC; - env->can_id = Pack_CCU_VCU_Msg1_candb(&ccu_candb_tx.CCU_VCU_Msg1, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; - } + env->can_id = Pack_CCU_VCU_Msg1_candb(&ccu_candb_tx.CCU_VCU_Msg1, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; + } + // конец---------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- + // конец---------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- + // конец---------------------------------------0x315 CCU_VCU_Msg1--------------------------------------------------- + + // начало--------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- + // начало--------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- + // начало--------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- if (env->time_CCU_VCU_Msg2 < timeMs) { env->time_CCU_VCU_Msg2 = timeMs + CCU_VCU_Msg2_CYC; - env->can_id = Pack_CCU_VCU_Msg2_candb(&ccu_candb_tx.CCU_VCU_Msg2, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; - } + env->can_id = Pack_CCU_VCU_Msg2_candb(&ccu_candb_tx.CCU_VCU_Msg2, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; + } + // конец---------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- + // конец---------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- + // конец---------------------------------------0x316 CCU_VCU_Msg2--------------------------------------------------- + + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- if (env->time_CCU_Msg1 < timeMs) { env->time_CCU_Msg1 = timeMs + CCU_Msg1_CYC; + CCU_Msg1(env); env->can_id = Pack_CCU_Msg1_candb(&ccu_candb_tx.CCU_Msg1, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + sendEventToCan(env); + ret = true; } + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- + // начало--------------------------------------0x380 CCU_Msg1------------------------------------------------------- + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- if (env->time_CCU_Msg3 < timeMs) { env->time_CCU_Msg3 = timeMs + CCU_Msg3_CYC; + CCU_Msg3(env); env->can_id = Pack_CCU_Msg3_candb(&ccu_candb_tx.CCU_Msg3, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + sendEventToCan(env); + ret = true; } + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- + // начало--------------------------------------0x501 CCU_Msg3------------------------------------------------------- if (env->time_CCU_AC_Ctrl < timeMs) { env->time_CCU_AC_Ctrl = timeMs + CCU_AC_Ctrl_CYC; - env->can_id = Pack_CCU_AC_Ctrl_candb(&ccu_candb_tx.CCU_AC_Ctrl, env->canFrame.data, &env->canFrame.dlc, &env->ide); - return; + env->can_id = Pack_CCU_AC_Ctrl_candb(&ccu_candb_tx.CCU_AC_Ctrl, env->canFrame.data, &env->canFrame.dlc, + &env->ide); + sendEventToCan(env); + ret = true; } + + return ret; } + static _Noreturn void CanSpamTransmitter_Thread(tCanSpamTransmitter *env) { for (;;) { if (osMutexAcquire(env->access, 100) == osOK) { - env->can_id = 0; - - TransCanSpamTransmitter(env); - - if (env->can_id) { - - if (env->ide) { - env->canFrame.id_type = FLEXCAN_ID_EXT; - env->canFrame.extended_id = env->can_id; - } else { - env->canFrame.id_type = FLEXCAN_ID_STD; - env->canFrame.standard_id = env->can_id; - } - - osMutexRelease(env->access); - env->ioCanFrame->transmit(env->ioCanFrame->env, (uint8_t *) &env->canFrame, env->canFrame.dlc, PROTOCOL_CAN_ADR_RAW, PROTOCOL_CAN_TYPE_RAW, 10); - } else { - osMutexRelease(env->access); - SystemDelayMs(10); + while (isEventTransmitter(env) != false) { } + osMutexRelease(env->access); + SystemDelayMs(1); } } diff --git a/CanSpamTransmitter.h b/CanSpamTransmitter.h index 74d7244..9b1bdd7 100644 --- a/CanSpamTransmitter.h +++ b/CanSpamTransmitter.h @@ -9,8 +9,20 @@ #include "CanSerialPortFrame.h" #include "ccu_candb-binutil.h" -#define PROTOCOL_CAN_ADR_RAW 0x777 -#define PROTOCOL_CAN_TYPE_RAW 0x0 +typedef enum { + event_CCU_none = 0x00, + event_CCU_Stat1_CYC = 0x01, + event_CCU_Stat2_CYC = 0x02, + event_CCU_Stat3_CYC = 0x03, + event_CCU_Errors_CYC = 0x04, + event_CCU_Requests = 0x05, + event_CCU_HVC_Req_Msg = 0x06, + event_CCU_VCU_Msg1 = 0x07, + event_CCU_VCU_Msg2 = 0x08, + event_CCU_Msg1 = 0x09, + event_CCU_Msg3 = 0x0A, + event_CCU_AC_Ctrl = 0x0B +} eTimeEventTransmit; typedef struct {