2025-02-18 10:13:34 +08:00

1076 lines
36 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 "main.h"
#include "user_init.h"
#include "lin.h"
#include "uart.h"
#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};
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},
};
/**
* @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 12位波特率如1200-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)
{
LED3_TOG();
if (UARTxOp.RxLen > 1)
{
UARTxOp.RxLen = 0;
}
lin_goto_idle();
}
else
{
g_lin_task.res_frame_timeout_cnt--;
}
break;
}
LED3_TOG();
}
}
/**
* @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);
}
}
#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
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)
{
}