技术热线: 4007-888-234

PIC16F87X单片机在CAN通信中的应用软件清单

更新时间: 2019-03-22
阅读量:2169

十年单片机开发方案公司深圳英锐恩分享PIC16F87X单片机在CAN通信中的应用软件清单。

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

#include

#include <pic16f87x.h>

#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 {

T1CON=0;

if(!flag1){

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

TMR1L=0x00;

T1CON=0x01;

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

flag1=1;

}

else {

{

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<n;j++)  a[j+2]=0;

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

SPIEXCHANGE(count);

WAIT_SPI();

for(j=0;j<n;j++)  b[j]=a[j+2];// 数据存到数组b[]中 

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<n;j++) a[j+2]="b[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();     // 设置为正常操作模式 

return;

}

// MCP2510芯片发送完成与否判断,邮箱号为adress 

void TXCOMPLETE(adress)

int adress;

{

int k=1;

do {

  RD2510(adress,1);

  k=b[0]&0x08;

}while(k);     // 确认是否已发送完毕 to add CLRWDT

return;

}

// 初始化PIC16F877芯片 

void INIT877()

{

PORTA=0;

PORTB=0;

PORTC=0;

PORTD=0;

PORTE=0;

TRISA=0xff;

TRISB=0xfd;

TRISC=0xd7;     // SCK, SDO:输出,SDI:输入  

TRISD=0;

TRISE=0x03;     // 片选CS信号输出

PORTA=0xff;

PORTB=0x03;     // RST=1

PORTC=0;

PORTD=0xff;

PORTE=0x04;

return;

}

// 初始化SPI接口 

 void INITSPI()

{

SSPCON=0x11;

SSPEN=1;       // SSP使能 

SSPSTAT=0;

return;

}

// 发送数据子程序 

 void  TXMSG(int DLC)

{

for(i=0;i<dlc;i++)  b[i]=c[i];

WR2510(TXB0D0,DLC);

b[0]=DLC;

WR2510(TXB0DLC,1);

b[0]=0x03;

b[1]=RecID_H;

b[2]=RecID_L;

WR2510(TXB0CTRL,3);

RTS2510(0x01);     // 请求发送 

TXCOMPLETE(TXB0CTRL);    //等待发送完毕 

return;

}

// 接收数据子程序 

 int RXMSG()

{

int k;

RD2510(CANINTF,1);

k=b[0]&0x01;

if(k==1) {

BM2510(CANINTF,0x01,0x00);

RD2510(RXB0SIDH,2);

RecID_H=b[0];

RecID_L=b[1]&0xe0;

RD2510(RXB0DLC,1);

DLC=b[0]&0x0f;

RD2510(RXB0D0,DLC);

for(i=0;i<dlc;i++) c[i]="b[i];

return 1;

}

return 0;

}

(文源网络,侵删)