1?
LIN總線簡介
LIN(Local Interconnect Network)總線是基于UART/SCI(通用異步收發(fā)器/串行接口)的低成本串行通訊協(xié)議,其目標(biāo)定位于車身網(wǎng)絡(luò)模塊節(jié)點間的低端通信,主要用于智能傳感器和執(zhí)行器的串行通信。LIN總線采用單主多從的組網(wǎng)方式,沒有CAN總線那樣的仲裁機(jī)制,輔以簡單驅(qū)動程序便可實現(xiàn)LIN協(xié)議。LIN節(jié)點由控制芯片和LIN收發(fā)器構(gòu)成,一般通過芯片搭載的UART模塊來實現(xiàn),主節(jié)點控制傳輸時刻,控制整個網(wǎng)絡(luò)的通信,從節(jié)點按照主節(jié)點的調(diào)度進(jìn)行通信。
2?
LIN報文結(jié)構(gòu)
LIN總線上有“顯性”和“隱性”兩種互補的邏輯電平。顯性電平是邏輯 0,隱性電平是邏輯1,總線上實行“線與”。
一幀LIN報文由幀頭(Header)和應(yīng)答(Response)兩部分組成。主機(jī)任務(wù)負(fù)責(zé)發(fā)送幀頭,從機(jī)任務(wù)接收幀頭并對幀頭所包含信息進(jìn)行解析,然后決定是發(fā)送應(yīng)答,還是接收應(yīng)答,還是不作任何反應(yīng)。幀在總線上的傳輸如下圖所示:
幀頭包括同步間隔段、同步段以及受保護(hù)ID段(PID)。應(yīng)答包括數(shù)據(jù)段和校驗和段。LIN報文幀整體結(jié)構(gòu)如下圖所示。
同步間隔段
同步間隔段標(biāo)志一幀的開始,由同步間隔(Break)和間隔符(Break Delimiter)構(gòu)成。同步間隔段至少有13個顯性位,間隔符至少有一個隱形位。
同步段
同步段固定一個字節(jié),值固定為0x55。
在LIN幀中,除了同步間隔段,后面各段都是通過字節(jié)域的格式傳輸?shù)?。LIN的字節(jié)域就是指標(biāo)準(zhǔn)的UART數(shù)據(jù)傳輸格式,字節(jié)域包括1位起始位(顯性)+8位數(shù)據(jù)位+1位停止位(隱性)。數(shù)據(jù)傳輸都是先發(fā)送LSB,最后發(fā)送 MSB。LIN總線將下降沿作為判斷標(biāo)志,通過字節(jié)0x55(01010101b)進(jìn)行同步,從機(jī)節(jié)點上可以采用非高精度時鐘,如果存在偏差,可以通過同步場來調(diào)整,使從機(jī)節(jié)點數(shù)據(jù)的波特率與主機(jī)節(jié)點一致。
受保護(hù)ID段
受保護(hù)ID段由6位幀ID和2位奇偶校驗位組成,幀ID范圍為0x00~0x3F共64個。
幀ID標(biāo)識了幀的類別,從機(jī)任務(wù)根據(jù)幀頭ID作出反應(yīng)(接收/發(fā)送/忽略應(yīng)答),其中P0與P1效驗如下:
P0 = ID0⊕ID1⊕ID2⊕ID4
P1 = ?(ID1⊕ID3⊕ID4⊕ID5)
其中“⊕”代表“異或”運算,“?”代表“取非”運算。
由公式可以看出,PID 不會出現(xiàn)全 0 或全 1 的情況,如果從機(jī)節(jié)點收到了“0xFF”或“0x00”,可判斷傳輸錯誤。LIN總線根據(jù)幀ID的不同,將報文分為信號攜帶幀、診斷幀、保留幀。
應(yīng)注意從機(jī)應(yīng)答幀是一個完整的幀,與幀結(jié)構(gòu)中的“應(yīng)答”不同。
數(shù)據(jù)段
數(shù)據(jù)段包含1~8個字節(jié),可以分為兩種數(shù)據(jù)類型:信號和診斷消息。信號由信號攜帶幀傳遞,診斷消息由診斷幀傳遞。LIN協(xié)議規(guī)定可傳輸?shù)腖IN字節(jié)數(shù)為2、4、8,并不是1~8內(nèi)任意一個數(shù)字。一般應(yīng)用方面會統(tǒng)一字節(jié)數(shù),通常是每幀傳輸8個字節(jié)。
校驗和段
校驗和段是為了對幀傳輸內(nèi)容進(jìn)行效驗。效驗分為標(biāo)準(zhǔn)型校驗與增強(qiáng)型校驗。
將校驗對象的各字節(jié)作帶進(jìn)位二進(jìn)制加法(當(dāng)結(jié)果大于等于256 時就減去255),并將所得最終的和逐位取反,以該結(jié)果作為要發(fā)送的校驗和。接收方根據(jù)校驗和類型,對接收數(shù)據(jù)作相同的帶進(jìn)位二進(jìn)制加法,最終的和不取反,并將該和與接收到的校驗和作加法,如果結(jié)果為0xFF,則校驗和無誤。這在一定程度上保證了數(shù)據(jù)傳輸?shù)恼_性。
采用標(biāo)準(zhǔn)型還是增強(qiáng)型是由主機(jī)節(jié)點管理,發(fā)布節(jié)點和收聽節(jié)點根據(jù)幀ID來判斷采用哪種校驗和。
3?
LIN通信實驗
MM32F5270的UART支持LIN協(xié)議下收發(fā)斷開符號,通過配置UART,根據(jù)總線特征編寫LIN驅(qū)動程序,實現(xiàn)LIN總線通信。相關(guān)代碼參考靈動官網(wǎng)的LibSamples或在此基礎(chǔ)上修改。
3.1 LIN驅(qū)動程序
同步間隔段
配置UART支持LIN協(xié)議下收發(fā)斷開符號:
voidLIN_MASTER_Break(void) { LIN_MASTER_TXBRK_InterruptFlag=0; UART_LINCmd(UART1,ENABLE); UART_SendBreak(UART1); while(0==LIN_MASTER_TXBRK_InterruptFlag) { } }
同步段
主機(jī)發(fā)送0x55:
voidLIN_MASTER_SyncByte(void) { LIN_MASTER_SendData(0x55); }
受保護(hù)ID段
uint8_tLIN_FrameIDToPID(uint8_tFrameID) { uint8_ti=0; uint8_tP0=0,P1=0,PID=0xFF; uint8_tID_BIT[6]= { 0,0,0,0,0,0 }; if(FrameID0x40) ????{ ????????PID?=?FrameID; ????????for?(i?=?0;?i?6;?i++) ????????{ ????????????if?(FrameID?&?(0x01?<
數(shù)據(jù)段
主機(jī)發(fā)送數(shù)據(jù):
voidLIN_MASTER_SendData(uint8_tData) { UART_SendData(UART1,Data); while(RESET==UART_GetFlagStatus(UART1,UART_FLAG_TXC)) { } }
從機(jī)發(fā)送數(shù)據(jù):
voidLIN_SLAVE_SendData(uint8_tData) { UART_SendData(UART1,Data); while(RESET==UART_GetFlagStatus(UART1,UART_FLAG_TXC)) { } }
校驗和段
標(biāo)準(zhǔn)型校驗:
uint8_tLIN_ClassicChecksum(uint8_t*Buffer,uint8_tLength) { uint8_ti=0; uint16_tChecksum=0; for(i=0;i0xFF) { Checksum%=0xFF; } } return(~(uint8_t)(Checksum&0x00FF)); }
增強(qiáng)型校驗:
uint8_tLIN_EnhancedChecksum(uint8_tPID,uint8_t*Buffer,uint8_tLength) { uint8_ti=0; uint16_tChecksum=PID; for(i=0;i0xFF) { Checksum%=0xFF; } } return(~(uint8_t)(Checksum&0x00FF)); }
主機(jī)發(fā)送幀頭
voidLIN_MASTER_SendHeader(uint8_tPID) { LIN_MASTER_Break(); LIN_MASTER_SyncByte(); LIN_MASTER_SendData(PID); }
主機(jī)發(fā)送報文
診斷幀ID包括主機(jī)請求幀0x3C、從機(jī)應(yīng)答幀0x3D,診斷幀用標(biāo)準(zhǔn)型校驗和,其他幀使用增強(qiáng)型校驗和。
voidLIN_Master_SendFrame(uint8_tFrameID,uint8_t*Buffer,uint8_tLength) { uint8_ti=0; uint8_tChecksum=0; uint8_tPID=LIN_FrameIDToPID(FrameID); if((0x3C==FrameID)||(0x3D==FrameID)) { Checksum=LIN_ClassicChecksum(Buffer,Length); } else { Checksum=LIN_EnhancedChecksum(PID,Buffer,Length); } LIN_MASTER_SendHeader(PID); for(i=0;i
從機(jī)發(fā)布數(shù)據(jù)
從機(jī)解析幀頭信息,將主機(jī)發(fā)送的PID得到幀ID,根據(jù)幀ID選擇校驗類型,發(fā)送數(shù)據(jù)段和校驗和段。
voidLIN_SLAVE_Response(uint8_t*Buffer,uint8_tLength) { uint8_ti=0; uint8_tChecksum=0,FrameID=0; FrameID=LIN_PIDToFrameID(LIN_SLAVE_RxBuffer[1]); Checksum=0; if((0x3C==FrameID)||(0x3D==FrameID)) { Checksum=LIN_ClassicChecksum(Buffer,Length); } else { Checksum=LIN_EnhancedChecksum(LIN_SLAVE_RxBuffer[1],Buffer,Length); } for(i=0;i
3.2 主機(jī)程序
主機(jī)UART配置
voidUART_Configure(uint32_tBaudrate) { GPIO_InitTypeDefGPIO_InitStruct; NVIC_InitTypeDefNVIC_InitStruct; UART_InitTypeDefUART_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1,ENABLE); UART_StructInit(&UART_InitStruct); UART_InitStruct.BaudRate=Baudrate; UART_InitStruct.WordLength=UART_WordLength_8b; UART_InitStruct.StopBits=UART_StopBits_1; UART_InitStruct.Parity=UART_Parity_No; UART_InitStruct.HWFlowControl=UART_HWFlowControl_None; UART_InitStruct.Mode=UART_Mode_Rx|UART_Mode_Tx; UART_Init(UART1,&UART_InitStruct); UART_IDLRConfig(UART1,100);/*LINMasterOnly!!!*/ UART_ITConfig(UART1,UART_IT_RX,ENABLE); UART_ITConfig(UART1,UART_IT_TXBRK,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_7); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_7); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU; GPIO_Init(GPIOA,&GPIO_InitStruct); NVIC_InitStruct.NVIC_IRQChannel=UART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); UART_Cmd(UART1,ENABLE); }
主機(jī)中斷服務(wù)子程序
voidUART1_IRQHandler(void) { uint8_ti=0; if(SET==UART_GetITStatus(UART1,UART_IT_TXBRK)) { UART1_RxLength=0; UART_ClearITPendingBit(UART1,UART_IT_TXBRK); UART_ITConfig(UART1,UART_IT_RXIDLE,ENABLE); LIN_MASTER_TXBRK_InterruptFlag=1; } if(SET==UART_GetITStatus(UART1,UART_IT_RX)) { UART1_RxBuffer[UART1_RxLength]=UART1->RDR&0x00FF; UART1_RxLength=(UART1_RxLength+1)%100; UART_ClearITPendingBit(UART1,UART_IT_RX); } if(SET==UART_GetITStatus(UART1,UART_IT_RXIDLE)) { for(i=0;i
主機(jī)例程
主機(jī)間隔500ms發(fā)布和接收數(shù)據(jù),發(fā)送幀ID和數(shù)據(jù)依次累加:
voidUART_LIN_Master_Sample(void) { uint8_ti=0; uint8_tFrameID=0,Mode=0; uint8_tBuffer[2]={0,0}; printf(" Test%s",__FUNCTION__); LIN_MASTER_RxLength=0; LIN_MASTER_RxFinish=0; for(i=0;i100;?i++) ????{ ????????LIN_MASTER_RxBuffer[i]?=?0; ????} ????UART_Configure(19200); ????while?(1) ????{ ????????if?(Mode?==?0) ????????{ ????????????printf(" LIN?Master?Write..."); ????????????LIN_Master_SendFrame(FrameID,?Buffer,?sizeof(Buffer)); ????????} ????????else ????????{ ????????????printf(" LIN?Master?Read...."); ????????????LIN_MASTER_SendHeader(LIN_FrameIDToPID(FrameID)); ????????????while?(0?==?LIN_MASTER_RxFinish) ????????????{ ????????????} ????????????LIN_MASTER_RxFinish?=?0; ????????????printf(" LIN?Master?Rx?Length?:?%d,?Rx?Buffer?:?",?LIN_MASTER_RxLength); ????????????for?(i?=?0;?i?
3.3 從機(jī)程序
從機(jī)UART配置
使能UART LIN總線模式、使能UART接收斷開幀中斷、使能接收單字節(jié)中斷。
voidUART_Configure(uint32_tBaudrate) { GPIO_InitTypeDefGPIO_InitStruct; NVIC_InitTypeDefNVIC_InitStruct; UART_InitTypeDefUART_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1,ENABLE); UART_StructInit(&UART_InitStruct); UART_InitStruct.BaudRate=Baudrate; UART_InitStruct.WordLength=UART_WordLength_8b; UART_InitStruct.StopBits=UART_StopBits_1; UART_InitStruct.Parity=UART_Parity_No; UART_InitStruct.HWFlowControl=UART_HWFlowControl_None; UART_InitStruct.Mode=UART_Mode_Rx|UART_Mode_Tx; UART_Init(UART1,&UART_InitStruct); UART_LINCmd(UART1,ENABLE); UART_ITConfig(UART1,UART_IT_RX,ENABLE); UART_ITConfig(UART1,UART_IT_RXBRK,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE); GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_7); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_7); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_High; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_StructInit(&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU; GPIO_Init(GPIOA,&GPIO_InitStruct); NVIC_InitStruct.NVIC_IRQChannel=UART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); UART_Cmd(UART1,ENABLE); }
從機(jī)中斷服務(wù)子程序
voidUART1_IRQHandler(void) { uint8_ti=0; if(SET==UART_GetITStatus(UART1,UART_IT_RXBRK)) { UART1_RxLength=0; UART_ClearITPendingBit(UART1,UART_IT_RXBRK); UART_ITConfig(UART1,UART_IT_RXIDLE,ENABLE); } if(SET==UART_GetITStatus(UART1,UART_IT_RX)) { UART1_RxBuffer[UART1_RxLength]=UART_ReceiveData(UART1); UART1_RxLength=(UART1_RxLength+1)%100; UART_ClearITPendingBit(UART1,UART_IT_RX); } if(SET==UART_GetITStatus(UART1,UART_IT_RXIDLE)) { for(i=0;i
從機(jī)例程
從機(jī)對幀頭包含信息解析,確定是發(fā)送應(yīng)答,還是接收應(yīng)答。
voidUART_LIN_Slave_Sample(void) { uint8_ti=0; uint8_tChecksum=0,FrameID=0; uint8_tLength=0,Buffer[100]; printf(" Test%s",__FUNCTION__); Length=0; LIN_SLAVE_RxLength=0; LIN_SLAVE_RxFinish=0; for(i=0;i100;?i++) ????{ ????????Buffer[i]?????????????=?0; ????????LIN_SLAVE_RxBuffer[i]?=?0; ????} ????UART_Configure(19200); ????while?(1) ????{ ????????if?(1?==?LIN_SLAVE_RxFinish) ????????{ ????????????LIN_SLAVE_RxFinish?=?0; ????????????if?(0x55?==?LIN_SLAVE_RxBuffer[0]) ????????????{ ????????????????if?(2?==?LIN_SLAVE_RxLength) ????????????????{ ????????????????????LIN_SLAVE_Response(Buffer,?Length); ????????????????} ????????????????else ????????????????{ ????????????????????for?(i?=?2;?i?
3.4 驗證
通過UART接口連接兩塊MM32F5270 MiniBoard,觀察串口調(diào)試助手:
先由主機(jī)發(fā)布數(shù)據(jù),從機(jī)接收數(shù)據(jù),接著由從機(jī)發(fā)布數(shù)據(jù),主機(jī)接收數(shù)據(jù),依次循環(huán)進(jìn)行。根據(jù)截圖信息,主從機(jī)收發(fā)數(shù)據(jù)一致,與程序邏輯相符,兩塊板LIN通信成功。
審核編輯:劉清
-
uart
+關(guān)注
關(guān)注
22文章
1276瀏覽量
103978 -
異步收發(fā)器
+關(guān)注
關(guān)注
0文章
37瀏覽量
11013 -
串行通訊
+關(guān)注
關(guān)注
2文章
79瀏覽量
16651 -
LIN通信
+關(guān)注
關(guān)注
2文章
8瀏覽量
3955 -
MM32
+關(guān)注
關(guān)注
1文章
108瀏覽量
1103
原文標(biāo)題:靈動微課堂 (第280講)|MM32F5270 UART實現(xiàn)LIN通信
文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
MM32F5270平臺ADC注入通道的單周期采樣的實現(xiàn)

基于MM32F5270開發(fā)板獲取雨滴傳感器的數(shù)據(jù)相關(guān)資料介紹
一文解析MM32F5270開發(fā)板+PWM測試與調(diào)制
MM32F5270總線架構(gòu)設(shè)計

基于MM32F5270控制器的I2S音頻播放
【MM32F5270】Keil開發(fā)環(huán)境搭建

MM32F5270平臺ADC注入通道的單周期采樣的實現(xiàn)

MM32F5270平臺ADC注入通道的單周期采樣的實現(xiàn)

評論