⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 24m

📁 基于CAN总线的NMEA2000协议
💻
字号:
#include <reg51.h>
#include <absacc.h>


/************** SJA1000 内部寄存器地址定义 ********/
#define   CAN_MODE      0            /*	模式寄存器		*/
#define   CAN_CMR       1            /*	命令寄存器		*/
#define   CAN_SR        2            /*	状态寄存器		*/
#define   CAN_IR        3            /*	中断寄存器		*/
#define   CAN_IER       4            /*	中断允许寄存器          */
#define   CAN_BTR0      6            /*	总线定时寄存器0         */
#define   CAN_BTR1      7            /*	总线定时寄存器1         */
#define   CAN_OCR       8            /*	输出控制寄存器          */
#define   CAN_TEST      9
#define   CAN_ALC       11            /*	仲裁丢失捕捉寄存器      */
#define   CAN_ECC       12            /*	错误代码捕捉寄存器      */
#define   CAN_EWLR      13            /*	错误报警限额寄存器      */
#define   CAN_RXERR     14            /*	接受错误计数寄存器      */
#define   CAN_TXERR     15            /*	发送错误计数寄存器      */

#define   CAN_RBSA      30            /*	接受缓存器起始地址寄存器 */
#define   CAN_CDR       31            /*	时钟分频寄存器          */


#define   CAN_ACR0      16            /*	验收代码寄存器0         */
#define   CAN_ACR1      17            /*	验收代码寄存器1         */
#define   CAN_ACR2      18            /*	验收代码寄存器2         */
#define   CAN_ACR3      19            /*	验收代码寄存器3         */
#define   CAN_AMR0      20            /*	验收屏蔽寄存器0         */
#define   CAN_AMR1      21            /*	验收屏蔽寄存器1         */
#define   CAN_AMR2      22            /*	验收屏蔽寄存器2         */
#define   CAN_AMR3      23            /*	验收屏蔽寄存器3         */



unsigned char  tx_data[13]={0x88,0x88,0x88,0x88,0x88,           /*                 */
                            0x11,0x22,0x33,0x44,    /*                 */
                            0x55,0x66,0x77,0x88};  /*  输入输出数据数组 其中tx_data[0]的4,5位
					             在SJA1000中保留未用,在此用来区分输入,输出数据*/
unsigned char  rx_data[13]={0,0,0,0,0,
                            0,0,0,0,
                            0,0,0,0};

unsigned char bdata sr ,ir;    /* 记录SJA1000 内部状态 */
bit getremote=0;		/* 远程帧标记  收到远程帧请求后 置1  */
bit timer0up=0;			/* 秒计时  到1秒 置1  */
unsigned char t0count=0;	
unsigned char mytime;	/* 用于记录0到9的ASCII  每秒增加1,远程帧访问增加1  */


void  can_init( void ) ;
void  can_txdata ( void ) ;
void  can_rxdata ( void ) ;
void  dealmessage_remote( void ) ;

/******************************************************************/
/*******************  write   reg  of  SJA1000     ****************/
/******************************************************************/
void writeSJAreg ( unsigned char SJAadd , unsigned char value)
{
        unsigned char temp_write =  value ;
        XBYTE[ 0x8000 + SJAadd ] =  temp_write ;
}

/******************************************************************/
/*******************  read    reg  of  SJA1000     ****************/
/******************************************************************/
unsigned char readSJAreg( unsigned char SJAadd )
{
        return( XBYTE[ 0x8000 + SJAadd ] );
}


/******************************************************************/
/*******************  set the reg bit of  SJA1000  ****************/
/******************************************************************/
void setREGbit(unsigned char SJAadd , unsigned char value)
{
        unsigned char temp ;
        temp = readSJAreg( SJAadd )  ;
        temp |= value ;
        writeSJAreg( SJAadd , temp ) ;
}


/******************************************************************/
/*******************  clear the reg bit of  SJA1000  ****************/
/******************************************************************/
void clearREGbit(unsigned char SJAadd , unsigned char value)
{
        unsigned char temp ;
        temp = readSJAreg( SJAadd )  ;
        temp &= value ;
        writeSJAreg( SJAadd , temp ) ;
}

/******************************************************************/
/*******************  test bit of  SJA1000  ****************/
/******************************************************************/
unsigned char testREGbit(unsigned char SJAadd , unsigned char value)
{
        unsigned char temp ;
        temp = readSJAreg( SJAadd )  ;
        temp &= value ;
        return (temp) ;
}

/******************************************************************/
/*******************  initializtion of CPU     ****************/
/******************************************************************/
void cpu_init(void)
{
        IE = 0x03;                 /*     EX0=1 */
        IP = 0x01;                 /*    INT0  为高优先*/
        TCON = 0x10 ;              /*   T0 and INT0 */
        TMOD  = 0x01;              /*    T0 方式1 ,定时器 */
        TH0 = 0x3c;
        TL0 = 0x0b0;

        EA = 1;
}


/******************************************************************/
/*******************  initializtion of SJA1000     ****************/
/******************************************************************/
void can_init(void)
{
      //  while (readSJAreg( CAN_MODE )!=  0x01)
              writeSJAreg( CAN_MODE , 0x01 ) ;           /*  进入复位模式  */

        while (readSJAreg( CAN_CDR )!=  0x88)
              writeSJAreg( CAN_CDR , 0x88 ) ;    /*   工作在pelican模式,时钟关闭CLOCK OFF    */

        while( readSJAreg( CAN_RBSA )!=  0x00)
              writeSJAreg( CAN_RBSA , 0x00 );        /*   设置接收缓冲器地址FIFO起始地址为0   */

        while( readSJAreg( CAN_OCR )!=  0x1A)
              writeSJAreg( CAN_OCR , 0x1A );     /*    推挽输出      */

        while( readSJAreg( CAN_BTR0 )!=  0x02)
              writeSJAreg( CAN_BTR0 , 0x02 );     /*  BRT0 = 0x01, BRT1 = 0x1c   500kbps */
        while( readSJAreg( CAN_BTR1 )!=  0x1c)
              writeSJAreg( CAN_BTR1 , 0x1c );    /*   设置为250kbps   BRT0 = 0x03, BRT1 = 0x1c */

        while( readSJAreg( CAN_AMR0 )!=  0xff)
              writeSJAreg( CAN_AMR0 , 0xff );
        while( readSJAreg( CAN_AMR1 )!=  0xff)
              writeSJAreg( CAN_AMR1 , 0xff );
        while( readSJAreg( CAN_AMR2 )!=  0xff)
              writeSJAreg( CAN_AMR2 , 0xff );
        while( readSJAreg( CAN_AMR3 )!=  0xff)
              writeSJAreg( CAN_AMR3 , 0xff );

        while( readSJAreg( CAN_ACR0 )!=  0xff)
              writeSJAreg( CAN_ACR0 , 0xff );
        while( readSJAreg( CAN_ACR1 )!=  0xff)
              writeSJAreg( CAN_ACR1 , 0xff );
        while( readSJAreg( CAN_ACR2 )!=  0xff)
              writeSJAreg( CAN_ACR2 , 0xff );
        while( readSJAreg( CAN_ACR3 )!=  0xff)
              writeSJAreg( CAN_ACR3 , 0xff );

        while( readSJAreg( CAN_IER )!=  0x01)
              writeSJAreg( CAN_IER , 0x01 );       /*   开放,接收中断,出错报警,数据溢出  */

        while( readSJAreg( CAN_TXERR )!=  0x00)
              writeSJAreg( CAN_TXERR , 0x00 );     /*   清除发送错误计数寄存器              */

        while( readSJAreg( CAN_RXERR )!=  0x00)
              writeSJAreg( CAN_RXERR , 0x00 );     /*   清除接收错误计数寄存器              */

        while( readSJAreg( CAN_MODE )!=  0x0c)
              writeSJAreg( CAN_MODE , 0x0c );     /*    单向滤波器,自检测模式      */

}

/*************************************************************/
/*************          发送子程序            ****************/
/*************        通过tx_data[]传参       ****************/
/*************  使用此程序前要预先将数据放入tx_data[]中 ******/
/*************************************************************/
void can_txdata (  )
{
        unsigned char i , length  ;

        sr =  CAN_SR;

        do{  ;}
        while(!(sr^3)) ;               /*   判断上次发送是否完成,未完成,等待  */

        do{  ;}
        while(sr^2) ;               /*   判断发送缓冲器是否锁定,锁定,等待  */

      //  if(sr^1)
      //  writeSJAreg( CAN_CMR , 0X0C );          /*   清除数据溢出  释放接收缓冲器*/
     //   do{ can_rxdata ( );}
      //  while(readSJAreg(29)) ;

        switch(tx_data[0]&0xC0)
        {
                case    0x00:  /*标准帧、数据帧*/
                               length  = ( tx_data[0] & 0x0f ) ;
                               if(length>8)   length  =  8;
                               length  +=  3;  break ;
                case    0x40:  /*标准帧、远程帧*/
                               length  =   3;  break ;
                case    0x80:  /*扩展帧、数据帧*/
                               length  = ( tx_data[0] & 0x0f ) ;
                               if(length>8)   length  =  8;
                               length  +=  5;  break ;
                case    0xc0:  /*扩展帧、远程帧*/
                               length  =   5;  break ;
                default: break;
        }

        for(i=0 ; i<length ; i++)
        {
                writeSJAreg( 16+i , tx_data[i] );
        }

        writeSJAreg( CAN_CMR , 0X11 );       /*   启动自收发*/
       // writeSJAreg( CAN_CMR , 0X02 );

        ir    =   readSJAreg( CAN_IR ) ;
}



/*************************************************************/
/*************     接收子程序                 ****************/
/*************  将接收到的数据存入rx_data[]中      ***********/
/*************************************************************/
void can_rxdata ( void )
{
        unsigned char  length;
        unsigned char  i;

        rx_data[0] = length = readSJAreg( 16 ) ;


        switch(length&0xC0)
        {
                case    0x00:  /*标准帧、数据帧*/
                               length  = ( rx_data[0] & 0x0f ) ;
                               if(length>8)   length  =  8;
                               length  +=  3;  break ;
                case    0x40:  /*标准帧、远程帧*/
                               length  =   3;  break ;
                case    0x80:  /*扩展帧、数据帧*/
                               length  = ( rx_data[0] & 0x0f ) ;
                               if(length>8)   length  =  8;
                               length  +=  5;  break ;
                case    0xc0:  /*扩展帧、远程帧*/
                               length  =   5;  break ;
                default: break;
        }


        for (i=0;i<length;i++)
        {
                rx_data[i] = readSJAreg( 16+ i ) ;
        }

        writeSJAreg( CAN_CMR , 0X0c );     /*  接收完毕,释放接收缓冲区  */
}

/*********************************************************/
/*************        接收中断程序      ******************/
/*********************************************************/
void int0() interrupt 0
{
       EA = 0 ;                                /*   关中断    */

           can_rxdata ( );
           getremote =1;
       EA   =   1 ;

}

/*********************************************************/
/*************       定时器中断程序      ******************/
/*********************************************************/
void timer0() interrupt 1
{
       EA = 0 ;                                /*   关中断    */

        t0count++;
        if(t0count>=20)
        {
             P2 = 0xff;
             timer0up = 1;
             t0count = 0;
        }
        
        if(mytime>=57)
        {mytime = 0x2f;}
        TH0 = 0x3c;
        TL0 = 0xb0;
       EA   =   1 ;

}

/*********************************************************/
/*************       命令处理程序       ******************/
/*********************************************************/
void  dealmessage_remote( void )
{
char j ;

//    tx_data[13]={0x88,0xf0,0xf0,0xf0,0x88,           /* 上位机显示一串1          */
// /                0x13,0x35,0x33,0x30,                /* 1/3  5  3   0     */
//                 0x39,0x30,0x32,0x4e};               /*  9   0  2   N     */
    for (j=0;j<50;j++);
       tx_data[5] =  0x13;
       tx_data[6] =  0x35;
       tx_data[7] =  0x33;
       tx_data[8] =  0x30;
       tx_data[9] =  0x39;
       tx_data[10] =  0x30;
       tx_data[11] =  0x32;
       tx_data[12] =  0x4e;
    can_txdata (  );

   for (j=0;j<50;j++);

//   tx_data[13]={0x88,0xf0,0xf0,0xf0,0x88,           /* 地理坐标          */
//                 0x23,0x30,0x30,0x31,                /* 2/3  0  0   1     */
  //               0x35,0x30,0x34,0x30};               /*  5   0  4   0     */
       tx_data[5] =  0x23;
       tx_data[6] =  0x30;
       tx_data[7] =  0x30;
       tx_data[8] =  0x31;
       tx_data[9] =  0x35;
       tx_data[10] =  0x30;
       tx_data[11] =  0x34;
       tx_data[12] =  0x30;
    can_txdata (  );

   for (j=0;j<50;j++);

 //   tx_data[13]={0x88,0xf0,0xf0,0xf0,0x88,           /* 地理坐标          */
 //                0x33,0x57,0x32,0x32,                /* 3/3  W  2   2     */
 //                0x32,0x32,0x32,0x32};               /*  2   2  2   2     */
 mytime++;
       tx_data[5] =  0x33;
       tx_data[6] =  0x57;
       tx_data[7] =  0x32;
       tx_data[8] =  0x32;
       tx_data[9] =  0x32;
       tx_data[10] =  mytime;
       tx_data[11] =  0x32;
       tx_data[12] =  mytime;
    can_txdata (  );


}

main ()
{  char i,j ,temp=0;
   
   for(i=0;i<255;i++)
   for (j=0;j<255;j++);

   cpu_init();
   P2 =0xc0;					/*硬件复位SJA1000*/
   for (j=0;j<100;j++);
   P2 =0xff;
   can_init(  ) ;


   writeSJAreg( CAN_TEST , 0xaa );
   temp =  readSJAreg( CAN_TEST ) ;

   writeSJAreg( CAN_TEST , 0x55 );
   temp =  readSJAreg( CAN_TEST ) ;
   getremote =0;
   mytime = 0x2f;

   for (j=0;j<255;j++);
   while(1)
   {
       if(getremote)  //(timer0up)&&
       {
           if( 0x88 ==  rx_data[1])
           {
                switch(rx_data[0]&0xC0)
                {
                        case    0x00:  /*标准帧、数据帧*/
                                     break ;
                        case    0x40:  /*标准帧、远程帧*/
                                     break ;
                        case    0x80:  /*扩展帧、数据帧*/
                                     break ;
                        case    0xc0:  /*扩展帧、远程帧*/
                                     dealmessage_remote();
                                     P2 = 0x60;			/*点发光二极管*/
                                     getremote = 0 ;
                                     break ;
                        default: break;
                }

           }

           
       }

       if(timer0up)     //      (!getremote)&&
       {
            dealmessage_remote();
            timer0up =0;
       }
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -