Master配置
添加lin模块,配置成MASTER,lin使用的是LPUART的通道资源,所以LPUART的引脚需要配置,另外LIN的超时需要定时器,再配一个500us的定时器,详细配置可以自己更改;
时钟和引脚相关配置不再说明,只贴lin相关的代码;
#define LIN1_RECV_STATUS_ID (1U)
#define LIN1_SEND_STATUS_ID (2U)
#define TIMER_COMPARE_VAL (uint16_t)(2000U)
#define TIMER_TICKS_1US (uint16_t)(4U)
#define TIMEOUT (500U)
uint8_t lin_master_txbuf[8] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
uint8_t lin_master_rxbuf[8] = {0};
uint16_t lin2_timerOverflowInterruptCount = 0U;
// lin init
LIN_DRV_Init(INST_LIN2, &lin2_InitConfig0, &lin2_State);
LIN_DRV_InstallCallback(INST_LIN2, (lin_callback_t)lin2_callback);
// config timer
FTM_DRV_Init(INST_FLEXTIMER_MC2, &flexTimer_mc2_InitConfig, &timer1_state);
INT_SYS_InstallHandler(FTM1_Ovf_Reload_IRQn, &timer1_handler, (isr_t *)0U);
INT_SYS_EnableIRQ(FTM1_Ovf_Reload_IRQn);
FTM_DRV_InitCounter(INST_FLEXTIMER_MC2, &flexTimer_mc2_TimerConfig);
FTM_DRV_CounterStart(INST_FLEXTIMER_MC2);
lin_callback_t lin2_callback(uint32_t instance, lin_state_t * lin2_State)
{
(void)instance;
lin_callback_t lin2_callback_cur = lin2_State->Callback;
switch (lin2_State->currentEventId) {
case LIN_PID_OK:
// 超时服务
LIN_DRV_SetTimeoutCounter(INST_LIN2, TIMEOUT);
// master send, slave recv
if (lin2_State->currentId == LIN1_RECV_STATUS_ID) {
LIN_DRV_SendFrameData(INST_LIN2, lin_master_txbuf, sizeof(lin_master_txbuf));
}
// master recv, slave send
if (lin2_State->currentId == LIN1_SEND_STATUS_ID) {
LIN_DRV_ReceiveFrameData(INST_LIN2, lin_master_rxbuf, sizeof(lin_master_rxbuf));
lin_master_rx_flag = 1;
}
break;
case LIN_PID_ERROR:
break;
case LIN_TX_COMPLETED:
case LIN_RX_COMPLETED:
LIN_DRV_GotoIdleState(INST_LIN2);
break;
case LIN_WAKEUP_SIGNAL:
break;
case LIN_RECV_BREAK_FIELD_OK:
LIN_DRV_SetTimeoutCounter(INST_LIN2, TIMEOUT);
break;
default:
break;
}
return lin2_callback_cur;
}
// 超时服务相关
uint32_t lin2TimerGetTimeIntervalCallback0(uint32_t *ns)
{
static uint32_t lin2_previousCountValue = 0UL;
uint32_t lin2_counterValue;
lin2_counterValue = FTM_DRV_CounterRead(INST_FLEXTIMER_MC2);
*ns = ((uint32_t)(lin2_counterValue + lin2_timerOverflowInterruptCount * TIMER_COMPARE_VAL - lin2_previousCountValue)) * 1000 / TIMER_TICKS_1US;
lin2_timerOverflowInterruptCount = 0UL;
lin2_previousCountValue = lin2_counterValue;
return 0UL;
}
void timer1_handler()
{
// 清除定时器标志
FTM_DRV_ClearStatusFlags(INST_FLEXTIMER_MC2, FTM_TIME_OVER_FLOW_FLAG);
// lin1配置成了slave,不需要可以删掉
LIN_DRV_TimeoutService(INST_LIN1);
lin1_timerOverflowInterruptCount ++;
LIN_DRV_TimeoutService(INST_LIN2);
lin2_timerOverflowInterruptCount ++;
}
// 按键控制发送帧头ID
void key1_2_callback()
{
uint32_t key_int_flag = PINS_DRV_GetPortIntFlag(PORTC);
if (key_int_flag & (1 << 12)) {
// 发送ID为LIN1_RECV_STATUS_ID的帧头
LIN_DRV_MasterSendHeader(INST_LIN2, LIN1_RECV_STATUS_ID);
} else if (key_int_flag & (1 << 13)) {
// 发送ID为LIN1_SEND_STATUS_ID的帧头
LIN_DRV_MasterSendHeader(INST_LIN2, LIN1_SEND_STATUS_ID);
}
PINS_DRV_ClearPortIntFlagCmd(PORTC);
}
Slave配置
slave的模块配置和master基本相同,选择模式不同,相同部分不再说明,只贴不同的部分;
因为slave不需要发帧头,所以slave只需要处理ID即可;
LIN_DRV_Init(INST_LIN1, &lin1_InitConfig0, &lin1_State);
LIN_DRV_InstallCallback(INST_LIN1, (lin_callback_t)lin1_callback);
lin_callback_t lin1_callback(uint32_t instance, lin_state_t * lin1_State)
{
(void)instance;
lin_callback_t lin1_callback_cur = lin1_State->Callback;
switch (lin1_State->currentEventId) {
case LIN_PID_OK:
LIN_DRV_SetTimeoutCounter(INST_LIN1, TIMEOUT);
if (LIN1_RECV_STATUS_ID == lin1_State->currentId) {
LIN_DRV_ReceiveFrameData(INST_LIN1, lin_slave_rxbuf, sizeof(lin_slave_rxbuf));
}
if (LIN1_SEND_STATUS_ID == lin1_State->currentId) {
LIN_DRV_SendFrameData(INST_LIN1, lin_slave_txbuf, sizeof(lin_slave_txbuf));
}
break;
case LIN_PID_ERROR:
break;
case LIN_TX_COMPLETED:
case LIN_RX_COMPLETED:
LIN_DRV_GotoIdleState(INST_LIN1);
break;
case LIN_WAKEUP_SIGNAL:
break;
case LIN_RECV_BREAK_FIELD_OK:
LIN_DRV_SetTimeoutCounter(INST_LIN1, TIMEOUT);
break;
default:
break;
}
return lin1_callback_cur;
}
uint32_t lin1TimerGetTimeIntervalCallback0(uint32_t *ns)
{
static uint32_t lin1_previousCountValue = 0UL;
uint32_t lin1_counterValue;
lin1_counterValue = FTM_DRV_CounterRead(INST_FLEXTIMER_MC1);
*ns = ((uint32_t)(lin1_counterValue + lin1_timerOverflowInterruptCount * TIMER_COMPARE_VAL - lin1_previousCountValue)) * 1000 / TIMER_TICKS_1US;
lin1_timerOverflowInterruptCount = 0UL;
lin1_previousCountValue = lin1_counterValue;
return 0UL;
}