LIN总线解析与UART模拟LIN从机实战
生活随笔
收集整理的這篇文章主要介紹了
LIN总线解析与UART模拟LIN从机实战
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
目錄
文章目錄
前言
一、LIN總線是什么?
1.LIN總線的標準
2.LIN總線形式
3、幀的構成
二、UART模擬LIN從機的實現
1.方案概述
2.串口中斷處理
3、同步間隔斷中斷處理
4、接收中斷處理
驗證測試
1、CANoe IG發送幀頭
?2、示波器觀測波形
總結
前言
在汽車領域,CAN總線和LIN總線是應用比較多的總線,因此需要對LIN總線有深入的了解。
本文主要梳理關鍵知識點,幫助大家建立整體的概念,重點在于知識體系的構建。
一、LIN總線是什么?
1.LIN總線的標準
目前各大主機廠廣泛會用的是LIN2.1,波特率采用19200。
2.LIN總線形式
?LIN在總線上的展現形式,主機發幀頭(對比CAN的ID),從機響應數據(對比CAN的8字節數據)
3、幀的構成
?同步段為? 0x55
?ID段為? ? ?幀ID+校驗
數據段為? 幀的數據內容
校驗和? ? 數據段字節和ID的校驗和
二、UART模擬LIN從機的實現
1.方案概述
用接收中斷進行同步段驗證、數據接收
用發送中斷進行數據和校驗的發送
2.串口中斷處理
在中斷中處理
同步間隔中斷
接收中斷
發送中斷
void UartLIN_Handler(void *device, uint32_t wpara, uint32_t lpara) {// Receive break fieldif (0 != (lpara & UART_LSR1_FBRK_Msk)){LIN_IfcAux();UART_LIN->LSR1 |= UART_LSR1_FBRK_Msk; ///<write 1 to clear break status}// Receive dataif (0 != (wpara & UART_LSR0_DR_Msk)){LIN_IfcRx();}// Transmit data doneif (0 != (wpara & UART_LSR0_THRE_Msk)){LIN_IfcTx();} }3、同步間隔斷中斷處理
void LIN_IfcAux(void) {if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_IDLE){g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;USART_TXE_INT_Enable(USART1_SFR, FALSE);}else{//fprintf("Frame err\r\n");g_state = g_autoBaud ? LIN_STATE_RECEIVE_IDENTIFIER : LIN_STATE_RECEIVE_SYNC;g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;USART_TXE_INT_Enable(USART1_SFR, FALSE);}} }4、接收中斷處理
void LIN_IfcRx(void) {uint8_t data = 0, id = 0, index = 0, checksum = 0, frameNum = 0;FRAME_ID_TBL *frameTable = 0, *frameInfo = 0;data = USART_ReceiveData(USART1_SFR);//fprintf("%02x ", data);if (g_direction == DIR_TX){ #if 0if (data != g_buffer[g_rxCount]){// Send error//fprintf("bit err\r\n");}g_rxCount++;// transmit doneif (g_rxCount == g_tranByte){frameInfo = &g_scheduleTable[g_schTblIdx].schedule[g_frameIdx];if (g_state == LIN_STATE_SEND_SYNC){// Start transmit or receive dataif (frameInfo->dir == DIR_TX){g_state = LIN_STATE_SEND_DATA;g_direction = DIR_TX;g_tranByte = frameInfo->dtl + 1;memcpy((void *)g_buffer, (const void *)frameInfo->data, (unsigned int)g_tranByte - 1);checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,frameInfo->dtl, frameInfo->data);g_buffer[g_tranByte - 1] = checksum;g_txCount = 0;g_rxCount = 0;//UART_SetTXEInterrupt(UART_LIN, ENABLE);USART_Send(USART1_SFR, g_buffer, g_tranByte);}else{g_state = LIN_STATE_RECEIVE_DATA;g_direction = DIR_RX;g_recvByte = frameInfo->dtl + 1;g_rxCount = 0;}}else if (g_state == LIN_STATE_SEND_DATA){// Transmit frame doneg_state = LIN_STATE_IDLE;}} #endif}else{if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_RECEIVE_SYNC){// Check sync fieldif (data == 0x55){g_state = LIN_STATE_RECEIVE_IDENTIFIER;}else{g_state = LIN_STATE_IDLE;//fprintf("Sync err\r\n");}}else if (g_state == LIN_STATE_RECEIVE_IDENTIFIER){// Check protect idid = data & 0x3F;if (data == LIN_MakeProtId(id)){frameTable = g_scheduleTable[g_schTblIdx].schedule;frameNum = g_scheduleTable[g_schTblIdx].frameNum;for (index = 0; index < frameNum; index++){frameInfo = &frameTable[index];// Find needed idif (id == frameInfo->id){g_frameIdx = index;g_protectId = data;//fprintf("%d\r\n", id);// Start transmit or receive dataif (frameInfo->dir == DIR_TX){g_state = LIN_STATE_SEND_DATA;g_direction = DIR_TX;g_tranByte = frameInfo->dtl + 1;memcpy((void *)g_buffer, (const void *)frameInfo->data, g_tranByte - 1);checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,frameInfo->dtl, frameInfo->data);g_buffer[g_tranByte - 1] = checksum;g_txCount = 0;g_rxCount = 0;//UART_SetTXEInterrupt(UART_LIN, ENABLE);//USART_Send(USART1_SFR, g_buffer, g_tranByte);USART_TXE_INT_Enable(USART1_SFR, TRUE);//delay_us(2);//g_state = LIN_STATE_IDLE;//g_direction = DIR_RX;//g_txCount = 0;//g_rxCount = 0;}else{g_state = LIN_STATE_RECEIVE_DATA;g_direction = DIR_RX;g_recvByte = frameInfo->dtl + 1;g_rxCount = 0;}break;}}// Not needed idif (index == frameNum){g_state = LIN_STATE_IDLE;//fprintf("Err Id:0x%x\r\n", data);}}else{g_state = LIN_STATE_IDLE;//fprintf("Pid:0x%x err\r\n", data);}}else if (g_state == LIN_STATE_RECEIVE_DATA){if (g_rxCount < g_recvByte){g_buffer[g_rxCount] = data;g_rxCount++;}// Receive frame doneif (g_rxCount == g_recvByte){frameInfo = &g_scheduleTable[g_schTblIdx].schedule[g_frameIdx];checksum = LIN_MakeChecksum((frameInfo->cst == ENHANCED_CHECKSUM) ? g_protectId : 0,g_recvByte - 1, g_buffer);if (checksum == g_buffer[g_rxCount - 1]){// Checksum is successful.// Save datamemcpy((void *)frameInfo->data, (const void *)g_buffer, g_rxCount - 1);}else{// Checksum is failed.//fprintf("Cs err\r\n");}g_state = LIN_STATE_IDLE;}}else{}}} }發送中斷處理
void LIN_IfcTx(void) {if (g_direction == DIR_TX){if (g_mode == SLAVE_MODE){if (g_state == LIN_STATE_SEND_DATA){// Send dataif (g_txCount < g_tranByte){//UART_SendData(UART_LIN, g_buffer[g_txCount]);USART_SendData(USART1_SFR, g_buffer[g_txCount]);g_txCount++;if (g_txCount == g_tranByte){//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);}}else{//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);g_direction = DIR_RX;g_txCount = 0;g_rxCount = 0;}}else{//UART_SetTXEInterrupt(UART_LIN, DISABLE);USART_TXE_INT_Enable(USART1_SFR, FALSE);}}} }數據結構和變量
typedef enum {LIN_STATE_IDLE, ///< Idle stateLIN_STATE_SEND_BREAK, ///< Send break stateLIN_STATE_RECEIVE_BREAK, ///< Receive break stateLIN_STATE_SEND_SYNC, ///< Send sync stateLIN_STATE_RECEIVE_SYNC, ///< Receive sync stateLIN_STATE_SEND_IDENTIFIER, ///< Send identifier stateLIN_STATE_RECEIVE_IDENTIFIER, ///< Receive identifier stateLIN_STATE_SEND_DATA, ///< Send data stateLIN_STATE_RECEIVE_DATA, ///< Receive data stateLIN_STATE_SEND_CHECKSUM, ///< Send checksum stateLIN_STATE_BUSSLEEP ///< Bus sleep state } lin_ifcState;typedef struct {uint8_t id; ///< LIN message frame ID for this frameuint8_t dir; ///< Name of the node that publishes the datauint8_t cst; ///< Type of checksum to be used (enhanced or classic)uint8_t dtl; ///< Number of bytes in the data fielduint16_t delayTime; ///< Actual slot time in ms for the frameuint8_t *data; ///< Address of the structure that lists the signals } FRAME_ID_TBL;typedef struct {uint8_t frameNum; ///< Number of frame slots in the schedule tableFRAME_ID_TBL *schedule; ///< Address of the schedule table } SCHEDULE_TBL;//#define UART_LIN UART1// Checksum type #define ENHANCED_CHECKSUM 0 ///< Enhanced checksum type #define CLASSIC_CHECKSUM 1 ///< Classic checksum type// Direction #define DIR_RX 0 ///< receive direction #define DIR_TX 1 ///< transmit direction// Node mode #define MASTER_MODE 0 ///< master mode #define SLAVE_MODE 1 ///< slave modeextern void LIN_IfcRx(void); extern void LIN_IfcAux(void); extern void LIN_IfcTx(void); extern void LinSlaveInit(void);void LinSlaveInit(void) {}uint8_t g_LinData[4][8] = {{0xA1,0xB2,0xC3,0xD4,0xE5,0xF6,0x97,0x88},{0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28},{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08},{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}, };///< Master send header and receive data FRAME_ID_TBL g_frameTable1[] = {{0x23, 1, 0, 3, 60, g_LinData[0]},{0x21, 0, 0, 8, 60, g_LinData[1]} };///< Schedule table SCHEDULE_TBL g_scheduleTable[] = {{2, &g_frameTable1[0]} };uint32_t g_sendTimes = 0xFFFF; ///< Send frame timesuint8_t g_mode = SLAVE_MODE; ///< Master or slave mode uint8_t g_state = 0; ///< Lin state uint8_t g_schTblIdx = 0; ///< Schedule table index uint8_t g_frameIdx = 0; ///< Frame index uint8_t g_protectId = 0; ///< Protect id uint8_t g_firstFlag = 1; ///< First time flaguint8_t g_direction = 0; ///< Send direction uint8_t g_tranByte = 0; ///< Need transmit bytes uint8_t g_recvByte = 0; ///< Need receive bytes uint8_t g_txCount = 0; ///< Transmit data count uint8_t g_rxCount = 0; ///< Receive data count uint8_t g_autoBaud = 0; ///< Auto baud rate uint8_t g_breakThre = 1; ///< Break threshold uint8_t g_buffer[20] = {0}; ///< Data bufferuint8_t LIN_MakeProtId(uint8_t idData) {union {uint8_t byte;struct {uint8_t d0: 1;uint8_t d1: 1;uint8_t d2: 1;uint8_t d3: 1;uint8_t d4: 1;uint8_t d5: 1;uint8_t p0: 1;uint8_t p1: 1;} bit;} buf;/* Load the desired message frame ID into the LSBits of the buffer. */buf.byte = idData & (uint8_t)0x3F;/* Set the two parity bits. */buf.bit.p1 = ~(buf.bit.d1 ^ buf.bit.d3 ^ buf.bit.d4 ^ buf.bit.d5);buf.bit.p0 = buf.bit.d0 ^ buf.bit.d1 ^ buf.bit.d2 ^ buf.bit.d4;return buf.byte; }uint8_t LIN_MakeChecksum(uint8_t protectId, uint8_t length, uint8_t *data) {uint8_t i = 0, checksum = 0;uint16_t sum = protectId;for (i = 0; i < length; i++){sum += data[i];if (sum >= 0x100){sum -= 0xFF;}}checksum = ~(uint8_t)sum;return checksum; }驗證測試
1、CANoe IG發送幀頭
?2、示波器觀測波形
總結
利用串口可以完美模擬從機,發送和接收采用中斷的形式有利于提高程序的執行效率。
5.1的最后一天假,完美收官
總結
以上是生活随笔為你收集整理的LIN总线解析与UART模拟LIN从机实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言温度换算作业,[编程入门]温度转换
- 下一篇: UVA 111