1151 lines
39 KiB
C
Raw Normal View History

2025-02-19 13:21:11 +08:00
/*
* Copyright (c) 2022, SHANGHAI FUDAN MICROELECTRONICS GROUP CO., LTD.(FUDAN MICROELECTRONICS./ FUDAN MICRO.)
* All rights reserved.
*
* Processor: FM33LG0xxA
* http: http://www.fmdevelopers.com.cn/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 4. To provide the most up-to-date information, the revision of our documents
* on the World Wide Web will be the most Current. Your printed copy may be
* an earlier revision. To verify you have the latest information avaliable,
* refer to: http://www.fmdevelopers.com.cn/.
*
* THIS SOFTWARE IS PROVIDED BY FUDAN MICRO "AS IS" AND ANY EXPRESSED
* ORIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.IN NO EVENT SHALL FUDAN MICRO OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISINGIN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OFTHE POSSIBILITY OF SUCH DAMAGE.
*/
2025-02-18 10:13:34 +08:00
#include "main.h"
#include "user_init.h"
#include "lin.h"
#include "uart.h"
2025-02-19 13:21:11 +08:00
#include "iwdt.h"
2025-02-18 10:13:34 +08:00
#define FRAME_DATA_MAX_LEN 11 /* 帧最大数据长度 */
#define SCHEDULE_FRAME_MAX_NUM 255 /* 进度表最大帧数量 */
#define FRAME_TYPE_UNCONDITIONAL 0 /* 无条件帧 */
#define FRAME_TYPE_EVENT_TRIGGER 1 /* 事件触发帧 */
#define FRAME_TYPE_SPORADIC 2 /* 偶发帧 */
#define FRAME_TYPE_DIAGNOSTIC 3 /* 诊断帧 */
#define FRAME_TYPE_RESERVED 4 /* 保留帧 */
#define FRAME_TYPE_NO_RESPONSE 5 /* 自定义,主机发送无需回应帧 */
/* 帧处理状态机 */
#define FRAME_STATE_IDLE 0 /* 空闲状态 主:等待任务开始 从:固定波特率:等待间隔段 自动波特率:等待间隔段+同步段 */
#define FRAME_STATE_SEND_SYN 1 /* 主机发送SYN(包括间隔段和同步段) */
#define FRAME_STATE_RECV_SYN 2 /* 固定波特率接收同步段0x55 */
#define FRAME_STATE_RECV_PID 3 /* 接收PID */
#define FRAME_STATE_RECV_DATA 4 /* 接收数据 */
#define FRAME_STATE_SEND 5 /* 串口发送 */
#define FRAME_STATE_SLEEP 6 /* 休眠状态 */
/**
* @brief PID
* @param id: id
* @retval PID
*/
uint8_t calculatePID(uint8_t id)
{
uint8_t P0 = 0, P1 = 0;
P0 = ((id) ^ (id >> 1) ^ (id >> 2) ^ (id >> 4)) & 0x01;
P1 = (~((id >> 1) ^ (id >> 3) ^ (id >> 4) ^ (id >> 5))) & 0x01;
return ((P1 << 7) | (P0 << 6) | id);
}
/**
* @brief
* @param data:
* len:
* @retval checkSum:
*/
uint8_t calculateChecksum(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 -= 0xFF;
}
}
checkSum = (~checkSum) & 0xFF;
return checkSum;
}
/**
* @brief LIN slp初始化
* @param void
* @retval void
*/
void lin_slp_pin_init(void)
{
FL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LIN_SLP_DISABLE();
GPIO_InitStruct.pin = LIN_SLP_PIN;
GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.pull = FL_DISABLE;
FL_GPIO_Init(LIN_SLP_GPIO, &GPIO_InitStruct);
}
#define Min(a, b) (((a)<(b))?(a):(b))
#define lin_calc_max_res_timeout_cnt(bitLength, size) (uint16_t)((14*(1+(size))*((bitLength)/TIMER_1US_LOAD))/TIME_BASE_PERIOD + 3 )
#if (AUTOBAUD == 1)
/* 同步处理步骤:目的是不符合要求尽快结束重新判断同步 */
#define SYN_STEP_WAIT_BREAK 0 /* 等待间隔段获取间隔段和间隔符时长与间隔段比较符合要求转step 1否则步骤不变 */
#define SYN_STEP_WAIT_START 1 /* 等待start, 获取起始位长度与间隔段比较符合要求且占空比为50%转step 2; 否则继续判断是否为间隔段 */
#define SYN_STEP_WAIT_BIT 2 /* 等待后续bit4次PWM符合要求之后转step3等待stop bit任意bit不符合要求转step 0 */
#define SYN_STEP_WAIT_STOP 3 /* 等到stop,判断符合要求结束判断不符合转step 0 */
/* GPTIM中断判断同步相关变量 */
uint32_t LinSampleValue[20]; /* 记录GPTIM中断来时当前 sysclk 计数值需要芯片支持sysclk时钟源为APB */
uint16_t LinSampleCounter; /* 记录GPTIM PWM中断次数 */
uint32_t BitLength; /* 位速率 */
#endif
/* 帧格式 [最大11字节] */
/* data区内容受保护ID-1字节; 数据段-0-8字节校验和-1字节 */
typedef struct s_lin_frame_type
{
uint8_t tx_len;/* 发送长度 */
uint8_t rx_len;/* 接收长度 */
uint8_t data[FRAME_DATA_MAX_LEN];
} lin_frame_data_type;
/* 任务处理:等待接收并处理 */
typedef struct s_lin_task_type
{
uint8_t frame_state; /* 帧处理状态机,参照 FRAME_STATE_IDLE 定义 */
#if (AUTOBAUD == 1)
uint8_t syn_step; /* 参照 SYN_STEP_WAIT_BREAK */
#endif
/* 帧超时计数接收到同步段后置起按照8字节数据计算超时 */
/* 公式round((1.4x(10+8x10)xTbit)/Tbase_period) + 38为接收字节数Tbit为单个bit用时Tbase_period为定时器周期单位都是us */
uint16_t frame_timeout_cnt;
/* 响应超时计数接收到需要响应的ID后置起按照实际接收长度计算超时 */
/* 公式round((1.4x(10+Nx10)xTbit)/Tbase_period) + 3N为接收字节数Tbit为单个bit用时Tbase_period为定时器周期单位都是us */
uint16_t res_frame_timeout_cnt;
/* Lin总线IDLE超时计数减为0进入SLEEP状态 */
uint16_t idle_timeout_cnt;
lin_frame_data_type lin_frame;/* 帧内容 */
} lin_task_type;
lin_task_type g_lin_task;
uint8_t LIN_CMD0_Data[8];
uint8_t LIN_CMD1_Data[8] = {0x12, 0x34, 0x56, 0x78};
uint8_t LIN_CMD2_Data[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
2025-02-19 13:21:11 +08:00
uint8_t LIN_CMD3_Data[8] = {0};
uint8_t LIN_CMD4_Data[8] = {0};
const uint8_t SoftwareVersion[8] = "SW0101 ";
const uint8_t SoftwareDate[8] = "20250218";
2025-02-18 10:13:34 +08:00
lin_cmd_packet_t scheduleTable[] =
{
/* 用户命令码 */
{LIN_CMD0, RECEIVE, LIN_CMD0_LENGTH, LIN_CMD0_Data},
{LIN_CMD1, TRANSMIT, LIN_CMD1_LENGTH, LIN_CMD1_Data},
{LIN_CMD2, TRANSMIT, LIN_CMD2_LENGTH, LIN_CMD2_Data},
2025-02-19 13:21:11 +08:00
{LIN_CMD3, TRANSMIT, LIN_CMD2_LENGTH, LIN_CMD3_Data},
{LIN_CMD4, TRANSMIT, LIN_CMD2_LENGTH, LIN_CMD4_Data},
2025-02-18 10:13:34 +08:00
};
/**
* @brief
* @param void
* @retval void
*/
void lin_timeout_init(void)
{
FL_BSTIM16_InitTypeDef timInit;
timInit.prescaler = 0; /* 分频系数1 */
timInit.clockSource = FL_CMU_BSTIM16_CLK_SOURCE_APBCLK; /* 时钟源 */
timInit.autoReload = TIMER_LOAD_VALUE - 1; /* 自动重装载值 */
timInit.autoReloadState = FL_DISABLE; /* 预装载preload禁能 */
FL_BSTIM16_Init(BSTIM16, &timInit);
FL_BSTIM16_ClearFlag_Update(BSTIM16);
NVIC_ClearPendingIRQ(BSTIM_IRQn);
/* NVIC中断配置 */
NVIC_DisableIRQ(BSTIM_IRQn);
NVIC_SetPriority(BSTIM_IRQn, LIN_BSTIM_IRQ_PRI);
NVIC_EnableIRQ(BSTIM_IRQn);
FL_BSTIM16_EnableIT_Update(BSTIM16);
/* 使能定时器 */
FL_BSTIM16_Enable(BSTIM16);
}
/**
* @brief lin idle
* @param void
* @retval void
*/
void lin_goto_idle(void)
{
LED2_TOG();
g_lin_task.lin_frame.tx_len = 0;
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.frame_state = FRAME_STATE_IDLE;
g_lin_task.idle_timeout_cnt = LIN_IDLE_TIMEOUT;
UARTxOp.RxLen = 0;
UARTxOp.TxLen = 0;
#if (AUTOBAUD == 1)
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK; /* 初始化同步步骤 */
LIN_UART_RX_GPIO->DFS |= LIN_UART_RX_PIN; /* 引脚重置为GPTIM输入 */
GPTIM2->CCER |= GPTIM_CCER_CCIP;
/* 关闭UART接收使能RX引脚输入捕获中断 */
FL_UART_DisableRX(LIN_UART);
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
NVIC_ClearPendingIRQ(GPTIM2_IRQn);
FL_GPTIM_EnableIT_CC(GPTIM2, FL_GPTIM_CHANNEL_1);/* 使能CC1捕捉中断 */
NVIC_EnableIRQ(GPTIM2_IRQn);
#else
FL_UART_EnableRX(LIN_UART); /* 非自动波特率打开接收 */
#endif
LED2_TOG();
}
/**
* @brief lin idle state初始化
* @param void
* @retval void
*/
__STATIC_INLINE void lin_init_idle_state(void)
{
g_lin_task.lin_frame.tx_len = 0;
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.frame_state = FRAME_STATE_IDLE;
g_lin_task.idle_timeout_cnt = LIN_IDLE_TIMEOUT;
UARTxOp.RxLen = 0;
UARTxOp.TxLen = 0;
#if (AUTOBAUD == 1)
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;/* 初始化同步步骤 */
#else
#endif
}
#if (AUTOBAUD == 1)
/**
* @brief bit长度是否超过BIT_GAP
* @param cmp_value:
* base_value:
* @retval 1: BIT_GAP
* 0: BIT_GAP
*/
uint8_t check_bit_gap(uint32_t cmp_value, uint32_t base_value)
{
uint32_t temp;
if (cmp_value > base_value)
{
temp = cmp_value - base_value;
}
else
{
temp = base_value - cmp_value;
}
if (temp > (uint32_t)(base_value * LIN_SYN_BIT_GAP_PERCENTAGE))
{
return 1;
}
else
{
return 0;
}
}
#if (SLEEP_SUPPORT == 1)
extern uint8_t g_awake_init;
#endif
/**
* @brief GPTIM2输入捕获中断
* @note
* @param void
* @retval void
*/
void GPTIM2_IRQHandler(void)
{
uint8_t temp, tempFlag;
volatile uint32_t IC1Value = 0;
volatile uint32_t IC2Value = 0;
static uint32_t sumCalcBaud = 0;/* 累计从起始位到第6位的时间 */
tempFlag = 0;
LED0_TOG();
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
if (LinSampleCounter)
{
IC1Value = GPTIM2->CCR1;
IC2Value = GPTIM2->CCR2;
}
#if (SLEEP_SUPPORT == 1)
else if (g_awake_init)
{
g_awake_init = 0;
/* 180us为LSCLK下使能引脚滤波的情况下产生中断所需要的时间然后转换成计数值 */
IC1Value = 180 * TIMER_1US_LOAD + GPTIM2->CCR1;
IC2Value = 180 * TIMER_1US_LOAD + GPTIM2->CCR2;
LinSampleCounter = 1;
}
#endif
if (LinSampleCounter)
{
if ((g_lin_task.frame_state == FRAME_STATE_IDLE) ||
(g_lin_task.frame_state == FRAME_STATE_SLEEP))
{
switch (g_lin_task.syn_step)
{
/* 等待间隔段 */
case SYN_STEP_WAIT_BREAK:
if (IC2Value < LIN_MIN_BREAK_VALUE)
{
/* 间隔段和间隔符长度倍数关系,不足则判定为错误,下降沿作为间隔段开始 */
LinSampleCounter = 0;
}
else
{
/* 等待下一个PWM */
temp = LinSampleCounter - 1;
temp = temp << 1;
LinSampleValue[temp] = IC2Value;
LinSampleValue[temp + 1] = IC1Value - IC2Value;
g_lin_task.syn_step = SYN_STEP_WAIT_START;
sumCalcBaud = 0;
}
break;
/* 等待START */
case SYN_STEP_WAIT_START:
/* 判断占空比是否符合要求 */
if (check_bit_gap(IC1Value - IC2Value, IC2Value))
{
/* 占空比不符合要求 */
tempFlag = 2;
}
else
{
/* 占空比符合要求 */
if (LinSampleValue[0] < (IC2Value << LIN_BREAK_DELIMITER_TIMES))
{
/* 间隔段和起始位长度倍数关系,不足则接着判断是否为新的间隔段 */
tempFlag = 3;
}
else
{
/* 间隔段和起始位符合逻辑关系,更新数值 */
temp = LinSampleCounter - 1;
temp = temp << 1;
LinSampleValue[temp] = IC2Value;
LinSampleValue[temp + 1] = IC1Value - IC2Value;
g_lin_task.syn_step = SYN_STEP_WAIT_BIT;
sumCalcBaud += IC1Value;
}
}
if (tempFlag)
{
if (IC2Value < LIN_MIN_BREAK_VALUE)
{
/* 间隔段和间隔符长度倍数关系,不足则判定为错误,下降沿作为间隔段开始 */
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;
}
else
{
LinSampleCounter = 1;
/* 等待下一个PWM */
temp = LinSampleCounter - 1;
temp = temp << 1;
LinSampleValue[temp] = IC2Value;
LinSampleValue[temp + 1] = IC1Value - IC2Value;
g_lin_task.syn_step = SYN_STEP_WAIT_START;
sumCalcBaud = 0;
}
}
break;
/* 等待后续位 */
case SYN_STEP_WAIT_BIT:
/* 判断占空比是否符合要求 */
if (check_bit_gap(IC1Value - IC2Value, IC2Value))
{
/* 占空比不符合要求 */
tempFlag = 4;
}
else
{
/* 占空比符合要求, 判断新的bit与起始位的长度关系 */
if (check_bit_gap(IC2Value, LinSampleValue[2]))
{
/* 超出差距 */
tempFlag = 5;
}
else
{
/* 间隔段和起始位符合逻辑关系,更新数值 */
temp = LinSampleCounter - 1;
temp = temp << 1;
LinSampleValue[temp] = IC2Value;
LinSampleValue[temp + 1] = IC1Value - IC2Value;
sumCalcBaud += IC1Value;
if (LinSampleCounter == 5)
{
/* 切换为单次上升沿触发直接计数此刻到下一次上升沿的数值 */
GPTIM2->CCER &= ~GPTIM_CCER_CCIP;
g_lin_task.syn_step = SYN_STEP_WAIT_STOP;
LED1_TOG();
sumCalcBaud = sumCalcBaud >> 3;
sumCalcBaud = sumCalcBaud * LIN_CAPTURE_TIMER_PSC;
}
else
{
g_lin_task.syn_step = SYN_STEP_WAIT_BIT;
}
}
}
if (tempFlag)
{
if (IC2Value < LIN_MIN_BREAK_VALUE)
{
/* 间隔段和间隔符长度倍数关系,不足则判定为错误,下降沿作为间隔段开始 */
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;
}
else
{
LinSampleCounter = 1;
/* 等待下一个PWM */
temp = LinSampleCounter - 1;
temp = temp << 1;
LinSampleValue[temp] = IC2Value;
LinSampleValue[temp + 1] = IC1Value - IC2Value;
g_lin_task.syn_step = SYN_STEP_WAIT_START;
sumCalcBaud = 0;
}
}
break;
/* 等待stop位 */
case SYN_STEP_WAIT_STOP:
/* 判断占空比是否符合要求 */
if (check_bit_gap(IC2Value, LinSampleValue[2]))
{
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;
GPTIM2->CCER |= GPTIM_CCER_CCIP;/* 切换回双沿 */
}
else
{
/* 检测同步成功 */
/* 引脚重置为RX接收 */
LIN_UART_RX_GPIO->DFS &= ~LIN_UART_RX_PIN;
LED1_TOG();
/* 设置串口波特率 */
BitLength = sumCalcBaud;
LIN_UART->CSR &= ~UART_CSR_RXEN_Msk;
LIN_UART->CSR &= ~UART_CSR_TXEN_Msk;
LIN_UART->BGR = BitLength - 1;
LIN_UART->CSR |= UART_CSR_TXEN_Msk;
LIN_UART->ISR = UART_ISR_RXBF_Msk;
/* 切换任务状态机 */
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.frame_state = FRAME_STATE_RECV_PID;
/* 初始化串口接收长度等使能接收等待接收ID */
UARTxOp.RxLen = 0 ;
LIN_UART->CSR |= UART_CSR_RXEN_Msk;
LED1_TOG();
/* 开始接收,置超时 */
g_lin_task.frame_timeout_cnt = lin_calc_max_res_timeout_cnt(BitLength, 8);
LED1_TOG();
/* 关闭GPTIM2中断 */
/* 关闭CC1捕捉中断 */
GPTIM2->DIER &= ~LIN_GPTIM2_IER_MASK;
//NVIC_DisableIRQ(GPTIM2_IRQn);
LinSampleCounter = 0;
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;
}
tempFlag = 6;
break;
default:
break;
}
}
}
LED1_TOG();
LinSampleCounter++;
}
#endif
/**
* @brief
* @note 121200-10ms 19.2KHz-625us
* @param void
* @retval void
*/
void BSTIM_IRQHandler(void)
{
if (FL_BSTIM16_IsActiveFlag_Update(BSTIM16))
{
FL_BSTIM16_ClearFlag_Update(BSTIM16);
switch (g_lin_task.frame_state)
{
case FRAME_STATE_IDLE:
if (0 == g_lin_task.idle_timeout_cnt)
{
g_lin_task.frame_state = FRAME_STATE_SLEEP;
g_lin_task.idle_timeout_cnt = LIN_IDLE_TIMEOUT;
}
else
{
g_lin_task.idle_timeout_cnt--;
}
break;
case FRAME_STATE_RECV_SYN:
case FRAME_STATE_RECV_PID:
case FRAME_STATE_SEND:
if (0 == g_lin_task.frame_timeout_cnt)
{
LED2_TOG();
lin_goto_idle();
}
else
{
g_lin_task.frame_timeout_cnt--;
}
break;
case FRAME_STATE_RECV_DATA:
if (0 == g_lin_task.res_frame_timeout_cnt)
{
if (UARTxOp.RxLen > 1)
{
UARTxOp.RxLen = 0;
}
lin_goto_idle();
}
else
{
g_lin_task.res_frame_timeout_cnt--;
}
break;
}
2025-02-19 13:21:11 +08:00
}
if(FL_BSTIM32_IsActiveFlag_Update(BSTIM32))
{
FL_BSTIM32_ClearFlag_Update(BSTIM32);
/* 用户代码,处理更新事件 */
TimebaseHandle();
2025-02-18 10:13:34 +08:00
}
}
/**
* @brief UART-LIN中断
* @param void
* @retval void
*/
void LIN_UART_IRQHandler(void)
{
uint8_t tmp08;
static uint8_t PID, i;
LED2_TOG();
/* 接收错误中断处理 需要注意帧类型错误会同时有RXBF标志用于判定同步段 */
if (LIN_UART->ISR & UART_ISR_FERR_Msk)
{
tmp08 = LIN_UART->RXBUF;
if (tmp08 == LIN_BREAK_BYTE)
{
/* 检测到间隔段 */
g_lin_task.frame_state = FRAME_STATE_RECV_SYN;
/* 收到间隔段之后置起超时等待在超时内收到同步字节0x55 */
g_lin_task.frame_timeout_cnt = lin_calc_max_res_timeout_cnt(LIN_BIT_TIMER_LOAD, 8);
}
else
{
/* 帧错误 */
lin_goto_idle();
}
LIN_UART->ISR = UART_ISR_FERR_Msk;
}
/* 接收中断处理 */
else if (LIN_UART->ISR & UART_ISR_RXBF_Msk)
{
switch (g_lin_task.frame_state)
{
/* 固定波特率接收同步阶段 */
case FRAME_STATE_RECV_SYN:
/* 接收数据 */
/* 接收中断标志可通过读取rxreg寄存器清除 */
tmp08 = LIN_UART->RXBUF;
UARTxOp.RxLen = 0;
if (tmp08 == LIN_SYN_BYTE)
{
/* 间隔段之后的第一个字节是0x55 */
g_lin_task.frame_state = FRAME_STATE_RECV_PID;
}
else
{
lin_goto_idle();
}
break;
/* 接收PID阶段判断PID是否有效如有效判定后续行为是发送还是接收 */
case FRAME_STATE_RECV_PID:
/* 接收数据 */
/* 接收中断标志可通过读取rxreg寄存器清除 */
tmp08 = LIN_UART->RXBUF;
UARTxOp.RxBuf[UARTxOp.RxLen] = tmp08;
UARTxOp.RxLen++;
LED2_TOG();
for (i = 0; i < TABLE_SIZE; i++)
{
if (scheduleTable[i].pid == tmp08)
{
PID = tmp08;
break;
}
}
LED2_TOG();
if (i == TABLE_SIZE)
{
/* 无对应命令,不做处理 */
lin_goto_idle();
return;
}
else
{
if (scheduleTable[i].type == RECEIVE)
{
/* 主机发送命令,更新待接收长度,转接收数据阶段 */
g_lin_task.lin_frame.rx_len = scheduleTable[i].length + 1;
g_lin_task.frame_state = FRAME_STATE_RECV_DATA;
/* 更新响应超时 */
#if (AUTOBAUD == 1)
g_lin_task.res_frame_timeout_cnt = lin_calc_max_res_timeout_cnt(BitLength, scheduleTable[i].length);
#else
g_lin_task.res_frame_timeout_cnt = lin_calc_max_res_timeout_cnt(LIN_BIT_TIMER_LOAD, scheduleTable[i].length);
#endif
}
else
{
/* 主机接收命令,更新待发送长度,转发送数据阶段 */
/* 第一时间发送数据,保证负载率 */
LIN_UART->TXBUF = scheduleTable[i].data[0];
LED2_TOG();
#if (CHECKSUM_TYPE == CHECKSUM_TYPE_ENHANCED)
g_lin_task.lin_frame.data[0] = PID;
memcpy(&g_lin_task.lin_frame.data[1], scheduleTable[i].data, scheduleTable[i].length);
g_lin_task.lin_frame.data[scheduleTable[i].length + 1] = calculateChecksum(g_lin_task.lin_frame.data, scheduleTable[i].length + 1);
g_lin_task.lin_frame.tx_len = scheduleTable[i].length + 1;
UARTxOp.TxLen = g_lin_task.lin_frame.tx_len;
UARTxOp.TxOpc = 1;
UARTxOp.TxBuf = &g_lin_task.lin_frame.data[1];
#else
memcpy(g_lin_task.lin_frame.data, scheduleTable[i].data, scheduleTable[i].length);
g_lin_task.lin_frame.data[scheduleTable[i].length] = calculateChecksum(g_lin_task.lin_frame.data, scheduleTable[i].length);
g_lin_task.lin_frame.tx_len = scheduleTable[i].length + 1;
UARTxOp.TxLen = g_lin_task.lin_frame.tx_len;
UARTxOp.TxOpc = 1;
UARTxOp.TxBuf = g_lin_task.lin_frame.data;
#endif
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.frame_state = FRAME_STATE_SEND;
}
}
LED2_TOG();
break;
/* 接收数据阶段,直到接收完成才处理 */
case FRAME_STATE_RECV_DATA:
if (UARTxOp.RxLen >= g_lin_task.lin_frame.rx_len)
{
/* 最后一个字节,第一时间开接收 */
#if (AUTOBAUD == 1)
/* 引脚重置为GPTIM输入 */
LIN_UART_RX_GPIO->DFS |= LIN_UART_RX_PIN;
GPTIM2->CCER |= GPTIM_CCER_CCIP;
/* 关闭UART接收使能RX引脚输入捕获中断 */
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
/* 使能CC1捕捉中断 */
GPTIM2->DIER = LIN_GPTIM2_IER_MASK;
/* 关闭UART接收 */
LIN_UART->CSR &= ~UART_CSR_RXEN_Msk;
#else
LIN_UART->CSR |= UART_CSR_RXEN_Msk;
#endif
LED2_TOG();
}
/* 接收数据 */
/* 接收中断标志可通过读取rxreg寄存器清除 */
tmp08 = LIN_UART->RXBUF;
UARTxOp.RxBuf[UARTxOp.RxLen] = tmp08;
UARTxOp.RxLen++;
if (UARTxOp.RxLen >= g_lin_task.lin_frame.rx_len + 1)
{
/* 主机主动发送,解析数据 */
#if (CHECKSUM_TYPE == CHECKSUM_TYPE_ENHANCED)
if (calculateChecksum(UARTxOp.RxBuf, UARTxOp.RxLen - 1) == UARTxOp.RxBuf[UARTxOp.RxLen - 1])
{
LED2_TOG();
/* 通过校验 */
if (scheduleTable[i].length != (UARTxOp.RxLen - 2))
{
lin_init_idle_state();
return;
}
else
{
memcpy(scheduleTable[i].data, &UARTxOp.RxBuf[1], scheduleTable[i].length);
LED2_TOG();
}
}
#else
if (calculateChecksum(&UARTxOp.RxBuf[1], UARTxOp.RxLen - 2) == UARTxOp.RxBuf[UARTxOp.RxLen - 1])
{
if (scheduleTable[i].length != (UARTxOp.RxLen - 2))
{
lin_init_idle_state();
return;
}
else
{
memcpy(scheduleTable[i].data, &UARTxOp.RxBuf[1], scheduleTable[i].length);
}
}
#endif
lin_init_idle_state();
}
break;
case FRAME_STATE_SEND:
/* 接收数据 */
/* 接收中断标志可通过读取rxreg寄存器清除 */
tmp08 = LIN_UART->RXBUF;
if (UARTxOp.TxOpc < UARTxOp.TxLen)
{
if (tmp08 != UARTxOp.TxBuf[UARTxOp.TxOpc - 1])
{
/* bit错误 */
#if (AUTOBAUD == 1)
LIN_UART_RX_GPIO->DFS |= LIN_UART_RX_PIN;/* 引脚重置为GPTIM输入 */
GPTIM2->CCER |= GPTIM_CCER_CCIP;
/* 关闭UART接收使能RX引脚输入捕获中断 */
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
GPTIM2->DIER = LIN_GPTIM2_IER_MASK;/* 使能CC1捕捉中断 */
LIN_UART->CSR &= ~UART_CSR_RXEN_Msk;/* 关闭UART接收 */
#else
LIN_UART->CSR |= UART_CSR_RXEN_Msk;
#endif
LED2_TOG();
lin_init_idle_state();
}
else
{
LIN_UART->TXBUF = UARTxOp.TxBuf[UARTxOp.TxOpc]; /* 发送一个数据 */
UARTxOp.TxOpc++;
}
}
else
{
/* 发送完毕,快速切换至接收 */
#if (AUTOBAUD == 1)
/* 引脚重置为GPTIM输入 */
LIN_UART_RX_GPIO->DFS |= LIN_UART_RX_PIN;
GPTIM2->CCER |= GPTIM_CCER_CCIP;
/* 关闭UART接收使能RX引脚输入捕获中断 */
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
/* 使能CC1捕捉中断 */
GPTIM2->DIER = LIN_GPTIM2_IER_MASK;
/* 关闭UART接收 */
LIN_UART->CSR &= ~UART_CSR_RXEN_Msk;
#else
LIN_UART->CSR |= UART_CSR_RXEN_Msk;
#endif
LED2_TOG();
lin_init_idle_state();
}
break;
default:
/* 接收数据 */
/* 接收中断标志可通过读取rxreg寄存器清除 */
tmp08 = LIN_UART->RXBUF;
break;
}
}
/* 清除可能的错误中断标志 */
if (LIN_UART->ISR & UART_ISR_PERR_Msk)
{
LIN_UART->ISR = UART_ISR_PERR_Msk;
}
if (LIN_UART->ISR & UART_ISR_OERR_Msk)
{
LIN_UART->ISR = UART_ISR_OERR_Msk;
}
LED2_TOG();
}
/**
* @brief lin UART初始化
* @param void
* @retval void
*/
void lin_uart_init(void)
{
/* 初始化uart配置 */
Uartx_Init(LIN_UART);
/* 中断使能 */
#if (AUTOBAUD == 1)
#else
/* 接收错误中断使能,用于同步判断 */
FL_UART_EnableIT_RXError(LIN_UART);
#endif
/* 接收中断使能 */
FL_UART_EnableIT_RXBuffFull(LIN_UART);
FL_UART_EnableTX(LIN_UART);
#if (AUTOBAUD == 1)
#else
FL_UART_EnableRX(LIN_UART);
#endif
}
/**
* @brief lin
* @param void
* @retval void
*/
void lin_task_init(void)
{
uint8_t i;
/* 状态机相关初始化 */
g_lin_task.frame_state = FRAME_STATE_IDLE;
g_lin_task.idle_timeout_cnt = LIN_IDLE_TIMEOUT;
/* 帧数据初始化 */
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.lin_frame.tx_len = 0;
/* 根据cmd计算pid */
for (i = 0; i < TABLE_SIZE; i++)
{
scheduleTable[i].pid = calculatePID(scheduleTable[i].cmd);
}
2025-02-19 13:21:11 +08:00
for (i = 0; i < 8; i++)
{
LIN_CMD3_Data[i] = SoftwareVersion[i];
LIN_CMD4_Data[i] = SoftwareDate[i];
}
2025-02-18 10:13:34 +08:00
}
#if (AUTOBAUD == 1)
/**
* @brief GPTIM初始化
* @param void
* @retval void
*/
void GPTIM_Init(void)
{
FL_GPTIM_InitTypeDef timInit;
FL_GPTIM_IC_InitTypeDef timICInit;
FL_GPTIM_SlaveInitTypeDef timSlaveInit;
FL_GPIO_InitTypeDef gpioInit = {0};
gpioInit.pin = FL_GPIO_PIN_0;
gpioInit.mode = FL_GPIO_MODE_DIGITAL;
gpioInit.outputType = FL_GPIO_OUTPUT_PUSHPULL;
gpioInit.pull = FL_DISABLE;
gpioInit.remapPin = FL_ENABLE;
FL_GPIO_Init(GPIOD, &gpioInit);
timInit.prescaler = LIN_CAPTURE_TIMER_PSC - 1; /* 分频系数1 */
timInit.counterMode = FL_GPTIM_COUNTER_DIR_UP; /* 向上计数 */
timInit.autoReload = 65535; /* 自动重装载值65536 */
timInit.clockDivision = FL_GPTIM_CLK_DIVISION_DIV1; /* 死区和滤波分频 */
timInit.autoReloadState = FL_ENABLE; /* 预装载preload使能 */
FL_GPTIM_Init(GPTIM2, &timInit);
timSlaveInit.slaveMode = FL_GPTIM_SLAVE_MODE_TRGI_RISE_RST; /* 从机复位模式用于配制PWM输入捕获 */
timSlaveInit.triggerSrc = FL_GPTIM_TIM_TS_TI1FP1; /* 触发源选择 TI1FP1 */
timSlaveInit.triggerDelay = FL_DISABLE; /* TRGI延迟禁止 */
FL_GPTIM_SlaveMode_Init(GPTIM2, &timSlaveInit);
timICInit.ICPolarity = FL_GPTIM_IC_POLARITY_INVERT; /* 下降沿捕获 */
timICInit.ICActiveInput = FL_GPTIM_CHANNEL_MODE_INPUT_NORMAL; /* CC1配置为输入IC1映射到TI1 */
timICInit.ICPrescaler = FL_GPTIM_IC_PSC_DIV1; /* 输入捕捉分频 */
timICInit.ICFilter = FL_GPTIM_IC_FILTER_DIV1; /* 输入捕捉滤波配置 */
timICInit.captureState = FL_ENABLE; /* 使能CC1通道 */
FL_GPTIM_IC_Init(GPTIM2, FL_GPTIM_CHANNEL_1, &timICInit);
timICInit.ICPolarity = FL_GPTIM_IC_POLARITY_NORMAL; /* 上升沿捕获 */
timICInit.ICActiveInput = FL_ATIM_CHANNEL_MODE_INPUT_CROSSOVER; /* CC1配置为输入IC1映射到TI1 */
FL_GPTIM_IC_Init(GPTIM2, FL_GPTIM_CHANNEL_2, &timICInit);
GPTIM2->ISR = LIN_GPTIM2_ISR_MASK;
/* 中断优先级配置 */
NVIC_ClearPendingIRQ(GPTIM2_IRQn);
NVIC_DisableIRQ(GPTIM2_IRQn);
NVIC_SetPriority(GPTIM2_IRQn, LIN_GPITM2_IRQ_PRI);
NVIC_EnableIRQ(GPTIM2_IRQn);
FL_GPTIM_ClearFlag_CC(GPTIM2, FL_GPTIM_CHANNEL_1); /* 清除CC1捕捉标志 */
FL_GPTIM_EnableIT_CC(GPTIM2, FL_GPTIM_CHANNEL_1); /* 使能CC1捕捉中断 */
FL_GPTIM_Enable(GPTIM2); /* 使能定时器 */
}
#endif
/**
* @brief LIN初始化
* @param void
* @retval void
*/
void lin_init(void)
{
lin_task_init();
lin_slp_pin_init();
lin_uart_init();
#if (AUTOBAUD == 1)
GPTIM_Init();
#endif
2025-02-19 13:21:11 +08:00
#if (SLEEP_SUPPORT == 1)
IWDT_SLP_Freeze(FL_ENABLE);
#endif
2025-02-18 10:13:34 +08:00
lin_timeout_init();
}
#if (SLEEP_SUPPORT == 1)
/**
* @brief LIN休眠前初始化
* @param void
* @retval void
*/
void lin_sleep_init(void)
{
/* 清除和关闭非唤醒源中断 */
Close_And_ClearIRQ(BSTIM_IRQn);
/* 关闭UART接收功能 */
LIN_UART->CSR &= ~UART_CSR_RXEN_Msk;
Close_And_ClearIRQ(LIN_UART_IRQType);
#if (AUTOBAUD == 1)
/* 禁能定时器 */
GPTIM2->CR1 &= ~GPTIM_CR1_CEN_Msk;
/* 提前配置唤醒后状态 */
GPTIM2->CCER |= GPTIM_CCER_CCIP;
Close_And_ClearIRQ(GPTIM2_IRQn);
#else
#endif
}
/**
* @brief LIN唤醒后初始化
* @param void
* @retval void
*/
void lin_awake_init(void)
{
g_lin_task.lin_frame.tx_len = 0;
g_lin_task.lin_frame.rx_len = 0;
g_lin_task.frame_state = FRAME_STATE_IDLE;
g_lin_task.idle_timeout_cnt = LIN_IDLE_TIMEOUT;
UARTxOp.RxLen = 0;
UARTxOp.TxLen = 0;
#if (AUTOBAUD == 1)
LinSampleCounter = 0;
/* 初始化同步步骤 */
g_lin_task.syn_step = SYN_STEP_WAIT_BREAK;
g_awake_init = 1;
NVIC_EnableIRQ(LIN_UART_IRQType);
#endif
/* 使能非唤醒源中断 */
NVIC_EnableIRQ(BSTIM_IRQn);
}
/**
* @brief LIN sleep判断
* @param void
* @retval 1: Sleep
* 0: Wake
*/
uint8_t lin_is_sleep(void)
{
if (g_lin_task.frame_state == FRAME_STATE_SLEEP)
{
return 1;
}
else
{
return 0;
}
}
#endif /* End #if (SLEEP_SUPPORT == 1) */
void GetMasterData(uint8_t *buf)
{
2025-02-19 13:21:11 +08:00
uint8_t i;
for (i = 0; i < 8; i++)
{
buf[i] = LIN_CMD0_Data[i];
}
2025-02-18 10:13:34 +08:00
}
2025-02-19 13:21:11 +08:00
void SetSlaveData(uint8_t *buf)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
LIN_CMD1_Data[i] = buf[i];
}
}