專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享
從全面的產(chǎn)品導(dǎo)入到強大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!
提供新的芯片及解決方案,提升客戶產(chǎn)品競爭力
提供最新的單片機資訊,行業(yè)消息以及公司新聞動態(tài)
十年單片機開發(fā)方案公司深圳英銳恩分享PIC16F87X單片機在CAN通信中的應(yīng)用軟件清單。
// ========CAN通信程序=======
#include
#include <pic16f87x.h>
#include // 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 {
T1CON=0;
if(!flag1){
TMR1H=0xfe; // 512 μs 脈沖寬度
TMR1L=0x00;
T1CON=0x01;
PORTD=0xff; // 輸出所有通道
flag1=1;
}
else {
{
CCP2IF=0;
T1CON=0x01;
return;
}
// 中斷入口,保護(hù)現(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); // 當(dāng)count!=0時,等待 to add "CLRWDT"
return;
}
// 對MCP2510芯片進(jìn)行復(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芯片進(jìn)行位修改子程序
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); // 確認(rèn)已進(jìn)入正常操作模式
return;
}
// 對MCP2510進(jìn)行初始化
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); // 確認(rèn)是否已發(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;
}
(文源網(wǎng)絡(luò),侵刪)