单片机/MCU论坛
直播中

djf

12年用户 176经验值
擅长:可编程逻辑 模拟技术 嵌入式技术 处理器/DSP 控制/MCU EDA/IC设计 可编程逻辑 嵌入式技术 模拟技术 EDA/IC设计 处理器/DSP 控制/MCU
私信 关注

S32K LIN Slave&Master(no SDK)

本帖最后由 yelangdjf 于 2020-8-20 10:21 编辑

S32K14X LIN BUS 主从驱动配置(纯C no SDK)
一、工作原理
1、LIN BUS通信原理简介
EM截图_2020819105936.png
EM截图_202081911537.png
EM截图_2020819111050.png
2、LPUART收发原理
EM截图_2020819111825.png
EM截图_2020819111852.png
3、基于LPUART硬件电路(TJA1021收发器)
EM截图_202081911224.png
二、代码编写
  1. /*
  2. * ===================================================
  3. * Function :  LPUART0 LIN init(Master & Salve)
  4. * 1. Clock Src= 1 (SOSCDIV2_CLK),set baud rate = 9600
  5. * 2. 8 bit format  
  6. * 3. 1 stop bit
  7. * 4. LIN Break Detect Interrupt
  8. * 5. Idle Line Interrupt
  9. * 6. receives interrupt
  10. * Coder :  djf
  11. * Date/Time :  2020/07/25
  12. * ===================================================
  13. */

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

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

  1. /**********************************************************/
  2. /* Name: void LIN_Slave_RxTxFrame(void)                   */
  3. /* Function: Slave receives response and sends response,  */
  4. /*           Slave receives Header                        */
  5. /* Modify Date: 2020/07/25                                */
  6. /* Parameter:                                             */
  7. /*                                                        */
  8. /*                                                        */
  9. /* Result:                                                */
  10. /* Coder:      djf                                        */
  11. /**********************************************************/   

  12. void LIN_RxTxFrame(void)
  13. {      
  14.     uint8_t i = 0;  
  15.     uint8_t RecOkflag = 0;  
  16.     uint8_t LinRecbuffer = 0;
  17.     static uint8_t BreakOkflag = 0;
  18.     static uint8_t recHeaderNu = 0;                  
  19.     static uint8_t recResponseNu = 0;           
  20.    // static uint8_t sendResponseNu = 0;
  21.     static uint8_t recResponseFlag = 0;         /* Receive response flag */   
  22.     static uint8_t sendResponseFlag = 0;
  23.     static uint8_t RecResponseFinish = 0;       /* Receive the response completion flag */
  24.    
  25.       
  26.     if((LPUART0->STAT & LPUART_STAT_LBKDIF_MASK) == LPUART_STAT_LBKDIF_MASK)  /* LIN break character detected? */
  27.         {
  28.                 LPUART0->STAT |= LPUART_STAT_LBKDIF_MASK;       /* Write 1 to clear flag */
  29.                 LPUART0->STAT &= ~LPUART_STAT_LBKDE_MASK;       /* LBKDE=0: LIN break detect is disabled */   
  30.         BreakOkflag = 1;      
  31.         }
  32.     else
  33.     {   
  34.       
  35.     }

  36.     if((LPUART0->STAT & LPUART_STAT_IDLE_MASK) == LPUART_STAT_IDLE_MASK)      //Idle line was detected
  37.     {
  38.         LPUART0->STAT |= LPUART_STAT_IDLE_MASK;                       //write logic 1 to the Idle flag
  39.         RecOkflag = 1;            
  40.     }
  41.     else
  42.     {
  43.       
  44.     }
  45.    
  46.     if((LPUART0->STAT & LPUART_STAT_FE_MASK) == LPUART_STAT_FE_MASK)      //Framing error
  47.     {
  48.         LPUART0->STAT |= LPUART_STAT_FE_MASK;                     //write logic 1 to the FE flag
  49.         RecOkflag = 1;     
  50.     }
  51.     else
  52.     {
  53.       
  54.     }
  55.    
  56.     if((LPUART0->STAT & LPUART_STAT_OR_MASK) == LPUART_STAT_OR_MASK)      //Receive overrun
  57.     {
  58.         LPUART0->STAT |= LPUART_STAT_OR_MASK;                     //write logic 1 to the OR flag
  59.         RecOkflag = 1;      
  60.     }
  61.     else
  62.     {
  63.       
  64.     }     

  65.    
  66.     if(((LPUART0->STAT & LPUART_STAT_RDRF_MASK) == LPUART_STAT_RDRF_MASK))
  67.     {      
  68.         LinRecbuffer = (uint8_t)LPUART0->DATA;
  69.         if(!RecOkflag)                                // No overflow, no frame error start receiving
  70.         {   
  71.             if(1==BreakOkflag)   
  72.             {           
  73.                 LinRecHeader[recHeaderNu] = LinRecbuffer;                       /* receive 0x55、PID */         
  74.                 recHeaderNu++;                             

  75.                 if(0x55!=LinRecHeader[0])                    /* The clear count flag is not equal to 0x55 when receiving the synchronization segment */
  76.                 {
  77.                     recHeaderNu = 0;                     
  78.                     BreakOkflag = 0;   
  79.                 }
  80.                 else
  81.                 {
  82.                     if(2==recHeaderNu)
  83.                     {                                             
  84.                         switch(LinRecHeader[1])
  85.                         {
  86.                             case PIDrxResp:                              // Receive the response header                                
  87.                                 recResponseFlag = 1;
  88.                                 sendResponseFlag = 0;
  89.                                 break;
  90.                                 
  91.                             case PIDtxResp:                              // Send the response header
  92.                                 recResponseFlag = 0;
  93.                                 sendResponseFlag = 1;
  94.                                 LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
  95.                                 break;
  96.                                 
  97.                             case HCMPID:  
  98.                                 recResponseFlag = 1;  
  99.                                 sendResponseFlag = 0;
  100.                                 break;
  101.                                 
  102.                             default:
  103.                                 LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
  104.                                 break;
  105.                         }  
  106.                         
  107.                         recHeaderNu = 0;                     
  108.                         BreakOkflag = 0;                       // Headers have been received. Clear the break flag and wait for the next Header to start
  109.                         
  110.                     }
  111.                     else
  112.                     {

  113.                     }
  114.                 }            
  115.             }
  116.             else
  117.             {               
  118.                 if(1==recResponseFlag)
  119.                 {
  120.                     LinRecResponseArray[recResponseNu] =  LinRecbuffer;               // Receive the response data segment
  121.                     recResponseNu++;
  122.                     if(8
  123.                     {                    
  124.                         recResponseNu = 0;                    
  125.                         recResponseFlag = 0;
  126.                         RecResponseFinish = 1;
  127.                         LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;                    // LIN break detect is enable
  128.                     }
  129.                     else
  130.                     {
  131.                         
  132.                     }
  133.                 }
  134.                 else
  135.                 {

  136.                 }                                 

  137.                 if(1==RecResponseFinish)                    /* Response receiving completion flag */
  138.                 {
  139.                     RecResponseFinish = 0;            
  140.                     CheckSum = LINCalcChecksum(LinRecResponseArray, LinRecHeader[1]) + LinRecResponseArray[8];      /* Calculate whether the sum of the validations equals 0xFF */
  141.                     if(0xFF==CheckSum)
  142.                     {
  143.                         for(i=0; i<8; i++)
  144.                         {                     
  145.                             LinRec02Data[i] =  LinRecResponseArray[i];               
  146.                         
  147.                         }                                                
  148.                     }
  149.                     else
  150.                     {
  151.                         
  152.                     }                                                                    
  153.                 }
  154.                 else
  155.                 {
  156.                      
  157.                 }
  158.                
  159.             }      
  160.         
  161.         }
  162.         else
  163.         {
  164.            
  165.         }
  166.         
  167.     }
  168.     else
  169.     {
  170.    
  171.     }        
  172.   
  173.     if(1==sendResponseFlag)                               //Send response
  174.     {
  175.         LinSendResponseArray[8] = 0xFF - LINCalcChecksum(LinSendResponseArray, PIDtxResp);
  176.         LIN_SendResponse(LinSendResponseArray);
  177.         sendResponseFlag = 0;
  178.     }
  179.     else
  180.     {

  181.     }

  182.     if(1==RecOkflag)
  183.     {
  184.         RecOkflag = 0;
  185.         recResponseFlag = 0;
  186.         recHeaderNu = 0;
  187.         recResponseNu = 0;  
  188.         BreakOkflag = 0;
  189.         LPUART0->STAT |= LPUART_STAT_LBKDE_MASK;
  190.     }
  191.     else
  192.     {
  193.    
  194.     }      
  195.                                                                                        
  196. }   
  197.    
  1. void LPUART0_RxTx_IRQHandler(void)
  2. {         
  3.     LIN_RxTxFrame();
  4. }
  1. void LPUART0_NVIC_init_IRQs(void)
  2. {
  3.         S32_NVIC->ICPR[1] = (uint32_t)(1 << (LPUART0_RxTx_IRQn % 32));
  4.         S32_NVIC->ISER[(uint32_t)(LPUART0_RxTx_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(LPUART0_RxTx_IRQn) & (uint32_t)0x1FU));
  5.         S32_NVIC->IP[LPUART0_RxTx_IRQn] = 0xC;            
  6. }

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



    S32K_LIN_drivers.rar (2020-8-20 10:04 上传)

    5.03 KB, 下载次数: 42

    附件是.C文件,可添加在《S32K144 CAN FIFO Driver》工程里面进行调试,基于IAR

更多回帖

发帖
×
20
完善资料,
赚取积分