nasphere 发表于 2011-8-9 10:48:23

贴一个c8051f040的CAN自测程序(已验证,相关现象在后有说明)

#include<c8051f040.h>
#include<stdio.h>
// CAN Protocol Register Index for CAN0ADR, from TABLE 18.1 of the C8051F040
// datasheet
////////////////////////////////////////////////////////////////////////////////
#define CANCTRL            0x00               //Control Register
#define CANSTAT            0x01               //Status register
#define ERRCNT             0x02               //Error Counter Register
#define BITREG             0x03               //Bit Timing Register
#define INTREG             0x04               //Interrupt Low Byte Register
#define CANTSTR            0x05               //Test register
#define BRPEXT             0x06               //BRP Extension         Register
////////////////////////////////////////////////////////////////////////////////
//IF1 Interface Registers
////////////////////////////////////////////////////////////////////////////////
#define IF1CMDRQST         0x08               //IF1 Command Rest      Register
#define IF1CMDMSK          0x09               //IF1 Command Mask      Register
#define IF1MSK1            0x0A               //IF1 Mask1             Register
#define IF1MSK2            0x0B               //IF1 Mask2             Register
#define IF1ARB1            0x0C               //IF1 Arbitration 1   Register
#define IF1ARB2            0x0D               //IF1 Arbitration 2   Register
#define IF1MSGC            0x0E               //IF1 Message Control   Register
#define IF1DATA1         0x0F               //IF1 Data A1         Register
#define IF1DATA2         0x10               //IF1 Data A2         Register
#define IF1DATB1         0x11               //IF1 Data B1         Register
#define IF1DATB2         0x12               //IF1 Data B2         Register
////////////////////////////////////////////////////////////////////////////////
//IF2 Interface Registers
////////////////////////////////////////////////////////////////////////////////
#define IF2CMDRQST         0x20               //IF2 Command Rest      Register
#define IF2CMDMSK          0x21               //IF2 Command Mask      Register
#define IF2MSK1            0x22               //IF2 Mask1             Register
#define IF2MSK2            0x23               //IF2 Mask2             Register
#define IF2ARB1            0x24               //IF2 Arbitration 1   Register
#define IF2ARB2            0x25               //IF2 Arbitration 2   Register
#define IF2MSGC            0x26               //IF2 Message Control   Register
#define IF2DATA1         0x27               //IF2 Data A1         Register
#define IF2DATA2         0x28               //IF2 Data A2         Register
#define IF2DATB1         0x29               //IF2 Data B1         Register
#define IF2DATB2         0x2A               //IF2 Data B2         Register
////////////////////////////////////////////////////////////////////////////////
//Message Handler Registers
////////////////////////////////////////////////////////////////////////////////
#define TRANSREQ1          0x40               //Transmission Rest1 Register
#define TRANSREQ2          0x41               //Transmission Rest2 Register

#define NEWDAT1            0x48               //New Data 1            Register
#define NEWDAT2            0x49               //New Data 2            Register

#define INTPEND1         0x50               //Interrupt Pending 1   Register
#define INTPEND2         0x51               //Interrupt Pending 2   Register

#define MSGVAL1            0x58               //Message Valid 1       Register
#define MSGVAL2            0x59               //Message Valid 2       Register

sfr16 CAN0DATA=0xd8;
void IO_ini(void);
void oscx_ini(void);
void clear_msg_objects(void);
//void init_msg_object_tx(void);
//void init_msg_object_rx(void);
void start_CAN(void);
sbit switch1=P2^0;
void inter_CAN(void);
unsigned int a, b;
extern void delay_50us(int n);
void main(){

WDTCN = 0xde;
WDTCN = 0xad;

IO_ini();
oscx_ini();
// init_msg_object_tx();
// init_msg_object_rx();
EIE2 = 0x20;//允许can0中断
while(switch1==1);
start_CAN();
EA = 1;
//CANSIE=0;
// init_msg_object_tx();
clear_msg_objects();
//TXOK=0;
while(1);
}

void IO_ini(void){
   
SFRPAGE=CONFIG_PAGE;
P2MDOUT=0Xff;
                                    
P2=0X0f;
XBR3|=0X80;
XBR2=0X40;                           //该处可设定弱上拉使能
}

void oscx_ini(void){
SFRPAGE=CONFIG_PAGE;
OSCXCN|=0X67;
delay_50us(20);
while((OSCXCN&0x80)==0);
CLKSEL|=0x01;
}

void clear_msg_objects(void){
unsigned char i, IDL=4,j;
unsigned short data_temp=0x0101;
SFRPAGE=CAN0_PAGE;
CANINIT=1;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0Xf3;                                 
         


for(i=1;i<=8;i++){
   

    CAN0ADR=IF1MSK1;
        CAN0DATA=0X0000;
    CAN0DATA=0X0000;                                    //需要修改IDE过滤
    CAN0ADR=IF1ARB2;
    CAN0DATH=0Xa0;
    CAN0DATL=IDL;
    IDL += 4;
    CAN0DATA=0X0088;               //IF1MSGC

   /* CAN0ADR=IF1DATA1;
    for(j=1;j<=4;j++){
    CAN0DATA=data_temp;
    data_temp+=257;
    }*/
    CAN0ADR=IF1CMDRQST;
    while((CAN0DATH & 0X80) == 1);
    CAN0DATL=i;

}
    IDL=0x04;
    for(;i<=16;i++){                     
   


    CAN0ADR=IF1MSK1;
        CAN0DATA=0XFFFF;
    CAN0DATA=0X1FFF;                                    //需要修改IDE过滤
    CAN0ADR=IF1ARB2;
    CAN0DATH=0XA0;
    CAN0DATL=IDL;
    IDL += 4;
    CAN0DATA=0X1080;                     //可设定newdata引发intpnd

    CAN0ADR=IF1CMDRQST;
    while((CAN0DATH & 0X80) == 1);
    CAN0DATL=i;

}
CANINIT=0;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0X87;                         //87控制位等不改
for(i=1;i<=8;i++){
CAN0ADR=IF1DATA1;
        for(j=1;j<=4;j++){
        CAN0DATA=data_temp;
        data_temp+=257;
        }
CAN0ADR=IF1CMDRQST;
CAN0DATL=i;         //这里发送
// delay_50us(55);
}

         
}

/*void init_msg_object_rx(void){
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0XA3;

CAN0ADR=IF1ARB1;    //关于寄存器地址可能存在问题
CAN0DATA=0X0000;
CAN0DATA=0X0000;
CAN0DATA=0X0401;
CAN0ADR=IF1CMDRQST;
while((CAN0DATH&0X80)!=0);
CAN0DATL=0X01;*/


/*void init_msg_object_tx(){
SFRPAGE=CAN0_PAGE;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0XA3;

CAN0ADR=IF1ARB1;    //关于寄存器地址可能存在问题
CAN0DATA=0X0000;
CAN0DATA=0X0000;
CAN0DATA=0X0801;
CAN0ADR=IF1DATA1;
CAN0DATL=0XAA;
CAN0ADR=IF1CMDRQST;
while((CAN0DATH&0X80)!=0);
CAN0DATL=0X11;
while((CAN0DATH&0X80)!=0);
CAN0ADR=IF1CMDMSK;
CAN0DATL|=0X04;
}
*/
void start_CAN(){
SFRPAGE=CAN0_PAGE;
CAN0CN|=0X00C1;   // 开测试和bt设置
CAN0CN&=0XFFd7;   //自动重发开启错误中断禁止

CAN0ADR=CANTSTR;
CAN0DATL|=0X10;
CAN0ADR=BITREG;
CAN0DATA=0X2640;
CAN0CN|=0X0006;
CAN0CN&=0XFFBE;
}

void delay_50us(int n){

    unsigned char l;
    for( ;n>0;n--)
      for(l=19;l>0;l--);
}

void inter_CAN(void) interrupt 19
{
/*SFRPAGE=CAN0_PAGE;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0XFF;
TXOK=0;*/
    unsigned int can_interrupt, i;
        unsigned int status;
//    temp_page=CAN0ADR;
//temp_data=CAN0DATA;

        SFRPAGE= CAN0_PAGE;
    CAN0ADR= INTREG;          //只读的中断寄存器
    can_interrupt = CAN0DATA;
    CAN0ADR=NEWDAT1;
   
    i=CAN0DATA;
        if(0){SFRPAGE=CONFIG_PAGE;
                P5MDOUT=0xff;
      P5&=0xf0;
                SFRPAGE=CAN0_PAGE;
        }

    if(can_interrupt==0x8000)   //status interrupt
    {
      status = CAN0STA;       //读状态寄存器
      if ((status&0x10) != 0)
      {                                           // RxOk is set, interrupt caused by reception
         // CAN0STA = (CAN0STA&0xEF)|0x07;          // Reset RxOk, set LEC to NoChange
            /* read message number from CAN INTREG */
//            receive_data ();                  // Up to now, we have only one RX message
      }
      if ((status&0x08) != 0)
      {   
                SFRPAGE=CONFIG_PAGE;
                P5MDOUT=0x0f;
      P5=0x0f;
                SFRPAGE=CAN0_PAGE;                                    // TxOk is set, interrupt caused by transmision
   //         CAN0STA = (CAN0STA&0xF7)|0x07;          // Reset TxOk, set LEC to NoChange
      }
      if (((status&0x07) != 0)&&((status&0x07) != 7))
      {                                           // Error interrupt, LEC changed
            /* error handling ? */
            CAN0STA = CAN0STA|0x07;               // Set LEC to NoChange
      }
        }
/*        CAN0ADR=NEWDAT1;
        temp_data=CAN0DATA;
    CAN0ADR= IF2CMDMSK;      
    CAN0DATA= 0x007f;
    CAN0ADR= IF2CMDRQST;
        CAN0DATL=9;
    CAN0ADR=IF1DATA1;
        for(i=0;i<=7;i++)
    a=CAN0DATA;

        CAN0ADR=NEWDAT1;
        temp_data=CAN0DATA;
    CAN0ADR= IF2CMDMSK;      
    CAN0DATA= 0x007f;
    CAN0ADR= IF2CMDRQST;
        CAN0DATL=0x10;
    CAN0ADR=IF1DATA1;
        for(i=0;i<=7;i++)
    b=CAN0DATA;*/

             

//        CAN0DATA=temp_data;
//        CAN0ADR=temp_page;
/*CAN0ADR=IF1CMDMSK;
        CAN0DATL=0X0C;
        CAN0ADR=IF1CMDRQST;
        CAN0DATL=0X09;
        CAN0ADR=IF1CMDRQST;
        CAN0DATL=0X10;*/

}


该程序运用ID滤波RTR与IDE均不参与过滤   
按键按下后才开始发送数据(便于之后两块板的正常通信调试)且正常发送时P5低四位的灯亮起指示
程序还不是非常的完善望大家指出我也好学习学习^-^

nasphere 发表于 2011-8-9 14:35:12

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_665871CIEOQC.jpg
完整点附上switch1的接线图 (原文件名:按键.jpg)

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_665872PAZ931.jpg
这是灯部分的接线与040的P5口连 (原文件名:灯.jpg)

mvpgpz 发表于 2013-8-22 15:37:37

正好在做040的can,学习一下,汲取经验!

zhangyunbo 发表于 2013-9-13 16:01:57

楼上的能留下联系方式么?我也刚开始做这个。不知道怎么弄。

陶新成 发表于 2015-7-28 09:05:12

楼主有C8051F040的串口程序吗,我用的是内部时钟,串口能发出数据但是格式和数据为全不对,估计是波特率没算好,你能传给我一个串口程序吗,使用外部晶振的也可以
页: [1]
查看完整版本: 贴一个c8051f040的CAN自测程序(已验证,相关现象在后有说明)