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

📄 can.c

📁 英飞凌的CAN驱动。英飞凌的CAN非常复杂
💻 C
字号:
#include<XC886CLM.H>
#include<stdio.h>
#include "can.h"
//uchar tmp;
//#define _can_0_
typedef struct can_struct
{
uchar leibie;//侦的类别 0标准 1扩展
ulong signal;
unsigned char length;
unsigned char data0[8];
} can_data;
can_data a,b;



void can_write(uword addr,ulong value)
{
CAN_ADL=(addr>>2)&0xff;
CAN_ADH=(addr>>10)&0x0f;
CAN_DATA0=value&0xff;
CAN_DATA1=(value>>8)&0xff;
CAN_DATA2=(value>>16)&0xff;
CAN_DATA3=(value>>24)&0xff;
CAN_ADCON=0xf1;
while(BSY==1);
//BSY=0;
}
//reg 0 2 4 8  选择写那个寄存器
void can_write_0(uword addr,uchar value,uchar reg)
{
  uchar i=1;
  CAN_ADL=(addr>>2)&0xff;
CAN_ADH=(addr>>10)&0x0f;
 switch (reg)
 {
 case 0:
         V0=1;
         CAN_DATA0=value;break;
 case 1:
         V1=1;
         CAN_DATA1=value;break;
  case 2:
         V2=1;
         CAN_DATA2=value;break;
  case 3:
         V3=1;
         CAN_DATA3=value;break;

 }
 //AUAD=0X01;
 RWEN=1;
 while(BSY==1);
}


void can_read(uword addr)
{
  CAN_ADL=(addr>>2)&0xff;
CAN_ADH=(addr>>10)&0x0f;
 RWEN=0;
 while(BSY==1);
// BSY=0;
}
 //置位
void set_bit(uword addr,uchar bitnum,uchar value)
{
  uchar i=1;
  //can_read(addr);
  CAN_ADL=(addr>>2)&0xff;
  CAN_ADH=(addr>>10)&0x0f;
   if(bitnum<8)  {
   
   if(value)
   CAN_DATA0|=(i<<bitnum);
   else
   CAN_DATA0&=~(i<<bitnum);
   V0=1;
   }
   else if(bitnum>=8&&bitnum<16)
   {
     
     if(value)
     CAN_DATA1|=(i<<(bitnum-8));
     else
     CAN_DATA1&=~(i<<(bitnum-8));
       V1=1;
     }
      else if(bitnum>=16&&bitnum<24)
      {
      
      if(value)
     CAN_DATA2|=(i<<(bitnum-16));
     else
       CAN_DATA2&=~(i<<(bitnum-16));
       V2=1;
     }
      else if(bitnum>=24&&bitnum<32)
      {
   
      if(value)
     CAN_DATA3|=(i<<(bitnum-24));
     else
     CAN_DATA3&=~(i<<(bitnum-24));
     V3=1;
     }

       RWEN=1;
 while(BSY==1);
}
     //读相应的位
    uchar read_bit(uword addr,uchar bitnum)
    {
      uchar i=1;
  //can_read(addr);
  CAN_ADL=(addr>>2)&0xff;
  CAN_ADH=(addr>>10)&0x0f;
      RWEN=0;
 while(BSY==1);
   if(bitnum<8)  {
   //V0=1;
     return CAN_DATA0&(i<<bitnum)  ;
   }
   else if(bitnum>=8&&bitnum<16)
   {
     //V1=1;
     return CAN_DATA1&(i<<(bitnum-8));

     }
      else if(bitnum>=16&&bitnum<24)
      {
      //V2=1;
     return CAN_DATA2&(i<<(bitnum-16));
     }
      else if(bitnum>=24&&bitnum<32)
      {
      //V3=1;
     return CAN_DATA3&(i<<(bitnum-24));
     }
    }

 //写发送数据
void write_send_data(can_data data1)
{
uchar j=0,k=0,p=0;
  can_write_0(MOFCR0,data1.length,3);
  if(data1.leibie==1)
  can_write(MOAR0,((data1.signal)|0x20000000));
  else
  can_write(MOAR0,(data1.signal<<18)&0XDFFFFFFF);
    while(data1.length--)
    {
      //can_wtrite_0((0X1010+j+k),data1.data0[j],p);
      //PORT_PAGE=0;
      //P3_DATA=data1.data0[j];
      can_write_0((MODATAL0+p),data1.data0[j],j);
      j++;
        //p++;

   if(j>=4)
   {
    // k=k+0x20;
     p++;
   }

   } //end while


}

//接受报文函数  p458
void receive_message()
{
   set_bit(MOSTAT0,MSGVAL,1);
   set_bit(MOSTAT0,RXEN,1);
   set_bit(MOSTAT0,NEWDAT,0);

   //设置接受标识符
   can_write(MOAR0,0XF0);
   while(read_bit(MOSTAT0,RTSEL)==0);
   while(read_bit(MOSTAT0,NEWDAT)!=0&&read_bit(MOSTAT0,RXUPD)!=0);
     set_bit(MOSTAT0,NEWDAT,1);
     if(read_bit(MOSTAT0,RXPND)==1)
     {
        set_bit(MOSTAT0,RXPND,0);
        //设置p3值
     }



}
 //PANAR2为列表,panar1为报文对象,pancmd位命令
void write_pancom(uchar pancmd,uchar panar1 ,uchar panar2)
{
    CAN_ADL=(PANCTR>>2)&0xff;
CAN_ADH=(PANCTR>>10)&0x0f;

CAN_DATA0=pancmd;
CAN_DATA2=panar1;
CAN_DATA3=panar2;
CAN_ADCON=0XD5;//必须在data数据之后设置
while(BSY==1);
  while(read_bit(PANCTR,0X08)!=0);
}

 void can1_init()
 {

 //节点1控制
      //漏极开路选择
    PORT_PAGE  = 0x03;
  P1_OD      = 0x00;
  PORT_PAGE  = 0x00;
  //1.3out,1.4in
  P1_DIR=0x08;

  //设置rxsel
  set_bit(NCR1,CCE,1);
  can_write_0(NPCR1,0X03,0);
  PORT_PAGE=0x02;
     P1_ALTSEL0 = 0x02;
  P1_ALTSEL1 =  0x02; //p477,端口选择
    //写面板控制寄存器,静态分配,将报文对象0给节点1
     write_pancom(0x02,0x00,0x02);
          //位时序控制,CCE置位

    can_write(NBTR1,0X3487);
    //设置ncr1(p495),使能can1节点
   can_write(NCR1,0x0e);
   //set_bit(NCR1,CCE,0);
     return;
 }
//can初始化
/*********选择节点0 ,直接使用复位值(由npcr0控制)
p1.0(in) p1.1(out)
******************************/
void can_init()
{
#ifdef _can_0_
  //漏极开路选择
    PORT_PAGE  = 0x03;
  P1_OD      = 0x00;
  PORT_PAGE  = 0x00;
  P1_DIR=0xfe;
  //设置rxsel
    set_bit(NCR0,CCE,1);
  can_write_0(NPCR0,0X00,0);
  PORT_PAGE=0x02;
     P1_ALTSEL0 = 0x02;
  P1_ALTSEL1 =  0x02; //p477,端口选择
    //写面板控制寄存器,静态分配,将报文对象0给节点1
     write_pancom(0x02,0x00,0x01);


     //测试是否给list1分配报文对象
        /*
        can_read(MOSTAT0);
        if((CAN_DATA1&0xf0)==0x10)
        {
      PORT_PAGE=0;
         P3_DATA=0x55;
        }
        if(read_bit(0x0104,24)==0)
         {
         PORT_PAGE=0;
         P3_DATA=0XFF;
         }*/

      //位时序控制,CCE置位

    can_write(NBTR0,0X3487);
     //设置ncr0 (p495),使能can0节点
   can_write(0x0200,0x0e);
   //set_bit(NCR0,CCE,0);
    //can_write(NBTR0,0X2240);
    #else
    can1_init();
    #endif
    //发送数据写入
     a.leibie=0;
    a.signal=0x05;
    a.length=2;
    a.data0[0]=0x01;
     a.data0[1]=0x02;
    write_send_data(a);

   //报文发送请求,数据侦
    set_bit(MOCTR0 ,SETDIR,1);
    //set_bit(MOCTR0 ,RESDIR,1);
    //set_bit(MOCTR0 ,SETMSGVAL,1);
   //set_bit(MOCTR0 ,RESNEWDAT,0);
     set_bit(MOCTR0 ,SETNEWDAT,1);
      set_bit(MOCTR0 ,SETMSGVAL,1);
   // set_bit(MOCTR0 ,RESMSGVAL,0);
    set_bit(MOCTR0 ,SETTXEN0,1);
    //set_bit(MOCTR0 ,RESTXEN0,0);
    set_bit(MOCTR0 ,SETTXEN1,1);
    //set_bit(MOCTR0 ,RESTXEN1,0);
    set_bit(MOCTR0 ,SETTXRQ,1);
    //set_bit(MOCTR0 ,RESTXRQ,0);
    //set_bit(NSR0,RXOK,1);

    //can_write(0x0200,0x004e);
   // PORT_PAGE=0;
   // P3_DATA=0X01;
    //while(read_bit(MOSTAT0,RTSEL)==0);
    if(read_bit(MOSTAT0,NEWDAT)!=0)
    {
    PORT_PAGE=0;
    P3_DATA=0X02;}
    //while(read_bit(MOSTAT0,RTSEL)==0);
    while(read_bit(MOSTAT0,NEWDAT)!=0);
     while(read_bit(NSR0,TXOK)==0);
     //set_bit(NSR0,TXOK,0);



     //set_bit(MOSTAT0,MSGVAL,1);
     //set_bit(MOSTAT0,DIR,1);
     //set_bit(MOSTAT0,TXEN0,1);
     //set_bit(MOSTAT0,TXEN1,1);
      //set_bit(MOSTAT0,TXRQ,1);

      //set_bit(MOSTAT0,RTSEL,1);
      //while(read_bit(MOSTAT0,RTSEL)==0);//RTSEL位1,选中报文对象进行接收
     // set_bit(MOSTAT0,NEWDAT,1);
      //报文对象发送
     // while(read_bit(MOSTAT0,NEWDAT)==1);

 }


void main()
{

  P3_init();
 can_init();
 PORT_PAGE=0X00;
 P3_DATA=0X21;
 while(1);
}

⌨️ 快捷键说明

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