|
- // ========CAN通信程序=======
- #include <PIC.h>
- #include <PIC16f87x.h>
- #include <mcp2510.h> // MCP2510寄存器定義
- // =========常數(shù)和變量定義=========
- #define READ 0x03 // 讀MCP2510指令代碼
- #define WRITE 0x02 // 寫MCP2510指令代碼
- #define RESET 0xC0 // 復(fù)位MCP2510指令代碼
- #define RTS 0x80 // MCP2510請求發(fā)送指令代碼
- #define STA2510 0xA0 // 讀MCP2510狀態(tài)指令代碼
- #define BITMOD 0x05 // MCP2510位修改指令代碼
- int a[12]; // SPI發(fā)送或接收數(shù)據(jù)寄存器
- int b[8]; // 發(fā)送或接收的數(shù)據(jù)
- int c[8]; // 發(fā)送或接收的數(shù)據(jù)
- int i; // 臨時變量
- int count; // 發(fā)送接收計數(shù)器
- 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);
- }
- }
- // ========中斷服務(wù)程序=======
- // SPI中斷服務(wù)子程序
- void SPIINT()
- {
- SSPIF=0;
- a[i++]=SSPBUF; // 數(shù)據(jù)暫存a[]中
- count-=1;
- if(count>0) SSPBUF=a[i];// 未發(fā)送完,繼續(xù)
- else RE2=1; // 否則,片選信號置高電平
- return;
- }
- // TMR1中斷服務(wù)子程序
- 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中斷服務(wù)子程序
- void CCP1INT()
- {
- CCP1IF=0;
- T1CON=0x01;
- return;
- }
- // CCP2中斷服務(wù)子程序
- void CCP2INT()
- {
- CCP2IF=0;
- T1CON=0x01;
- return;
- }
- // 中斷入口,保護現(xiàn)場,判中斷類型
- 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) { // 有數(shù)據(jù)可送?
- i=0;
- RE2=0; // 片選位置低電平
- SSPBUF=a[i]; // 送數(shù)
- }
- else
- ; // 否則,空操作,并返回
- return;
- }
- // 等待SPI傳送完成
- void WAIT_SPI()
- {
- do{
- ;
- }while(count>0); // 當count!=0時,等待 to add "CLRWDT"
- return;
- }
- // 對MCP2510芯片進行復(fù)位
- void RESET2510()
- {
- a[0]=RESET;
- count=1;
- SPIEXCHANGE(count); // 送復(fù)位指令
- WAIT_SPI();
- return;
- }
- // 讀取從地址"adress"開始的寄存器中的數(shù)據(jù),共n個,存放在數(shù)組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; // 指令、地址和要得到的數(shù)據(jù)量n
- SPIEXCHANGE(count);
- WAIT_SPI();
- for(j=0;j<n;j++) b[j]=a[j+2];// 數(shù)據(jù)存到數(shù)組b[]中
- return;
- }
- // 向從地址"adress"開始的寄存器寫入數(shù)據(jù),共n個,數(shù)據(jù)存放數(shù)組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; // 指令、地址和要寫入的數(shù)據(jù)量n
- SPIEXCHANGE(count);
- WAIT_SPI();
- return;
- }
- // MCP2510芯片請求發(fā)送程序
- void RTS2510(RTSn)
- int RTSn;
- {
- a[0]=RTS^RTSn;
- count=1;
- SPIEXCHANGE(count); // 發(fā)送MCP2510芯片,請求發(fā)送指令
- WAIT_SPI();
- return;
- }
- // 讀取MCP2510芯片的狀態(tài)
- int GETS2510()
- {
- a[0]=STA2510;
- a[1]=0;
- count=2;
- SPIEXCHANGE(count); // 讀取MCP2510芯片狀態(tài)
- WAIT_SPI();
- b[0]=a[1]; // 狀態(tài)存到數(shù)組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; // 位修改數(shù)據(jù)
- count=4;
- SPIEXCHANGE(count);
- WAIT_SPI();
- return;
- }
- // 設(shè)置MCP2510芯片為正常操作模式
- void SETNORMAL()
- {
- int k=1;
- BM2510(CANCTRL,0xe0,0x00); // 設(shè)置為正常操作模式
- do {
- RD2510(CANSTAT,1);
- k=b[0]&0xe0;
- }while(k); // 確認已進入正常操作模式
- return;
- }
- // 對MCP2510進行初始化
- void INIT2510()
- {
- RESET2510(); // 使芯片復(fù)位
- 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(); // 設(shè)置為正常操作模式
- return;
- }
- // MCP2510芯片發(fā)送完成與否判斷,郵箱號為adress
- void TXCOMPLETE(adress)
- int adress;
- {
- int k=1;
- do {
- RD2510(adress,1);
- k=b[0]&0x08;
- }while(k); // 確認是否已發(fā)送完畢 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;
- }
- // 發(fā)送數(shù)據(jù)子程序
- 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); // 請求發(fā)送
- TXCOMPLETE(TXB0CTRL); //等待發(fā)送完畢
- return;
- }
- // 接收數(shù)據(jù)子程序
- 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;
- }
復(fù)制代碼
|
|