Files
Frame-rate-optimization/Bsp/bsp_lin.c
2026-04-09 10:14:20 +08:00

236 lines
5.8 KiB
C
Raw Permalink 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 "bsp_lin.h"
#include "circular_buffer.h"
static lin_error_enum lin_error = FIFO_VOID;
static lin_rxstate_enum lin_rxstateget = BREAK_GET;
static lin_msg_struct lin_msg = {0};
static CircBuf_t lin_rx_circbuf = {0};//接收环形队列索引
void lin_init(void)
{
gpio_init_type gpio_init_struct;
crm_periph_clock_enable(CRM_USART5_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
// TX引脚配置
gpio_default_para_init(&gpio_init_struct); // 清空结构体
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; // 中等驱动强度
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; // 推挽输出
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; // 引脚复用模式
gpio_init_struct.gpio_pins = GPIO_PINS_3; // TX引脚
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; // 无上下拉
gpio_init(GPIOB, &gpio_init_struct); // 初始化TX引脚
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE3, GPIO_MUX_10);
// RX引脚配置
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; // 输入模式
gpio_init_struct.gpio_pins = GPIO_PINS_4; // RX引脚
gpio_init(GPIOB, &gpio_init_struct); // 初始化RX引脚
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE4, GPIO_MUX_10);
// USART配置
usart_init(USART5, Lin_Speed, USART_DATA_8BITS, USART_STOP_1_BIT);
usart_transmitter_enable(USART5, TRUE); // 使能发送器
usart_receiver_enable(USART5, TRUE); // 使能接收器
usart_parity_selection_config(USART5, USART_PARITY_NONE); // 无奇偶校验
usart_break_bit_num_set(USART5, USART_BREAK_11BITS); // 断帧检测
usart_lin_mode_enable(USART5, TRUE); // 启用LIN模式
// 中断配置
nvic_irq_enable(USART5_IRQn, 0, 0); // 配置串口优先级
usart_enable(USART5, TRUE); // 使能USART1
usart_interrupt_enable(USART5, USART_BF_INT, TRUE); // 使能帧中断
usart_interrupt_enable(USART5, USART_RDBF_INT,TRUE);// 使能串口接收中断
CircBuf_Alloc(&lin_rx_circbuf, sizeof(lin_msg_struct)*2);
}
uint8_t lin_getpid(uint8_t id)
{
uint8_t pid = 0, p0 = 0, p1 = 0;
p0 = (((id>>0)^(id>>1)^(id>>2)^(id>>4))&0x01)<<6;//偶校验位
p1 = ((~((id>>1)^(id>>3)^(id>>4)^(id>>5)))&0x01)<<7;//奇校验位
pid = (id|p0|p1);
return pid;
}
uint8_t lin_getchecksum(uint8_t pid, uint8_t* p_data, uint8_t data_len, uint8_t flag)
{
uint16_t checksum = 0;
if((pid != 0x3c)&&(pid != 0x7d))
{
checksum = pid;
}
for(uint8_t i = 0; i < data_len; i++)
{
checksum += p_data[i];
if(checksum > 0xff)
{
checksum -=0xff;
}
}
if(flag == 0)
{
return (~checksum) & 0xff; //发送方需要取反
}
else
{
return checksum & 0xff; //接收方不需要
}
}
void lin_send_bytes(usart_type * usart_x, uint8_t* p_data, uint8_t data_len)
{
for(uint8_t i = 0; i < data_len; i++)
{
usart_data_transmit(usart_x, *p_data++);
while(usart_flag_get(USART3, USART_TDBE_FLAG) == RESET);
}
}
void lin_rx_data(uint8_t pid, uint8_t* p_data, uint8_t data_len)
{
uint8_t lin_buffer[data_len + 1];
uint8_t checksum = lin_getchecksum(pid, p_data, data_len, 0);
for(uint8_t i = 0; i < data_len; i++)
{
lin_buffer[i] = *(p_data + i);
}
lin_buffer[data_len] = checksum;
lin_send_bytes(USART3,lin_buffer, data_len + 1);
}
void lin_master_rxmsg(uint8_t data)
{
lin_msg_struct* p_lin_msg = &lin_msg;
switch((uint8_t)lin_rxstateget)
{
case BREAK_GET:
break;
case SYNCH_GET:
{
if(data != 0x55)
{
lin_error = SYNC_ERR;
lin_rxstateget = BREAK_GET;
}
else
{
p_lin_msg->sync = data;
lin_rxstateget = PID_GET;
}
}
break;
case PID_GET:
{
p_lin_msg->frameid = data&0x3f;
p_lin_msg->pid = data;
uint8_t pid = lin_getpid(p_lin_msg->frameid);
if(pid == p_lin_msg->pid)
{
if(p_lin_msg->frameid == 0x03) //执行 即继续接收数据
{
lin_rxstateget = MSG_GET;
p_lin_msg->datalen = 0;
}
else if(p_lin_msg->frameid == 0x32) //反馈 即向lin总线发送消息
{
lin_rx_data(p_lin_msg->pid, &data, 1);
lin_rxstateget = BREAK_GET;
}
else
{
lin_rxstateget = BREAK_GET;
}
}
else
{
lin_error = PID_ERR;
lin_rxstateget = BREAK_GET;
}
}
break;
case MSG_GET:
{
p_lin_msg->data[p_lin_msg->datalen++] = data;
lin_rxstateget = (p_lin_msg->datalen >= 8) ? CHECKSUM_GET:MSG_GET;
}
break;
case CHECKSUM_GET:
{
p_lin_msg->checksum = data;
uint8_t checksum = lin_getchecksum(p_lin_msg->pid, p_lin_msg->data, p_lin_msg->datalen, 1);
if((checksum + p_lin_msg->checksum) == 0xff)
{
CircBuf_Push(&lin_rx_circbuf, (uint8_t *)p_lin_msg, sizeof(lin_msg_struct));
}
else
{
lin_error = FORMAT_ERR;
}
lin_rxstateget = BREAK_GET;
}
break;
default:
lin_rxstateget = BREAK_GET;
break;
}
}
uint8_t rx_ring_buffer_get_lin_msg(lin_msg_struct * p_lin_msg)
{
return CircBuf_Pop(&lin_rx_circbuf,(uint8_t*)p_lin_msg, sizeof(lin_msg_struct));
}
void USART5_IRQHandler(void)
{
uint8_t receive_data = 0;
if(RESET != usart_interrupt_flag_get(USART5,USART_BFF_FLAG))
{
usart_data_receive(USART5);
lin_rxstateget = SYNCH_GET;
usart_flag_clear(USART5,USART_FERR_FLAG);//清除帧错误标志lin断开段也是数据只不过断开段是超过10位的0不符合串口的帧标准所以出现了帧错误
usart_flag_clear(USART5,USART_BFF_FLAG);
usart_flag_clear(USART5,USART_RDBF_FLAG);
return ;
}
if(RESET != usart_interrupt_flag_get(USART5,USART_RDBF_FLAG))
{
receive_data = usart_data_receive(USART5);
if(RESET == usart_interrupt_flag_get(USART5,USART_FERR_FLAG))
{
if((receive_data == 0x55)&&(lin_rxstateget == BREAK_GET))
{
lin_rxstateget = SYNCH_GET;
return ;
}
lin_master_rxmsg(receive_data);
}
usart_flag_clear(USART5,USART_RDBF_FLAG);
}
}