S32K LIN Slave&Master(no SDK)

4 篇文章 0 订阅
3 篇文章 1 订阅

S32K_LIN_Master&Slave_driver(寄存器配置no SDK)

S32K14X LIN BUS 主从驱动配置(纯C no SDK)

一、工作原理
1、LIN BUS通信原理简介
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、LPUART收发原理
在这里插入图片描述
在这里插入图片描述
3、基于LPUART硬件电路(TJA1021收发器)
在这里插入图片描述
二、代码编写

/*
 * ===================================================
 * Function :  LPUART0 LIN init(Master & Salve) 
 * 1. Clock Src= 1 (SOSCDIV2_CLK),set baud rate = 9600 
 * 2. 8 bit format  
 * 3. 1 stop bit
 * 4. LIN Break Detect Interrupt 
 * 5. Idle Line Interrupt 
 * 6. receives interrupt 
 * Coder :  djf
 * Date/Time :  2020/07/25 
 * ===================================================
 */

void LPUART0_LIN_init(void)        
{
	PCC->PCCn[PCC_LPUART0_INDEX] &= ~PCC_PCCn_CGC_MASK;    /* Ensure clk disabled for config */
	PCC->PCCn[PCC_LPUART0_INDEX] |= PCC_PCCn_PCS(1)        /* Clock Src= 1 (SOSCDIV2_CLK) */
                            	 |  PCC_PCCn_CGC_MASK;     /* Enable clock for LPUART1 regs */
    
    LPUART0->GLOBAL |= LPUART_GLOBAL_RST_MASK;   /* RST=1: Module is reset */
	LPUART0->GLOBAL &= ~LPUART_GLOBAL_RST_MASK;  /* RST=0: Module is not reset */
    
    LPUART0->BAUD &= ~LPUART_BAUD_SBNS_MASK;     /* SBNS=0: One stop bit */
	LPUART0->BAUD &= ~LPUART_BAUD_SBR_MASK;      /* Clear SBR field */
	LPUART0->BAUD = LPUART_BAUD_SBR(0x34)|    /* Initialize for 9600 baud, 1 stop. SBR=52 (0x34): baud divisor = 8M/9600/16 = ~52 */
                	LPUART_BAUD_OSR(15) |     /* OSR=15: Over sampling ratio = 15+1=16 */
					LPUART_BAUD_LBKDIE_MASK;  // LIN Break Detect Interrupt Enable, Hardware interrupt requested when STAT[LBKDIF] flag is 1.						
                                              /* SBNS=0: One stop bit */
                                              /* BOTHEDGE=0: receiver samples only on rising edge */
                                              /* M10=0: Rx and Tx use 7 to 9 bit data characters */
                                              /* RESYNCDIS=0: Resync during rec'd data word supported */
                                              /* LBKDIE, RXEDGIE=0: interrupts disable */
                                              /* TDMAE, RDMAE, TDMAE=0: DMA requests disabled */
                                              /* MAEN1, MAEN2,  MATCFG=0: Match disabled */
    
    LPUART0->STAT &= ~LPUART_STAT_MSBF_MASK;     /* MSBF=0: LSB (bit0) is the first bit */
	LPUART0->STAT |= LPUART_STAT_BRK13_MASK |    /* BRK13=1: Break character is transmitted with length of 13 bit times */
                     LPUART_STAT_LBKDE_MASK;     /* LBKDE=1: LIN break detect is enabled */

	LPUART0->CTRL =	LPUART_CTRL_ORIE_MASK  |    // Overrun Interrupt Enable
                    LPUART_CTRL_PEIE_MASK  |    // Framing Error Interrupt Enable
                    LPUART_CTRL_RIE_MASK   |    // Receiver Interrupt Enable
                    LPUART_CTRL_IDLECFG(7) |    // 128 idle characters
                    LPUART_CTRL_ILT_MASK   |    /* ILT=1: Idle char bit count starts after start bit */
                    LPUART_CTRL_ILIE_MASK  |    // Idle Line Interrupt Enable
                    LPUART_CTRL_RE_MASK    |    /* RE=1: Receiver enabled */ 
					LPUART_CTRL_TE_MASK;        /* TE=1: Transmitter enabled, Enable transmitter & receiver, no parity, 8 bit char: */                                          
                    // LPUART_CTRL_LOOPS_MASK;   
                    // LPUART_CTRL_RSRC_MASK;                                                      
                    
}
void LIN_SendHeader(uint8_t PID)
{			       
    while((LPUART0->STAT & LPUART_STAT_TDRE_MASK) == 0);    /* Wait until Transmit data buffer become empty */
    LPUART0->CTRL |= LPUART_CTRL_SBK_MASK;                  /* SBK=1: Queue break character(s) to be sent */  
	LPUART0->CTRL &= ~LPUART_CTRL_SBK_MASK;                 /* SBK=0: Normal transmitter operation */    
    
    while((LPUART0->STAT & LPUART_STAT_TDRE_MASK) == 0);    /* Wait until Transmit data buffer become empty */ 
	LPUART0->DATA = 0x55;                                   /* Transmit Sync Byte */
    
	while((LPUART0->STAT & LPUART_STAT_TDRE_MASK) == 0);    /* Wait until Transmit data buffer become empty */
	LPUART0->DATA = PID;                                    /* transmit PID */
    
    while((LPUART0->STAT & LPUART_STAT_TC_MASK) == 0);      /* transmission activity complete */
    
}
void LIN_SendResponse(uint8_t *SendArray)
{    
    uint8_t i = 0;             
                                   
    for(i=0; i<9; i++)
    {           
        while((LPUART0->STAT & LPUART_STAT_TDRE_MASK) == 0);        
        LPUART0->DATA = SendArray[i];     
    }    
    while((LPUART0->STAT & LPUART_STAT_TC_MASK) == 0);     /* transmission activity complete*/     
                                                                    
}                      

/**********************************************************/
/* Name: void LIN_Slave_RxTxFrame(void)                   */
/* Function: Slave receives response and sends response,  */
/*           Slave receives Header                        */
/* Modify Date: 2020/07/25                                */
/* Parameter:                                             */
/*                                                        */
/*                                                        */
/* Result:                                                */
/* Coder:      djf                                        */
/**********************************************************/   

void LIN_RxTxFrame(void)
{       
    uint8_t i = 0;  
    uint8_t RecOkflag = 0;  
    uint8_t LinRecbuffer = 0;
    static uint8_t BreakOkflag = 0;
    static uint8_t recHeaderNu = 0;                  
    static uint8_t recResponseNu = 0;           
   // static uint8_t sendResponseNu = 0;
    static uint8_t recResponseFlag = 0;         /* Receive response flag */   
    static uint8_t sendResponseFlag = 0; 
    static uint8_t RecResponseFinish = 0;       /* Receive the response completion flag */
    
       
    if((LPUART0->STAT & LPUART_STAT_LBKDIF_MASK) == LPUART_STAT_LBKDIF_MASK)  /* LIN break character detected? */
	{
		LPUART0->STAT |= LPUART_STAT_LBKDIF_MASK;       /* Write 1 to clear flag */
		LPUART0->STAT &= ~LPUART_STAT_LBKDE_MASK;       /* LBKDE=0: LIN break detect is disabled */    
        BreakOkflag = 1;       
	}
    else
    {   
       
    }
 
    if((LPUART0->STAT & LPUART_STAT_IDLE_MASK) == LPUART_STAT_IDLE_MASK)      //Idle line was detected
    {
        LPUART0->STAT |= LPUART_STAT_IDLE_MASK;                       //write logic 1 to the Idle flag
        RecOkflag = 1;             
    }
    else
    {
       
    } 
    
    if((LPUART0->STAT & LPUART_STAT_FE_MASK) == LPUART_STAT_FE_MASK)      //Framing error
    {
        LPUART0->STAT |= LPUART_STAT_FE_MASK;                     //write logic 1 to the FE flag
        RecOkflag = 1;     
    }
    else
    {
       
    }
    
    if((LPUART0->STAT & LPUART_STAT_OR_MASK) == LPUART_STAT_OR_MASK)      //Receive overrun
    {
        LPUART0->STAT |= LPUART_STAT_OR_MASK;                     //write logic 1 to the OR flag
        RecOkflag = 1;       
    }
    else
    {
       
    }     

    
    if(((LPUART0->STAT & LPUART_STAT_RDRF_MASK) == LPUART_STAT_RDRF_MASK))
    {       
        LinRecbuffer = (uint8_t)LPUART0->DATA; 
        if(!RecOkflag)                                // No overflow, no frame error start receiving
        {   
            if(1==BreakOkflag)   
            {           
                LinRecHeader[recHeaderNu] = LinRecbuffer;                       /* receive 0x55、PID */         
                recHeaderNu++;                             

                if(0x55!=LinRecHeader[0])                    /* The clear count flag is not equal to 0x55 when receiving the synchronization segment */
                {
                    recHeaderNu = 0;                      
                    BreakOkflag = 0;    
                }
                else
                {
                    if(2==recHeaderNu)
                    {                                             
                        switch(LinRecHeader[1])
                        {
                            case PIDrxResp:                              // Receive the response header                                
                                recResponseFlag = 1;
                                sendResponseFlag = 0;
                                break;
                                
                            case PIDtxResp:                              // Send the response header
                                recResponseFlag = 0;
                                sendResponseFlag = 1;
                                LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
                                break;
                                
                            case HCMPID:  
                                recResponseFlag = 1;  
                                sendResponseFlag = 0;
                                break;
                                
                            default:
                                LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
                                break; 
                        }  
                        
                        recHeaderNu = 0;                      
                        BreakOkflag = 0;                       // Headers have been received. Clear the break flag and wait for the next Header to start 
                        
                    }
                    else
                    {

                    }
                }            
            }
            else
            {               
                if(1==recResponseFlag)
                {
                    LinRecResponseArray[recResponseNu] =  LinRecbuffer;               // Receive the response data segment
                    recResponseNu++;
                    if(8<recResponseNu)
                    {                    
                        recResponseNu = 0;                    
                        recResponseFlag = 0;
                        RecResponseFinish = 1;
                        LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;                    // LIN break detect is enable
                    }
                    else
                    {
                        
                    } 
                }
                else
                {

                }  				

                if(1==RecResponseFinish)                    /* Response receiving completion flag */
                {
                    RecResponseFinish = 0;            
                    CheckSum = LINCalcChecksum(LinRecResponseArray, LinRecHeader[1]) + LinRecResponseArray[8];      /* Calculate whether the sum of the validations equals 0xFF */
                    if(0xFF==CheckSum)
                    {
                        for(i=0; i<8; i++)
                        {                     
                            LinRec02Data[i] =  LinRecResponseArray[i];                
                        
                        }                                                 
                    }
                    else
                    {
                         
                    }                                                                    
                }
                else
                {
                     
                } 
                
            }      
        
        }
        else
        {
           
        }
        
    }
    else
    {
    
    }        
  
    if(1==sendResponseFlag)                               //Send response
    {
        LinSendResponseArray[8] = 0xFF - LINCalcChecksum(LinSendResponseArray, PIDtxResp); 
        LIN_SendResponse(LinSendResponseArray);
        sendResponseFlag = 0;
    }
    else
    {

    } 

    if(1==RecOkflag)
    {
        RecOkflag = 0;
        recResponseFlag = 0;
        recHeaderNu = 0;
        recResponseNu = 0;  
        BreakOkflag = 0; 
        LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
    }
    else
    {
    
    }      
                                                                                       
}    
   
/*******************************************************/
/* Name: void LinMasterSchedule(void)                  */
/* Function: LinMasterSchedule                         */
/* Modify Date: 2020/07/25                             */
/* Parameter:                                          */
/*                                                     */
/*                                                     */
/* Result:                                             */
/* Coder:      djf                                     */
/*******************************************************/   
    
void LinSchedule(void)
{
    static uint8_t LinScheduleTimer = 0;		    	      
	 
    if(2>LinScheduleTimer)
    {
        LinScheduleTimer++;
    }
    else
    {
        LinScheduleTimer = 0;
        LinSendResponseArray[1]++;
        LinSendResponseArray[2] = 0xFF - LinSendResponseArray[1];
    }                       
    
    switch(LinScheduleTimer)
    {
        case (HCM):
        {       	   			             
            if(200>LinSend16Data[1])
            {
                LinSend16Data[1]++;
            }
            else
            {
                LinSend16Data[1] = 0;
                
            }
            LinSend16Data[2] = 0xFF-LinSend16Data[1];
            
            LPUART0->CTRL &= ~LPUART_CTRL_RE_MASK;         //Block the receive and interrupt,Reduced interrupt scheduling time
            LPUART0->CTRL &= ~LPUART_CTRL_RIE_MASK;           
            LinSend16Data[8] = 0xFF - LINCalcChecksum(LinSend16Data, HCMPID);      //CheckSum
            LIN_SendHeader(HCMPID);                
            LIN_SendResponse(LinSend16Data);
           

        }
            break; 

        case (FCP):               //receiving response
        {							             
            LPUART0->CTRL |= LPUART_CTRL_RIE_MASK;
            LPUART0->CTRL |= LPUART_CTRL_RE_MASK;              
            LIN_SendHeader(PIDrxResp);	                    
        }
            break;    
            
        case (PM):               //send response
        {		             			            
            LPUART0->CTRL |= LPUART_CTRL_RIE_MASK;
            LPUART0->CTRL |= LPUART_CTRL_RE_MASK;           
            LIN_SendHeader(PIDtxResp);	                         
        }
            break;  	          
        
        default:             				            
            break;        
    }       	 		               
  
}
#define HCMPID           0xD6              //ID 0x16    
#define PIDrxResp        0x42              //ID 0x02        
#define PIDtxResp        0xA3              //ID 0x23       
#define HCM             0   
#define FCP             1           //0+3   
#define PM              2           //0+3+2  
void LPUART0_NVIC_init_IRQs(void)
{
	S32_NVIC->ICPR[1] = (uint32_t)(1 << (LPUART0_RxTx_IRQn % 32)); 
	S32_NVIC->ISER[(uint32_t)(LPUART0_RxTx_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(LPUART0_RxTx_IRQn) & (uint32_t)0x1FU));
	S32_NVIC->IP[LPUART0_RxTx_IRQn] = 0xC;             
}
void LPUART0_RxTx_IRQHandler(void)
{          
    LIN_RxTxFrame();
}

三、总结
以上代码是基于LPUART编写的LIN 主节点、从节点驱动程序,从节点接收报头和响应是放在LPUART接收发送中断函数里面,主节点调度是放在主循环里面轮询,调度周期为100ms。上面例程包含了主节点和从节点收发驱动,初始化配置里面配置了break检测中断,Idle检测中断,error帧检测中断,overrun中断。LIN的初始化配置相比CAN初始化简单不少,重点在于从节点接收和发送驱动程序编写,大伙在调试时这方面重点看下。

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值