|
- // ========CAN通信程序=======
- #include <PIC.h>
- #include <PIC16f87x.h>
- #include <mcp2510.h> // 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<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;
- }
复制代码
|
|