1.dLIN.h和dLIN.c驱动层代码
/*
* dLIN.h
*
* Created on: 2024/10/25
* Author: WZX
*/
#ifndef _DLIN_H_
#define _DLIN_H_
#include <stdint.h>
typedef enum
{
CLASSIC, // 经典校验
ENHANCE // 增强校验
} LIN_CHECKSUM_TYPE;
typedef enum
{
RECV, // 接收
SEND // 发送
} LIN_TRANSFER_TYPE;
typedef enum
{
LIN_BUS_WAIT_BREAK, // 等待Break信号
LIN_BUS_WAIT_SYNC, // 等待接收同步信号
LIN_BUS_WAIT_PID, // 等待接收PID
LIN_BUS_WAIT_DATA, // 等待接收数据
LIN_BUS_WAIT_CHECKSUM, // 等待接收校验和
LIN_BUS_SENDING_DATA, // 正在发送数据
} LIN_BUS_STATUS;
typedef enum
{
LIN_BUS_VOLTAGE_NORMAL = 0, // 电源正常
LIN_BUS_VOLTAGE_OVER = 1, // 电源过压
LIN_BUS_VOLTAGE_UNDER = 2, // 电源欠压
} LIN_BUS_VOLTAGE_STATUS;
typedef union
{
uint8_t Value;
struct
{
uint8_t Reset : 1; // 重置 ------------ 优先级最低
uint8_t Rx_Overflow_Err : 1; // 接收过载错误
uint8_t Rx_Sync_Err : 1; // 接收同步段错误
uint8_t Tx_ReadBack_Err : 1; // 发送时读回值错误
uint8_t Rx_Check_Sum_Err : 1; // 接收校验和错误
uint8_t Rx_ByteField_Framing_Err : 1; // 字节字段帧错误
uint8_t Rx_Pid_Check_Err : 1; // 接收PID校验错误 -- 优先级最高
} Bit;
} LIN_BUS_ERR_TYPE;
typedef struct
{
uint8_t Data[10]; // 发送数据缓冲区
uint8_t Len; // 发送数据长度
} LIN_BUS_SEND_TYPE;
typedef struct
{
LIN_BUS_STATUS Bus_State; //总线状态
LIN_BUS_ERR_TYPE Bus_Error; //总线错误状态
LIN_BUS_VOLTAGE_STATUS Bus_Voltage; //总线电压状态
uint8_t Bus_Is_Sending; //总线是否在发送中
uint16_t Bus_IDLE_Time; //总线空闲时间
void (*LIN_Init)(void); //lin初始化
void (*LIN_Wait_Break)(void); //lin等待间隔帧
void (*LIN_InSleep)(void); //lin进入低功耗
void (*LIN_OutSleep)(void); //lin退出低功耗
void (*LIN_IntoIDLE_Tick)(void); //lin进入idle计时
} LIN_TypeDef_t;
void dLIN_Init(LIN_TypeDef_t *lin_t);
void dLIN_Receive_Break(void);
uint16_t dLIN_Get_IDLE_Time(void);
void dLIN_Into_IDLE_Tick(void);
uint8_t dLIN_Cal_Pid(uint8_t Id);
uint8_t dLIN_Check_Pid(uint8_t Pid);
uint8_t dLIN_Cal_CheckSum_Classic(uint8_t* Data, uint8_t Len);
uint8_t dLIN_Cal_CheckSum_Enhance(uint8_t Pid, uint8_t* Data, uint8_t Len);
#endif
/*
* dLIN.c
*
* Created on: 2024/10/25
* Author: WZX
*/
#include "dLIN.h"
#include <stddef.h>
static LIN_TypeDef_t *lin = NULL;
/*********************************************************************
* @fn dLIN_Init
*
* @brief lin初始化配置.
*
* @param none
*
* @return none
*/
void dLIN_Init(LIN_TypeDef_t *lin_t)
{
if(lin_t == NULL)
{
return;
}
lin = lin_t;
lin->LIN_Init();
lin->LIN_Wait_Break();
}
/*********************************************************************
* @fn dLIN_Receive_Break
*
* @brief lin接收break.
*
* @param none
*
* @return none
*/
void dLIN_Receive_Break(void)
{
lin->LIN_Wait_Break();
}
/*********************************************************************
* @fn dLIN_Get_IDLE_Time
*
* @brief 获取lin空闲时间.
*
* @param none
*
* @return none
*/
uint16_t dLIN_Get_IDLE_Time(void)
{
return lin->Bus_IDLE_Time;
}
/*********************************************************************
* @fn dLIN_Into_IDLE_Tick
*
* @brief lin进入idle计数.
*
* @param none
*
* @return none
*/
void dLIN_Into_IDLE_Tick(void)
{
lin->LIN_IntoIDLE_Tick();
}
/*
lin pid校验
id 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
pid 0x80 0xc1 0x42 0x03 0xc4 0x85 0x06 0x47 0x08 0x49 0xca 0x8b 0x4c 0x0d 0x8e 0xcf
id 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f
pid 0x50 0x11 0x92 0xd3 0x14 0x55 0xd6 0x97 0xd8 0x99 0x1a 0x5b 0x9c 0xdd 0x5e 0x1f
id 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f
pid 0x20 0x61 0xe2 0xa3 0x64 0x25 0xa6 0xe7 0xa8 0xe9 0x6a 0x2b 0xec 0xad 0x2e 0x6f
id 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f
pid 0xf0 0xb1 0x32 0x73 0xb4 0xf5 0x76 0x37 0x78 0x39 0xba 0xfb 0x3c 0x7d 0xfe 0xbf
*/
#define BIT(Data, Bit) ((Data >> Bit) & 0x01)
/*********************************************************************
* @fn dLIN_Cal_Pid
*
* @brief lin计算pid.
*
* @param none
*
* @return none
*/
uint8_t dLIN_Cal_Pid(uint8_t Id)
{
// P1 P0 ID5 ID4 ID3 ID2 ID1 ID0
// P1 =!(ID1^ID3^ID4^ID5)
// P0 = (ID0^ID1^ID2^ID4)
uint8_t Pid = 0;
uint8_t P1 = !(BIT(Id, 1) ^BIT(Id, 3) ^BIT(Id, 4) ^BIT(Id, 5));
uint8_t P0 = BIT(Id, 0) ^BIT(Id, 1) ^BIT(Id, 2) ^BIT(Id, 4);
Pid = (Id & 0x3F);
Pid |= (P1<<7) | (P0<<6);
return Pid;
}
/*********************************************************************
* @fn dLIN_Check_Pid
*
* @brief lin校验pid.
*
* @param none
*
* @return none
*/
uint8_t dLIN_Check_Pid(uint8_t Pid)
{
// P1 P0 ID5 ID4 ID3 ID2 ID1 ID0
// P1 =!(ID1^ID3^ID4^ID5)
// P0 = (ID0^ID1^ID2^ID4)
uint8_t P0, P1;
P1 = !(BIT(Pid, 1) ^BIT(Pid, 3) ^BIT(Pid, 4) ^BIT(Pid, 5));
P0 = BIT(Pid, 0) ^BIT(Pid, 1) ^BIT(Pid, 2) ^BIT(Pid, 4);
if ((P1 == BIT(Pid, 7)) && (P0 == BIT(Pid, 6)))
{
return 1;
}
return 0;
}
/*********************************************************************
* @fn dLIN_Cal_CheckSum_Classic
*
* @brief lin经典校验.
*
* @param none
*
* @return none
*/
uint8_t dLIN_Cal_CheckSum_Classic(uint8_t* Data, uint8_t Len)
{
uint8_t i;
uint16_t CheckSum = 0;
for(i=0; i<Len; i++)
{
CheckSum += Data[i];
if (CheckSum >= 0x100)
{
CheckSum &= 0x00FF;
CheckSum += 1;
}
}
CheckSum ^= 0xFF; // 取反
return (uint8_t)CheckSum;
}
/*********************************************************************
* @fn dLIN_Cal_CheckSum_Enhance
*
* @brief lin增强校验.
*
* @param none
*
* @return none
*/
uint8_t dLIN_Cal_CheckSum_Enhance(uint8_t Pid, uint8_t* Data, uint8_t Len)
{
uint8_t i;
uint16_t CheckSum = Pid;
for(i=0; i<Len; i++)
{
CheckSum += Data[i];
if (CheckSum >= 0x100)
{
CheckSum &= 0x00FF;
CheckSum += 1;
}
}
CheckSum ^= 0xFF; // 取反
return (uint8_t)CheckSum;
}
2.Config_LIN.c、Cmd_LIN.h、Cmd_LIN.h
这个部分分出三个主要是因为lin着实有点难写,需要的内容有点多,在Cmd中调用Config的代码,实现解耦。
/*
* Config_LIN.c
*
* Created on: 2024/10/25
* Author: WZX
*/
#include "Cmd_LIN.h"
static void LIN_Intp_Interrupt(void);
static void LIN_Tim_Break_Interrupt(void);
static void LIN_Receive_Interrupt(void);
static void LIN_Transmit_Interrupt(void);
/*********************************************************************
* @fn LIN_Conifg_Init
*
* @brief lin配置.
*
* @param none
*
* @return none
*/
void LIN_Conifg_Init(void)
{
//这里放lin的引脚和检测同步间隔帧的初始化代码
}
/*********************************************************************
* @fn LIN_Wait_Break_Succ_Callback
*
* @brief lin等待break信号成功回调函数.
*
* @param none
*
* @return none
*/
__weak void LIN_Wait_Break_Succ_Callback(void)
{
}
/*********************************************************************
* @fn LIN_Wait_Break_Fail_Callback
*
* @brief lin等待break同步信号失败回调函数.
*
* @param none
*
* @return none
*/
__weak void LIN_Wait_Break_Fail_Callback(void)
{
}
/*********************************************************************
* @fn LIN_Receive_Error_Callback
*
* @brief lin接收数据错误回调函数.
*
* @param none
*
* @return none
*/
__weak void LIN_Receive_Error_Callback(void)
{
}
/*********************************************************************
* @fn LIN_Receive_Callback
*
* @brief lin接收数据回调函数.
*
* @param none
*
* @return none
*/
__weak void LIN_Receive_Callback(uint8_t Data)
{
}
/*********************************************************************
* @fn LIN_Transmit_Callback
*
* @brief lin发送数据回调函数.
*
* @param none
*
* @return none
*/
__weak void LIN_Transmit_Callback(void)
{
}
//intp中断--作用未知
static void LIN_Intp_Interrupt(void)
{
}
//tim用作等待同步信号
static void LIN_Tim_Break_Interrupt(void)
{
static volatile uint32_t g_tm40_ch3_width = 0UL;
INTC_ClearPendingIRQ(LIN_TIM_IRQ);
//这个是检测同步间隔的长度
g_tm40_ch3_width = (uint32_t)(TM40->TDR[3] + 1UL);
if(g_tm40_ch3_width > LIN_BREAK_TIME) {
LIN_Wait_Break_Succ_Callback();
INTC_ClearPendingIRQ(LIN_UART_RX_IRQ);
INTC_EnableIRQ(LIN_UART_RX_IRQ);
TIM_Stop(TM40, TIM_Index_Channel3);
} else {
LIN_Wait_Break_Fail_Callback();
}
}
//lin接收数据中断
static void LIN_Receive_Interrupt(void)
{
volatile uint8_t err_type;
INTC_ClearPendingIRQ(LIN_UART_RX_IRQ);
INTC_EnableIRQ(LIN_UART_RX_IRQ);
err_type = UART_GetErrStaus(LIN_UART_BASE, UART_FLAG_FEF | UART_FLAG_PEF | UART_FLAG_OVF);
if(err_type) {
LIN_Receive_Error_Callback();
}
LIN_Receive_Callback(LIN_UART_RX_DATA);
}
//lin发送数据中断
static void LIN_Transmit_Interrupt(void)
{
INTC_ClearPendingIRQ(LIN_UART_TX_IRQ);
LIN_Transmit_Callback();
}
/*
* Cmd_LIN.h
*
* Created on: 2024/10/25
* Author: WZX
*/
#ifndef _CMD_LIN_H_
#define _CMD_LIN_H_
void Cmd_LIN_Init(void);
__weak void LIN_Conifg_Init(void);
#endif
/*
* Cmd_LIN.c
*
* Created on: 2024/10/25
* Author: WZX
*/
#include "Cmd_LIN.h"
#include "dLIN.h"
#include "Cmm_LIN.h"
static LIN_TypeDef_t lin_temp;
static Queue_LIN_Para *lin_rx_para;
static Queue_LIN_Para *lin_tx_para;
static Communicate_LIN_Message_Type *lin_cmm_message = NULL;
static uint8_t lin_function_size;
static void lin_receive_break(void);
static void lin_insleep(void);
static void lin_outsleep(void);
static void lin_into_idle_time(void);
/*********************************************************************
* @fn Cmd_LIN_Init
*
* @brief lin初始化配置.
*
* @param none
*
* @return none
*/
void Cmd_LIN_Init(void)
{
lin_rx_para = Calloc(1, sizeof(struct __Queue_LIN_Para));
lin_tx_para = Calloc(1, sizeof(struct __Queue_LIN_Para));
lin_cmm_message = Cmm_LIN_Get_Function();
lin_function_size = Cmm_LIN_Get_Sizeof_Function();
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
lin_temp.Bus_Voltage = LIN_BUS_VOLTAGE_NORMAL;
lin_temp.Bus_Error.Value = 0;
lin_temp.Bus_Is_Sending = 0;
lin_temp.Bus_IDLE_Time = 0;
lin_temp.LIN_Init = LIN_Conifg_Init;
lin_temp.LIN_InSleep = lin_insleep;
lin_temp.LIN_OutSleep = lin_outsleep;
lin_temp.LIN_IntoIDLE_Tick = lin_into_idle_time;
lin_temp.LIN_Wait_Break = lin_receive_break;
dLIN_Init(&lin_temp);
}
//使能接收同步信号中断
static void lin_receive_break(void)
{
//这个放同步间隔功能函数
}
//lin进入低功耗
static void lin_insleep(void)
{
}
//lin退出低功耗
static void lin_outsleep(void)
{
}
//lin进入空闲的时间
static void lin_into_idle_time(void)
{
if(lin_temp.Bus_IDLE_Time < 0xFFF)
{
lin_temp.Bus_IDLE_Time++;
}
}
//lin发送数据
static void lin_send_data(uint8_t ID)
{
if(lin_temp.Bus_Is_Sending) {
return;
}
if(lin_cmm_message[ID].Len == 0) {
return;
}
lin_cmm_message[ID].Communicate_LIN((void *)lin_cmm_message[ID].pBuffer);
if(lin_cmm_message[ID].ChkSumType == CLASSIC) {
lin_cmm_message[ID].pBuffer[lin_cmm_message[ID].Len] = dLIN_Cal_CheckSum_Classic(lin_cmm_message[ID].pBuffer, \
lin_cmm_message[ID].Len);
} else {
lin_cmm_message[ID].pBuffer[lin_cmm_message[ID].Len] = dLIN_Cal_CheckSum_Enhance(dLIN_Cal_Pid(lin_cmm_message[ID].ID), \
lin_cmm_message[ID].pBuffer, lin_cmm_message[ID].Len);
}
lin_tx_para->ID = lin_cmm_message[ID].ID;
lin_tx_para->Lenght = lin_cmm_message[ID].Len + 1;
lin_tx_para->CheckSum_Type = lin_cmm_message[ID].ChkSumType;
memcpy((uint8_t *)lin_tx_para->Buffer, lin_cmm_message[ID].pBuffer, lin_tx_para->Lenght);
lin_temp.Bus_Is_Sending = 1;
lin_receive_break();
INTC_ClearPendingIRQ(UART0_IRQn);
INTC_SetPendingIRQ(UART0_IRQn);
INTC_EnableIRQ(UART0_IRQn);
}
/*********************************************************************
* @fn LIN_Conifg_Init
*
* @brief lin初始化配置.
*
* @param none
*
* @return none
*/
__weak void LIN_Conifg_Init(void)
{
}
/*********************************************************************
* @fn LIN_Wait_Break_Succ_Callback
*
* @brief lin等待break信号成功回调函数.
*
* @param none
*
* @return none
*/
void LIN_Wait_Break_Succ_Callback(void)
{
lin_temp.Bus_State = LIN_BUS_WAIT_SYNC;
}
/*********************************************************************
* @fn LIN_Wait_Break_Fail_Callback
*
* @brief lin等待break同步信号失败回调函数.
*
* @param none
*
* @return none
*/
void LIN_Wait_Break_Fail_Callback(void)
{
if(lin_temp.Bus_State != LIN_BUS_SENDING_DATA) {
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
}
lin_receive_break();
}
/*********************************************************************
* @fn LIN_Transmit_Callback
*
* @brief lin发送数据回调函数.
*
* @param none
*
* @return none
*/
void LIN_Transmit_Callback(void)
{
static uint8_t tx_count = 0;
if(tx_count < lin_tx_para->Lenght) {
UART0_TX = lin_tx_para->Buffer[tx_count++];
} else {
lin_temp.Bus_Is_Sending = 0;
tx_count = 0;
INTC_DisableIRQ(UART0_IRQn);
//这个是主机读,从机发送完成后的,这个是用的队列,可以参考我之前的队列
//Cmd_LIN_Rx_Push_aData(lin_tx_para);
}
}
/*********************************************************************
* @fn LIN_Receive_Callback
*
* @brief lin接收数据回调函数.
*
* @param none
*
* @return none
*/
void LIN_Receive_Callback(uint8_t Data)
{
volatile uint8_t id, lin_tx_err = 0;
static uint8_t rx_count = 0;
static uint8_t tx_rxcb_count = 0;
static uint8_t tx_rxcb_buffer[10];
//lin总线清除空闲时间
lin_temp.Bus_IDLE_Time = 0;
switch(lin_temp.Bus_State) {
//lin发送数据回读并校验
case LIN_BUS_SENDING_DATA:
tx_rxcb_buffer[tx_rxcb_count++] = Data;
lin_tx_err = 0;
if(tx_rxcb_count >= lin_tx_para->Lenght) {
for(uint8_t i = 0; i < tx_rxcb_count; i++) {
if(tx_rxcb_buffer[i] != lin_tx_para->Buffer[i]) {
lin_tx_err = 1;
break;
}
}
if(lin_tx_err) {
lin_temp.Bus_Error.Bit.Tx_ReadBack_Err = 1;
} else {
lin_temp.Bus_Error.Value = 0;
}
//将队列接收放接收数据完成
//Cmd_LIN_Rx_Push_aData(lin_tx_para);
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
lin_receive_break();
}
break;
//lin当前正在接收同步帧0x55
case LIN_BUS_WAIT_SYNC:
if(Data == 0x55) {
lin_temp.Bus_State = LIN_BUS_WAIT_PID;
} else {
lin_receive_break();
lin_temp.Bus_Error.Bit.Rx_Sync_Err = 1;
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
}
break;
//lin当前正在接收PID并且决定发送数据还是接收数据
case LIN_BUS_WAIT_PID:
if(dLIN_Check_Pid(Data)) {
id = Data & 0x3F;
for(uint8_t i = 0; i < lin_function_size; i++) {
if(id == lin_cmm_message[i].ID) {
if(lin_cmm_message[i].TransfDir == RECV) {
lin_rx_para->ID = id;
lin_rx_para->CheckSum_Type = lin_cmm_message[i].ChkSumType;
lin_rx_para->Lenght = lin_cmm_message[i].Len;
lin_temp.Bus_State = LIN_BUS_WAIT_DATA;
} else {
if(lin_temp.Bus_Voltage == LIN_BUS_VOLTAGE_NORMAL) {
if(lin_temp.Bus_Is_Sending == 0) {
if(lin_cmm_message[i].Len) {
tx_rxcb_count = 0;
lin_temp.Bus_State = LIN_BUS_SENDING_DATA;
lin_send_data(i);
} else {
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
lin_receive_break();
}
}
} else {
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
lin_receive_break();
}
}
return;
}
}
lin_receive_break();
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
}
break;
//lin当前正在接收数据
case LIN_BUS_WAIT_DATA:
lin_rx_para->Buffer[rx_count++] = Data;
if(rx_count >= lin_rx_para->Lenght) {
rx_count = 0;
lin_temp.Bus_State = LIN_BUS_WAIT_CHECKSUM;
}
break;
//lin当前做检验
case LIN_BUS_WAIT_CHECKSUM:
if(lin_rx_para->CheckSum_Type == CLASSIC) {
if(Data == dLIN_Cal_CheckSum_Classic((uint8_t *)&lin_rx_para->Buffer, lin_rx_para->Lenght)) {
//Cmd_LIN_Rx_Push_aData(lin_rx_para);
} else {
lin_temp.Bus_Error.Bit.Rx_Check_Sum_Err = 1;
}
} else {
if(Data == dLIN_Cal_CheckSum_Enhance(dLIN_Cal_Pid(lin_rx_para->ID), \
(uint8_t *)&lin_rx_para->Buffer, lin_rx_para->Lenght)) {
//Cmd_LIN_Rx_Push_aData(lin_rx_para);
} else {
lin_temp.Bus_Error.Bit.Rx_Check_Sum_Err = 1;
}
}
lin_temp.Bus_State = LIN_BUS_WAIT_BREAK;
lin_receive_break();
break;
default:
break;
}
}
3.Task_LIN.h、Task_LIN.c
这个是lin的主任务,我是放在10ms的时间片上
/*
* Task_LIN.h
*
* Created on: 2024/10/25
* Author: WZX
*/
#ifndef _TASK_LIN_H_
#define _TASK_LIN_H_
void Task_LIN(void);
#endif
/*
* Task_LIN.c
*
* Created on: 2024/10/25
* Author: WZX
*/
#include "Task_LIN.h"
#include "Cmd_Queue.h"
#include "Cmm_LIN.h"
#include "dLIN.h"
/*********************************************************************
* @fn Task_LIN
*
* @brief lin任务.
*
* @param none
*
* @return none
*/
void Task_LIN(void)
{
#define Task_LIN_Is_Stop_Time 100
#define Task_LIN_Is_IntoSleep_Time 400
//这里也是队列,参考之前的文章
static Queue_LIN_Para rx_temp;
//需要添加检测12v电源检测
if(Cmd_LIN_Rx_Pop_aData(rx_temp) == 0)
{
if(Cmm_LIN_Set_Function(rx_temp.ID, (void *)&rx_temp.Buffer) != 0)
{
}
}
dLIN_Into_IDLE_Tick();
if(dLIN_Get_IDLE_Time() > Task_LIN_Is_Stop_Time)
{
//超时
}
if(dLIN_Get_IDLE_Time() > Task_LIN_Is_IntoSleep_Time)
{
//进入低功耗
}
else
{
//退出低功耗
}
}
4.Cmm_LIN.h、Cmm_LIN.c、Cmm_LIN_DBL.h
/*
* Cmm_LIN.h
*
* Created on: 2024/10/25
* Author: WZX
*/
#ifndef _CMM_LIN_H_
#define _CMM_LIN_H_
#include <stdint.h>
#include "dLIN.h"
typedef struct
{
uint8_t ID; // ID
uint8_t Len; // 数据长度
LIN_TRANSFER_TYPE TransfDir; // 传输方向
LIN_CHECKSUM_TYPE ChkSumType; // 校验类型
uint8_t *pBuffer;
void (*Communicate_LIN)(void *Buf); // 帧ID回调函数
} Communicate_LIN_Message_Type;
void *Cmm_LIN_Get_Function(void);
uint8_t Cmm_LIN_Get_Sizeof_Function(void);
uint8_t Cmm_LIN_Set_Function(uint8_t ID, void *Buf);
#endif
/*
* Cmm_LIN_DBL.h
*
* Created on: 2024/10/25
* Author: WZX
*/
#ifndef _CMM_LIN_DBL_H_
#define _CMM_LIN_DBL_H_
#include <stdint.h>
#define Cmm_LIN_DBL_Max_Buf 8
/**
* @brief 0x3C -- 测试接收数据
*/
typedef union
{
uint8_t Buffer[Cmm_LIN_DBL_Max_Buf];
struct
{
struct
{
uint8_t Valve :8;
} Data1;
struct
{
uint8_t Valve :8;
} Data2;
struct
{
uint8_t Valve :8;
} Data3;
struct
{
uint8_t Valve :8;
} Data4;
struct
{
uint8_t Valve :8;
} Data5;
struct
{
uint8_t Valve :8;
} Data6;
struct
{
uint8_t Valve :8;
} Data7;
struct
{
uint8_t Valve :8;
} Data8;
} bit;
} Cmm_LIN_DBL_0x3C_RecTest;
/**
* @brief 0x3D -- 测试发送数据
*/
typedef union
{
uint8_t Buffer[Cmm_LIN_DBL_Max_Buf];
struct
{
struct
{
uint8_t Valve :8;
} Data1;
struct
{
uint8_t Valve :8;
} Data2;
struct
{
uint8_t Valve :8;
} Data3;
struct
{
uint8_t Valve :8;
} Data4;
struct
{
uint8_t Valve :8;
} Data5;
struct
{
uint8_t Valve :8;
} Data6;
struct
{
uint8_t Valve :8;
} Data7;
struct
{
uint8_t Valve :8;
} Data8;
} bit;
} Cmm_LIN_DBL_0x3D_SendTest;
#endif
/*
* Cmm_LIN.c
*
* Created on: 2024/10/25
* Author: WZX
*/
#include "Cmm_LIN.h"
#include "Cmm_LIN_DBL.h"
#include "Wos_Debug.h"
#include <stddef.h>
/*!< UART功能命令函数 */
static void Cmm_LIN_Receive_Test(void *Buf);
static void Cmm_LIN_Transmit_Test(void *Buf);
/*!< LIN功能命令列表 */
static uint8_t Cmm_LIN_Transmit_Finish = 0;
static uint8_t Cmm_LIN_Receive_Test_Buffer[8];
static uint8_t Cmm_LIN_Transmit_Test_Buffer[8 + 1]; //发送数据的时候需要多加一个字节做校验
static const Communicate_LIN_Message_Type CMM_LIN[] =
{
// ID 收发长度 传输方向 校验类型 存储参数 功能函数
{0x3C, 8, RECV, CLASSIC, &Cmm_LIN_Receive_Test_Buffer[0], Cmm_LIN_Receive_Test},
{0x3D, 8, SEND, CLASSIC, &Cmm_LIN_Transmit_Test_Buffer[0], Cmm_LIN_Transmit_Test},
};
/*********************************************************************
* @fn Cmm_LIN_Get_Function
*
* @brief LIN获取功能首地址.
*
* @param none
*
* @return none
*/
void *Cmm_LIN_Get_Function(void)
{
return (void *)&CMM_LIN;
}
/*********************************************************************
* @fn Cmm_LIN_Get_Sizeof_Function
*
* @brief LIN获取当前的帧ID数量.
*
* @param ID:功能ID号.
*
* @param Buf:接收数据帧.
*
* @return Command_StatusTypeDef:状态标志位
*/
uint8_t Cmm_LIN_Get_Sizeof_Function(void)
{
return sizeof(CMM_LIN)/sizeof(CMM_LIN[0]);
}
/*********************************************************************
* @fn Cmd_LIN_Set_Function
*
* @brief LIN功能命令设置函数(只用于接收lin的命令帧).
*
* @param ID:功能ID号.
*
* @param Buf:接收数据帧.
*
* @return Command_StatusTypeDef:状态标志位
*/
uint8_t Cmm_LIN_Set_Function(uint8_t ID, void *Buf)
{
for(uint8_t i = 0; i < (sizeof(CMM_LIN)/sizeof(CMM_LIN[0])); i++)
{
if(ID == CMM_LIN[i].ID)
{
if(CMM_LIN[i].Communicate_LIN != NULL)
{
if(CMM_LIN[i].TransfDir == RECV)
{
memcpy((uint8_t *)CMM_LIN[i].pBuffer, Buf, CMM_LIN[i].Len);
}
else
{
Cmm_LIN_Transmit_Finish = 1;
}
CMM_LIN[i].Communicate_LIN((void *)Buf);
Cmm_LIN_Transmit_Finish = 0;
}
return 0;
}
}
return 1;
}
/*********************************************************************
* @fn Cmm_LIN_Receive_Test
*
* @brief LIN接收数据测试.
*
* @param Buf:接收数据帧
*
* @return none
*/
static void Cmm_LIN_Receive_Test(void *Buf)
{
Cmm_LIN_DBL_0x3C_RecTest *temp = (Cmm_LIN_DBL_0x3C_RecTest *)Buf;
Debug("lin 0x3c data is %x %x %x %x %x %x %x %x", temp->bit.Data1.Valve, temp->bit.Data2.Valve, temp->bit.Data3.Valve, \
temp->bit.Data4.Valve, temp->bit.Data5.Valve, temp->bit.Data6.Valve, temp->bit.Data7.Valve, temp->bit.Data8.Valve);
}
/*********************************************************************
* @fn Cmm_LIN_Transmit_Test
*
* @brief LIN发送数据测试.
*
* @param Buf:接收数据帧
*
* @return none
*/
static void Cmm_LIN_Transmit_Test(void *Buf)
{
Cmm_LIN_DBL_0x3D_SendTest *temp = (Cmm_LIN_DBL_0x3D_SendTest *)Buf;
if(!Cmm_LIN_Transmit_Finish)
{//这里是发送数据时需要处理的任务
for(uint8_t i = 0; i < 8; i++)
{
temp->Buffer[i] = Cmm_LIN_Receive_Test_Buffer[i] + 1;
}
}
else
{//这里是发送数据完成需要处理的任务
Debug("lin 0x3D data is %x %x %x %x %x %x %x %x", temp->bit.Data1.Valve, temp->bit.Data2.Valve, temp->bit.Data3.Valve, \
temp->bit.Data4.Valve, temp->bit.Data5.Valve, temp->bit.Data6.Valve, temp->bit.Data7.Valve, temp->bit.Data8.Valve);
}
}