LIN总线驱动

2019-07-21 04:33发布

之前编写lin总线的程序,因为是汽车上用的,刚接触,在学习过程中发现lin的资料论坛中挺少的,所以特意分享下,自己在网上找到的资料,希望大家可以多多交流
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
zhouxb
1楼-- · 2019-07-21 05:50
zhouxb
2楼-- · 2019-07-21 10:19
谁知道如何添加附件
zhouxb
3楼-- · 2019-07-21 10:30
 精彩回答 2  元偷偷看……
zhouxb
4楼-- · 2019-07-21 13:31
#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
#include "LCD.h"      

#define BUZZ PORTB_PB5
#define BUZZ_dir DDRB_DDRB5

#define LEDCPU PORTD_PD3
#define LEDCPU_dir DDRD_DDRD3

#define  BUS_CLOCK                   16000000           //总线频率
#define BAUD 9600                    //串口波特率

#define BIT(A,B)      ((A>>B)&0x01)   // A 为变量
                                      // B 表示A中的第几位
#define     ID         0x30           // ID场值为0x30
#define     EN         PORTD_PD5     //LIN使能
#define     EN_dir     DDRD_DDRD5
unsigned int x=0;
Bool a;
                                      
struct message {
  unsigned char identifier;
  unsigned char data[8];
};

struct message msg_send;
struct message msg_get;

// 定义LIN状态
enum lin_state { IDLE, _BREAK, SYNCH, PROTECTED_IDENTIFIER, DATA0, DATA1,
                 DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, CHECKSUM };

// 定义帧结构体
struct frame {
  unsigned char protected_id;
  unsigned char data[8];
  unsigned char check;
  enum lin_state state;
  unsigned char error;
};

struct frame frame_send,frame_receive;

char *xianshi[3] = {
"飞翔科技开发板",
"接收到的数据为:",
};

/*************************************************************/
/*                      初始化锁相环                         */
/*                  使用外部晶振:16MHz                      */
/*                  设置总线频率:16MHz                      */
/*************************************************************/
void INIT_PLL(void)
{
    CPMUPROT=0x26;   //解除时钟配置保护     
   
    CPMUOSC_OSCE=1;    //使能外部晶振
    while(CPMUOSC_OSCPINS_EN==0);    //等待外部晶振使能
   
    CPMUCLKS &=(~0x40);
    CPMUCLKS |= 0x80;        //设置PLLCLK为系统时钟

    //PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1), fbus=PLLCLK/2
    CPMUSYNR=0x01;       //SYNDIV的值为1,
    CPMUREFDIV = 0x81;   //REFDIV的值为1
    CPMUPOSTDIV=0x00;
    CPMUPLL=0x10;

    while(CPMUFLG_LOCK==0); //等待PLLCLK锁定
   
    CPMUPROT=0x00;         //使能时钟配置保护
}

/************************************************************/
/*                    初始化TIM模块                         */
/************************************************************/
void initialize_TIM(void){
  TSCR1_TFFCA = 1;  // 定时器标志位快速清除
  TSCR1_TEN = 1;    // 定时器使能位. 1=允许定时器正常工作; 0=使主定时器不起作用(包括计数器)
  TIOS  = 0xff;      //指定所有通道为输出比较方式
  TCTL1 = 0x00;            // 后四个通道设置为定时器与输出引脚断开
  TCTL2 = 0x00;     // 前四个通道设置为定时器与输出引脚断开
  TIE   = 0x00;     // 禁止所有通道定时中断
  TSCR2 = 0x06;            // 预分频系数pr2-pr0:110,时钟周期为4us,
  TFLG1 = 0xff;            // 清除各IC/OC中断标志位
  TFLG2 = 0xff;     // 清除自由定时器中断标志位
}

/*************************************************************/
/*                        初始化LIN                          */
/*************************************************************/
void INIT_LIN(void)
{
  unsigned char i;
  SCI0BD = BUS_CLOCK/16/BAUD;   //设置SCI0波特率为9600  
  SCI0CR1 = 0x00;        //设置SCI0为正常模式,八位数据位,无奇偶校验
  SCI0CR2 = 0x2c;        //允许接收和发送数据,允许接收中断功能
  SCI0SR2_BRK13 = 1;  
  frame_receive.protected_id=0;
  frame_receive.state=IDLE;
  frame_receive.error=0;
  frame_receive.check=0;
  for (i=0;i<8;i++)
    frame_receive.data[i]=0;
  EN_dir=1;
  EN=1;
  }


/*************************************************************/
/*                     计算奇偶校验位                        */
/*************************************************************/
unsigned char LINCalcParity(unsigned char id)
{
  unsigned char parity, p0,p1;
  parity=id;
  p0=(BIT(parity,0)^BIT(parity,1)^BIT(parity,2)^BIT(parity,4))<<6;     //偶校验位
  p1=(!(BIT(parity,1)^BIT(parity,3)^BIT(parity,4)^BIT(parity,5)))<<7;  //奇校验位
  parity|=(p0|p1);
  return parity;
}

/*************************************************************/
/*                       计算和校验位                        */
/*************************************************************/
unsigned char LINCalcChecksum(unsigned char *data)         
{
  unsigned int sum = 0;
  unsigned char i;

  for(i = 0; i < 8; i++)
  {
    sum += data[i];
    if(sum&0xFF00)
      sum = (sum&0x00FF) + 1;
  }
  sum ^= 0x00FF;         
  return (unsigned char)sum;
}


/*************************************************************/
/*                      LIN接收字节函数                      */
/*************************************************************/
Bool LINGetChar(void)
{
  unsigned volatile char ch;
  
  // LIN接收通道状态
  switch(frame_receive.state)
  {
    case IDLE:
      if(!(SCI0SR1&0x22))
        return(FALSE);  
      if(SCI0DRL)
        return(FALSE);
      break;
    case _BREAK:
      if(!(SCI0SR1&0x20))
        return(FALSE);
      if(SCI0DRL != 0x55)
        return(FALSE);   
      break;  
    case SYNCH:
      if(!(SCI0SR1&0x20))
        return(FALSE);
      ch = SCI0DRL;
      frame_receive.protected_id = ch;
      break;   
    case PROTECTED_IDENTIFIER:
    case DATA0:
    case DATA1:
    case DATA2:
    case DATA3:
    case DATA4:
    case DATA5:
    case DATA6:
      if(!(SCI0SR1&0x20))
        return(FALSE);
      ch = SCI0DRL;
      frame_receive.data[frame_receive.state-PROTECTED_IDENTIFIER] = ch;
      break;
    case DATA7:
      if(!(SCI0SR1&0x20))
        return(FALSE);
      ch = SCI0DRL;
      frame_receive.check = ch;
      break;
    case CHECKSUM:
      return(FALSE);  
  }
  frame_receive.state+=1;
  return(TRUE);
}

/************************************************************/
/*                在液晶上显示接收到的数据                  */
/************************************************************/
void play_data(void)
{
    unsigned char l;
    write_command(0x8A);
    for(l=0;l<8;l++)
       write_Data(frame_receive.data[l]);
}

/************************************************************/
/*                         LIN接收数据                      */
/************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt void LINreceive(void)
{
  if(!LINGetChar())
  {
    frame_receive.error = 1;
    frame_receive.state = IDLE;
  }
}
#pragma CODE_SEG DEFAULT


/*************************************************************/
/*                           主函数                          */
/*************************************************************/
void main(void) {
  DisableInterrupts;
  INIT_PLL();
  initialize_TIM();
  INIT_LIN();
  INIT_PORT();
  LEDCPU_dir=1;
  LEDCPU=0;
  BUZZ_dir=1;
  BUZZ=0;
        EnableInterrupts;


  for(;;)
  {
       if(frame_receive.state == CHECKSUM)
       {
             //判断数据接收是否正确
             if((frame_receive.protected_id == LINCalcParity(ID))&&
                (frame_receive.check == LINCalcChecksum(frame_receive.data)))
                {
                  LEDCPU=~LEDCPU;
                  lcd_clear();
                  lcd_string(0,0,xianshi[0]);
                  lcd_string(1,0,xianshi[1]);
                  play_data(); //显示接收到的数据
                }
        frame_receive.state = IDLE;
            
       }
   
  }
}
wfl1287
5楼-- · 2019-07-21 14:04
谢谢楼主分享
小小的人
6楼-- · 2019-07-21 14:44
感谢楼主

一周热门 更多>