#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); } }