/* * 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. */ #include "main.h" #include "user_init.h" #include "lin.h" #include "uart.h" #include "iwdt.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 /* 等待后续bit,4次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) + 3,8为接收字节数,Tbit为单个bit用时,Tbase_period为定时器周期,单位都是us */ uint16_t frame_timeout_cnt; /* 响应超时计数,接收到需要响应的ID后置起,按照实际接收长度计算超时 */ /* 公式:round((1.4x(10+Nx10)xTbit)/Tbase_period) + 3,N为接收字节数,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}; 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"; 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}, {LIN_CMD3, TRANSMIT, LIN_CMD2_LENGTH, LIN_CMD3_Data}, {LIN_CMD4, TRANSMIT, LIN_CMD2_LENGTH, LIN_CMD4_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) { if (UARTxOp.RxLen > 1) { UARTxOp.RxLen = 0; } lin_goto_idle(); } else { g_lin_task.res_frame_timeout_cnt--; } break; } } if(FL_BSTIM32_IsActiveFlag_Update(BSTIM32)) { FL_BSTIM32_ClearFlag_Update(BSTIM32); /* 用户代码,处理更新事件 */ TimebaseHandle(); } } /** * @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); } for (i = 0; i < 8; i++) { LIN_CMD3_Data[i] = SoftwareVersion[i]; LIN_CMD4_Data[i] = SoftwareDate[i]; } } #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 #if (SLEEP_SUPPORT == 1) IWDT_SLP_Freeze(FL_ENABLE); #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) { uint8_t i; for (i = 0; i < 8; i++) { buf[i] = LIN_CMD0_Data[i]; } } void SetSlaveData(uint8_t *buf) { uint8_t i; for (i = 0; i < 8; i++) { LIN_CMD1_Data[i] = buf[i]; } }