236 lines
5.8 KiB
C
236 lines
5.8 KiB
C
|
|
#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};//<2F><><EFBFBD>ջ<EFBFBD><D5BB>ζ<EFBFBD><CEB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|
|||
|
|
|
|||
|
|
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<54><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
gpio_default_para_init(&gpio_init_struct); // <20><><EFBFBD>սṹ<D5BD><E1B9B9>
|
|||
|
|
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; // <20>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD><C7BF>
|
|||
|
|
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; // <20><><EFBFBD>Ÿ<EFBFBD><C5B8><EFBFBD>ģʽ
|
|||
|
|
gpio_init_struct.gpio_pins = GPIO_PINS_3; // TX<54><58><EFBFBD><EFBFBD>
|
|||
|
|
gpio_init_struct.gpio_pull = GPIO_PULL_NONE; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
gpio_init(GPIOB, &gpio_init_struct); // <20><>ʼ<EFBFBD><CABC>TX<54><58><EFBFBD><EFBFBD>
|
|||
|
|
|
|||
|
|
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE3, GPIO_MUX_10);
|
|||
|
|
|
|||
|
|
// RX<52><58><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
gpio_init_struct.gpio_mode = GPIO_MODE_MUX; // <20><><EFBFBD><EFBFBD>ģʽ
|
|||
|
|
gpio_init_struct.gpio_pins = GPIO_PINS_4; // RX<52><58><EFBFBD><EFBFBD>
|
|||
|
|
gpio_init(GPIOB, &gpio_init_struct); // <20><>ʼ<EFBFBD><CABC>RX<52><58><EFBFBD><EFBFBD>
|
|||
|
|
|
|||
|
|
gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE4, GPIO_MUX_10);
|
|||
|
|
|
|||
|
|
// USART<52><54><EFBFBD><EFBFBD>
|
|||
|
|
usart_init(USART5, Lin_Speed, USART_DATA_8BITS, USART_STOP_1_BIT);
|
|||
|
|
usart_transmitter_enable(USART5, TRUE); // ʹ<>ܷ<EFBFBD><DCB7><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
usart_receiver_enable(USART5, TRUE); // ʹ<>ܽ<EFBFBD><DCBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
usart_parity_selection_config(USART5, USART_PARITY_NONE); // <20><><EFBFBD><EFBFBD>żУ<C5BC><D0A3>
|
|||
|
|
usart_break_bit_num_set(USART5, USART_BREAK_11BITS); // <20><>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
|||
|
|
usart_lin_mode_enable(USART5, TRUE); // <20><><EFBFBD><EFBFBD>LINģʽ
|
|||
|
|
|
|||
|
|
// <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
nvic_irq_enable(USART5_IRQn, 0, 0); // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
|
|||
|
|
usart_enable(USART5, TRUE); // ʹ<><CAB9>USART1
|
|||
|
|
usart_interrupt_enable(USART5, USART_BF_INT, TRUE); // ʹ<><CAB9>֡<EFBFBD>ж<EFBFBD>
|
|||
|
|
usart_interrupt_enable(USART5, USART_RDBF_INT,TRUE);// ʹ<>ܴ<EFBFBD><DCB4>ڽ<EFBFBD><DABD><EFBFBD><EFBFBD>ж<EFBFBD>
|
|||
|
|
|
|||
|
|
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;//żУ<C5BC><D0A3>λ
|
|||
|
|
p1 = ((~((id>>1)^(id>>3)^(id>>4)^(id>>5)))&0x01)<<7;//<2F><>У<EFBFBD><D0A3>λ
|
|||
|
|
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; //<2F><><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD>Ҫȡ<D2AA><C8A1>
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return checksum & 0xff; //<2F><><EFBFBD>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD>Ҫ
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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) //ִ<><D6B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
{
|
|||
|
|
lin_rxstateget = MSG_GET;
|
|||
|
|
p_lin_msg->datalen = 0;
|
|||
|
|
}
|
|||
|
|
else if(p_lin_msg->frameid == 0x32) //<2F><><EFBFBD><EFBFBD> <09><><EFBFBD><EFBFBD>lin<69><6E><EFBFBD>߷<EFBFBD><DFB7><EFBFBD><EFBFBD><EFBFBD>Ϣ
|
|||
|
|
{
|
|||
|
|
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);//<2F><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE>lin<69>Ͽ<EFBFBD><CFBF><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>dz<EFBFBD><C7B3><EFBFBD>10λ<30><CEBB>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4>ڵ<EFBFBD>֡<EFBFBD><D6A1><EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD>Գ<EFBFBD><D4B3><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|