×
单片机 > 单片机程序设计 > 详情

MCP2510 CAN通信程序(pic单片机)

发布时间:2020-06-17 发布时间:
|

// ========CAN通信程序======= 

#include    

#include    

#include                // MCP2510寄存器定义 

// =========常数和变量定义=========  

#define    READ    0x03                // 读MCP2510指令代码 

#define    WRITE    0x02            // 写MCP2510指令代码 

#define    RESET    0xC0            // 复位MCP2510指令代码 

#define    RTS    0x80                // MCP2510请求发送指令代码 

#define    STA2510    0xA0            // 读MCP2510状态指令代码 

#define    BITMOD    0x05            // MCP2510位修改指令代码 

int    a[12];                    // SPI发送或接收数据寄存器

int    b[8];                    // 发送或接收的数据

int    c[8];                    // 发送或接收的数据

int    i;                        // 临时变量

int    count;                    // 发送接收计数器

int    count1=0;                // for test

int    RecID_H=0;

int    RecID_L=0;

int    DLC=8;

void SPIINT();

void TMR1INT();

void CCP1INT();

void SPIEXCHANGE(int count);

void WAIT_SPI();

void RESET2510();

int  RD2510(int adress,int n);

void WR2510(int adress,int n);

void RTS2510(int RTSn);

int  GETS2510();

void BM2510(int adress,int mask,int data);

void SETNORMAL();

void TXCOMPLETE(int adress);

void TXMSG(int DLC);

int  RXMSG();

void INIT2510();

void INIT877();

void INITSPI();

void ACK();

void wait();

// ========主程序======= 

main(void)

{

    int l,detect=0;

    SSPIE=1;

    TMR1IE=1;

    CCP1IE=1;

    CCP2IE=1;

    PEIE=1;

    ei();                    // 开中断 

    INIT877();                // 初始化PIC16F877芯片 

    INITSPI();                // 初始化SPI接口 

    INIT2510();                // 初始化MCP2510芯片 

    flag1=0;

    flag2=0;

    CCP1CON=0x05;

    CCP2CON=0x04;

    while(1)    {

        RXMSG();

        TXMSG(8);

    }

}

// ========中断服务程序======= 

// SPI中断服务子程序 

void SPIINT()

{

    SSPIF=0;

    a[i++]=SSPBUF;            // 数据暂存a[]中 

    count-=1;

    if(count>0)  SSPBUF=a[i];// 未发送完,继续 

    else  RE2=1;                // 否则,片选信号置高电平 

    return;

}

// TMR1中断服务子程序 

void TMR1INT()

{

    TMR1IF=0;

    T1CON=0;

    if(!flag1){

        TMR1H=0xfe;                // 512 μs 脉冲宽度

        TMR1L=0x00;

        T1CON=0x01;

        PORTD=0xff;                // 输出所有通道

        flag1=1;

    }

    else    {

        flag1=0;

        PORTD=0;

        T1CON=0;

    }

    return;

}

// CCP1中断服务子程序 

void CCP1INT()

{

    CCP1IF=0;

    T1CON=0x01;

    return;

}

// CCP2中断服务子程序 

void CCP2INT()

{

    CCP2IF=0;

    T1CON=0x01;

    return;

}

// 中断入口,保护现场,判中断类型 

void interrupt INTS()

{

    di();

    if(TMR1IF)  TMR1INT();        // 定时器TMR1中断 

    else if(CCP1IF)  CCP1INT();    // 电压过零捕捉中断1 

    else if(CCP2IF)  CCP2INT();    // 电压过零捕捉中断2 

    else if(SSPIF)  SPIINT();        // SPI接口中断 

    ei();

}

// ========子程序======= 

// 启动SPI传送 

void SPIEXCHANGE(count)

int count;

{

    if(count>0) {                // 有数据可送? 

      i=0;

      RE2=0;                        // 片选位置低电平 

      SSPBUF=a[i];                // 送数 

    }

    else

      ;                            // 否则,空操作,并返回 

    return;

}

// 等待SPI传送完成 

void WAIT_SPI()

{

    do{

      ;

    }while(count>0);                // 当count!=0时,等待 to add "CLRWDT" 

    return;

}

// 对MCP2510芯片进行复位 

void RESET2510()

{

    a[0]=RESET;

    count=1;

    SPIEXCHANGE(count);            // 送复位指令 

    WAIT_SPI();

    return;

}

// 读取从地址"adress"开始的寄存器中的数据,共n个,存放在数组b[n]中 

int RD2510(adress,n)

int     adress;

int        n;

{

    int j;

    a[0]=READ;

    a[1]=adress;

    for(j=0;j

    count=n+2;                    // 指令、地址和要得到的数据量n 

    SPIEXCHANGE(count);

    WAIT_SPI();

    for(j=0;j

    return;

}

// 向从地址"adress"开始的寄存器写入数据,共n个,数据存放数组b[n]中 

void WR2510(adress,n)

int        adress;

int        n;

{

    int j;

    a[0]=WRITE;

    a[1]=adress;

    for(j=0;j

    count=n+2;                    // 指令、地址和要写入的数据量n 

    SPIEXCHANGE(count);

    WAIT_SPI();

    return;

}

// MCP2510芯片请求发送程序 

void RTS2510(RTSn)

int RTSn;

{

    a[0]=RTS^RTSn;

    count=1;

    SPIEXCHANGE(count);            // 发送MCP2510芯片,请求发送指令 

    WAIT_SPI();

    return;

}

// 读取MCP2510芯片的状态 

int GETS2510()

{

    a[0]=STA2510;

    a[1]=0;

    count=2;

    SPIEXCHANGE(count);            // 读取MCP2510芯片状态 

    WAIT_SPI();

    b[0]=a[1];                    // 状态存到数组b[]中 

    return;

}

// 对MCP2510芯片进行位修改子程序 

void BM2510(adress,mask,data)

int  adress;

int  mask;

int  data;

{

    a[0]=BITMOD;                    // 位修改指令 

    a[1]=adress;                    // 位修改寄存器地址 

    a[2]=mask;                    // 位修改屏蔽位 

    a[3]=data;                    // 位修改数据 

    count=4;

    SPIEXCHANGE(count);

    WAIT_SPI();

    return;

}

// 设置MCP2510芯片为正常操作模式 

void  SETNORMAL()

{

    int  k=1;

    BM2510(CANCTRL,0xe0,0x00);    // 设置为正常操作模式 

    do    {

      RD2510(CANSTAT,1);

      k=b[0]&0xe0;

    }while(k);                    // 确认已进入正常操作模式 

    return;

}

// 对MCP2510进行初始化 

void INIT2510()

{

    RESET2510();                    // 使芯片复位 

    b[0]=0x02;

    b[1]=0x90;

    b[2]=0x07;

    WR2510(CNF3,3);                // 波特率为 125 kbps 

    b[0]=0x00;

    b[1]=0x00;

    WR2510(RXM0SIDH,2);

    b[0]=0x00;

    b[1]=0x00;

    WR2510(RXF0SIDH,2);            // RX0接收,屏蔽位为0,过滤器为0 

    b[0]=0x00;

    WR2510(CANINTE,1);            // CAN中断不使能 

    SETNORMAL();                    // 设置为正常操作模式 

ret



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机中断源的扩展方法