sja1000 c语言,基于51单片机SJA1000 CAN通讯实现
5.sja1000.c
#include "sja1000.h"
sbit LED=P1^0;
unsigned char xdata *SJA_BCANAdr;
unsigned char RevceData[8];
//C語言指針說明以 * 為分隔符,
//“*” 前面的存儲類型修飾—指針?biāo)赶虻膶ο髷?shù)據(jù)的存儲位置;
//“*” 后面的存儲類型修飾—指針本身所分配的存儲位置。
//
//unsigned char xdata *P說明指針指向的對象是一個處于Xdata的元素,比如數(shù)組.
//xdata unsigned char *p表明指針本身位于Xdata,至于指向什么類型的地址,自由變換.
//所以unsigned char xdata *p; 和xdata unsigned char *p ? 不一樣。說明的是2回事。
//而:xdata unsigned char *p; 和 unsigned char ?* xdata p; 完全一樣。
//因為C寫法中允許“最前面的存儲類型修飾符修飾最后面的對象。”
/*****************************************************************
函數(shù)功能:檢測SJA1000與CPU數(shù)據(jù)接口是否正確連接
入口參數(shù):
返回參數(shù):1正確 0錯誤
說明:
******************************************************************/
bit SJA_Interface_Test(void)
{
SJA_BCANAdr=REG_TEST;
*SJA_BCANAdr=0xAA;
if(*SJA_BCANAdr==0XAA)
return 1;
else return 0;
}
/*****************************************************************
函數(shù)功能:設(shè)置分頻系數(shù) ?工作模式
入口參數(shù):
返回參數(shù):1設(shè)置成功 0失敗
說明:此處設(shè)置為PeliCAN模式,終止CAN輸入比較器(復(fù)位模式),關(guān)閉時鐘輸出
******************************************************************/
bit Set_OutClock(unsigned char outclock)
{
SJA_BCANAdr=REG_CDR ;
*SJA_BCANAdr=outclock;
if(*SJA_BCANAdr==outclock)
return 1;
else return 0;
}
/*****************************************************************
函數(shù)功能:設(shè)置驗收驗收代碼寄存器和接收屏蔽碼寄存器 只有在復(fù)位模式下才能訪問該寄存器
入口參數(shù):各個寄存器的寫入值
返回參數(shù):1設(shè)置成功 0 設(shè)置失敗
說明:設(shè)置CAN節(jié)點的通訊對象,允許接收的報文,是由AMR和ACR共同決定的.
PeliCAN工作模式下濾波模式分為:
1.單濾波器模式 模式寄存器(MOD.3=1)
這種濾波模式可以定義一個4字節(jié)長慮波器 。慮波器字節(jié)和信息字節(jié)之位的對應(yīng)關(guān)系取決于當(dāng)前接收幀的格式。
標(biāo)準(zhǔn)幀:11位標(biāo)識符、RTR位、數(shù)據(jù)場前連個字節(jié)參與濾波。對于參與濾波的數(shù)據(jù),所有AMR為0的位所對應(yīng)的ACR位
和參與濾波數(shù)據(jù)的對應(yīng)位必須相同才算驗收通過。如果由于置位RTR位而沒有數(shù)據(jù)字節(jié),或因為設(shè)置相應(yīng)的數(shù)據(jù)長度代碼
而沒有或只有一個數(shù)據(jù)字節(jié),報文也會被接收。ACR1和AMR1的低四位是不用的,此時可將AMR1.3-AMR1.0設(shè)為1,定為不影響
擴展幀:29位標(biāo)識符和RTR位參與濾波。此時ACR3和AMR3的最低兩位是不用的。將AMR3.1、AMR3.0置1,定為不影響。
2.雙濾波器模式 模式寄存器(MOD.3=0)至少有一個濾波器驗收通過,數(shù)據(jù)才能正常接收。
接收標(biāo)準(zhǔn)幀:第一個濾波器由ACR0、ACR1、AMR0、AMR1及ACR3、AMR3的低四位組成。11位標(biāo)識符、RTR位和數(shù)據(jù)場的第一個字節(jié)參與濾波
在RTR位置位1或數(shù)據(jù)長度代碼是0,表示沒有數(shù)據(jù)字節(jié)存在時,只要從開始到RTR位的部分都表示接收。信息就可以通過濾波器1
第二個濾波器由ACR2、AMR2及ACR3、AMR3的高四位組成。11位標(biāo)識符和RTR位參與濾波。
如果沒有數(shù)據(jù)字節(jié)向濾波器請求過濾,AMR1和AMR3的低四位必須被置1,表示不影響。此時兩個濾波器的識別工作都是驗證
包括RTR在內(nèi)的整個標(biāo)準(zhǔn)識別碼。
接收擴展幀:定義的兩個濾波器是相同的
第一個濾波器由ACR0、ACR1和AMR0、AMR1構(gòu)成
第二個濾波器由ACR2、ACR3和AMR2、AMR3構(gòu)成
兩個濾波器都只比較擴展識別碼的前兩個字節(jié)即29位識別碼中的搞16位
******************************************************************/
bit SET_ACR(unsigned char BCAN_ACR0,unsigned char BCAN_ACR1,unsigned char BCAN_ACR2,unsigned char BCAN_ACR3)
{
SJA_BCANAdr=REG_ACR0;
*SJA_BCANAdr=BCAN_ACR0;
SJA_BCANAdr=REG_ACR1;
*SJA_BCANAdr=BCAN_ACR1;
SJA_BCANAdr=REG_ACR2;
*SJA_BCANAdr=BCAN_ACR2;
SJA_BCANAdr=REG_ACR3;
*SJA_BCANAdr=BCAN_ACR3;
if(*SJA_BCANAdr!=BCAN_ACR3) ?return 0;
return 1;
}
bit SET_AMR(unsigned char BCAN_AMR0,unsigned char BCAN_AMR1,unsigned char BCAN_AMR2,unsigned char BCAN_AMR3)
{
SJA_BCANAdr=REG_AMR0;
*SJA_BCANAdr=BCAN_AMR0;
SJA_BCANAdr=REG_AMR1;
*SJA_BCANAdr=BCAN_AMR1;
SJA_BCANAdr=REG_AMR2;
*SJA_BCANAdr=BCAN_AMR2;
SJA_BCANAdr=REG_AMR3;
*SJA_BCANAdr=BCAN_AMR3;
if(*SJA_BCANAdr!=BCAN_AMR3) return 0;
return 1;
}
/*****************************************************************
函數(shù)功能:設(shè)置CAN總線通信波特率
入口參數(shù):波特率
返回參數(shù):1設(shè)置成功 0設(shè)置失敗
說明:該子程序只能用于復(fù)位模式
因為總線定時器BTRO-BTR1只有在復(fù)位模式下才能讀寫操作,工作模式只讀
******************************************************************/
bit Set_Bandrate(unsigned char bandrate)
{
unsigned char BR_Num= bandrate,BTR0_num,BTR1_num;
switch (BR_Num)
{
case ByteRate_10k:
BTR0_num=BTR0_Rate_10k;
BTR1_num=BTR0_Rate_10k;
break;
case ByteRate_20k:
BTR0_num=BTR0_Rate_20k;
BTR1_num=BTR0_Rate_20k;
break;
case ByteRate_40k:
BTR0_num=BTR0_Rate_20k;
BTR1_num=BTR0_Rate_20k;
break;
case ByteRate_50k:
BTR0_num=BTR0_Rate_50k;
BTR1_num=BTR0_Rate_50k;
break;
case ByteRate_80k:
BTR0_num=BTR0_Rate_80k;
BTR1_num=BTR0_Rate_80k;
break;
case ByteRate_100k:
BTR0_num=BTR0_Rate_100k;
BTR1_num=BTR0_Rate_100k;
break;
case ByteRate_125k:
BTR0_num=BTR0_Rate_125k;
BTR1_num=BTR0_Rate_125k;
break;
case ByteRate_200k:
BTR0_num=BTR0_Rate_200k;
BTR1_num=BTR0_Rate_200k;
break;
case ByteRate_250k:
BTR0_num=BTR0_Rate_250k;
BTR1_num=BTR0_Rate_250k;
break;
case ByteRate_400k:
BTR0_num=BTR0_Rate_400k;
BTR1_num=BTR0_Rate_400k;
break;
case ByteRate_500k:
BTR0_num=BTR0_Rate_500k;
BTR1_num=BTR0_Rate_500k;
break;
case ByteRate_1000k:
BTR0_num=BTR0_Rate_1000k;
BTR1_num=BTR0_Rate_1000k;
break;
default :return 0;break;
}
SJA_BCANAdr=REG_BTR0;
*SJA_BCANAdr=BTR0_num;
if(*SJA_BCANAdr!=BTR0_num) return 0;
SJA_BCANAdr=REG_BTR1;
*SJA_BCANAdr=BTR1_num;
if(*SJA_BCANAdr!=BTR1_num) return 0;
return 1;
}
/*****************************************************************
函數(shù)功能:設(shè)置控制(模式)寄存器
入口參數(shù):寫入的命令
返回參數(shù):
說明:模式寄存器的內(nèi)容是用來改變CAN 控制器的行為
******************************************************************/
bit Set_ContrREG(unsigned char CMD)
{
SJA_BCANAdr ?= REG_CONTROL;//控制寄存器
*SJA_BCANAdr=CMD;
if(*SJA_BCANAdr==CMD) return 1;
else return 0;
}
/*****************************************************************
函數(shù)功能:設(shè)置復(fù)位請求和單濾波工作模式
入口參數(shù):
返回參數(shù):
說明:
******************************************************************/
bit Enter_RST_Mode(void)
{
SJA_BCANAdr ?= REG_CONTROL;//控制寄存器
*SJA_BCANAdr=0x09; ? ? ? ? ? //置位復(fù)位請求 和單濾波模式
if((*SJA_BCANAdr&0x01) == 1)
return ? 1;
else
return ? 0;
}/*****************************************************************
函數(shù)功能:
入口參數(shù):
返回參數(shù):
說明:
******************************************************************/
bit Quit_RST_Mode(void)
{
SJA_BCANAdr=REG_CONTROL; ? ? ? ? ? ?//退出 復(fù)位模式
*SJA_BCANAdr=*SJA_BCANAdr&0xfe;
if((*SJA_BCANAdr&0X01)==0)
return 1;
else return 0;
}
/*****************************************************************
函數(shù)功能:發(fā)送命令請求,并返回請求結(jié)果
入口參數(shù):
返回參數(shù):0請求成功 1請求失敗
說明:
******************************************************************/
bit ?CAN_CMD_PRG(unsigned char cmd)
{
SJA_BCANAdr=REG_COMMAND; ? ? ? ? ? ?//訪問地址指向命令寄存器
*SJA_BCANAdr=cmd; ? ? ? ? ? ? ? ? ? //啟動命令字
switch(cmd)
{
case ?TR_CMD: ? ?//發(fā)送請求
return ? ?1;
break;
case ?SRR_CMD: ? ? //CMR.4自接收模式
return 1;
break;
case ?AT_CMD: ? ? ?//CMR.1中止發(fā)送位
SJA_BCANAdr = REG_STATUS; ? //訪問地址指向狀態(tài)寄存器
if((*SJA_BCANAdr & 0x20)==0) //判斷是否正在發(fā)送 (0正在發(fā)送 1等待空閑)
return ?1;
else
return ?0;
break;
case ?RRB_CMD: ? // CMR.2釋放接收緩沖器
SJA_BCANAdr = REG_STATUS; ? //訪問地址指向狀態(tài)寄存器
if((*SJA_BCANAdr & 0x01)==1) //判斷接收緩沖器是否為空 (0為空 1不為空)
return ?0;//若不為空 則釋放接收緩沖器失敗
else
return ?1;
break;
case ?COS_CMD: ?//CMR.3清除數(shù)據(jù)溢出
SJA_BCANAdr = REG_STATUS;
if((*SJA_BCANAdr & 0x02)==0)//判斷清除溢出是否成功
return ?1;
else
return ?0;
break;
default:
return ?0;
break;
}
}
/*****************************************************************
函數(shù)功能:設(shè)置中斷使能寄存器
入口參數(shù):
返回參數(shù):
說明:
******************************************************************/
bit Set_IntEnable(unsigned char CMD)
{
SJA_BCANAdr=REG_INTENABLE; ? //SJA_BaseAdr+0x00 ?控制寄存器
*SJA_BCANAdr=CMD;
if (*SJA_BCANAdr == CMD)
return 1;
else
return 0;
}
unsigned char CAN_Write(unsigned char *SendDataBuf)
{
unsigned char temp;
SJA_BCANAdr = REG_STATUS;
temp=*SJA_BCANAdr;
if ((temp&0x08)==0) return ?1; ? ?//上次發(fā)送未完成
if ((temp&0x04)==0) return ?2; ? ?//發(fā)送緩沖區(qū)是否鎖定
if ((temp&0x10)==0x10) return 3; ?//判斷是否正在接收
SJA_BCANAdr = REG_RXBuffer1; ? ? ?//訪問地址指向發(fā)送緩沖區(qū)1,修改成頭文件
memcpy(SJA_BCANAdr,SendDataBuf,4); //將SendDataBuf起始地址的的4個字節(jié)數(shù)據(jù)拷貝到 SJA_BCANAdr 發(fā)送緩沖區(qū)中
CAN_CMD_PRG(TR_CMD); ? ? ? ? ? ? //請求發(fā)送
return 0;
}
//CAN發(fā)送一個字節(jié)
void CAN_Send_onebyte(unsigned char CAN_TX_data)
{
unsigned char temptt;
loop:
SJA_BCANAdr = REG_STATUS;
temptt=*SJA_BCANAdr;
//temptt=Read_SJA1000(REG_STATUS);
if((temptt&0x04)==0x00) ?goto loop;//循環(huán)檢測等待
//可以向發(fā)送緩沖器寫數(shù)據(jù)
SJA_BCANAdr = REG_RXBuffer1;
*SJA_BCANAdr=0x01;
SJA_BCANAdr = REG_RXBuffer2;
*SJA_BCANAdr=0x28;
SJA_BCANAdr = REG_RXBuffer3;
*SJA_BCANAdr=0x00;
SJA_BCANAdr = REG_RXBuffer4;
*SJA_BCANAdr=CAN_TX_data;
//數(shù)據(jù)發(fā)送請求
CAN_CMD_PRG(TR_CMD);
}
void CAN_Send_Str(unsigned char *str)
{
unsigned char temptt,length;
loop:
SJA_BCANAdr = REG_STATUS;
temptt=*SJA_BCANAdr;
//temptt=Read_SJA1000(REG_STATUS);
if((temptt&0x04)==0x00) ?goto loop;//循環(huán)檢測等待
//可以向發(fā)送緩沖器寫數(shù)據(jù)
length=strlen(str);
SJA_BCANAdr = REG_TXBuffer1;
*SJA_BCANAdr=0x80|length; //設(shè)置發(fā)送信息幀位擴展數(shù)據(jù)幀 和發(fā)送的數(shù)據(jù)字節(jié)長度
SJA_BCANAdr = REG_TXBuffer2;
*SJA_BCANAdr=ID28_21;
SJA_BCANAdr = REG_TXBuffer3;
*SJA_BCANAdr=ID20_13;
SJA_BCANAdr = REG_TXBuffer4;
*SJA_BCANAdr=ID12_5;
SJA_BCANAdr =REG_TXBuffer5;
*SJA_BCANAdr=ID4_0;
SJA_BCANAdr = REG_TXBuffer6;
memcpy(SJA_BCANAdr,str,length);
//數(shù)據(jù)發(fā)送請求
CAN_CMD_PRG(TR_CMD);
}
/*****************************************************************
函數(shù)功能:SJA1000初始化
入口參數(shù):
返回參數(shù):
說明:
******************************************************************/
unsigned char SJA_Init(void)
{
bit s;
EA=0;//關(guān)總中斷
if (!Enter_RST_Mode()) return 1; //設(shè)置模式(控制)寄存器 置位復(fù)位請求位 和驗收濾波模式位(單濾波模式)
if (!SJA_Interface_Test()) return 2; //!!!!!我覺得此處邏輯上應(yīng)先測試SJA1000再進行復(fù)位操作
//0XC8=1100 0000 最高位CDR.7(CANmode位)=1=Pelican模式(=0=BasicCAN模式)
//置位CDR.6 可以中止CAN 輸入比較器 CDR.3置位關(guān)閉external CLKOUT CD2-CD0 設(shè)置時鐘分頻
//設(shè)置為PeliCAN模式,終止CAN輸入比較器(復(fù)位模式),關(guān)閉時鐘輸出
if (!Set_OutClock(0XC8)) return 3;
//設(shè)置濾波器濾波條件
SET_ACR(0x0A,0x4A,0x6B,0x78);
s=SET_AMR(0x00,0x00,0x00,0x03);
if (s==0) return 4;
if (!Set_Bandrate(ByteRate_1000k)) return 5;//設(shè)置通信波特率
if (!Set_IntEnable(0x1D)) return 6;
SJA_BCANAdr=REG_OCR ; ? ? ? ? ? ? ? //輸出控制寄存器
*SJA_BCANAdr=0x1a; ? ? ? ? ? ? ? ? ?//設(shè)置為正常輸出模式
if(!Quit_RST_Mode()) return 7;
EA=1;
PX0=1;//外部中斷0定義為高優(yōu)先級中斷
EX0=1;//開啟外部中斷
IT0=0;//外部中斷0觸發(fā)方式選擇位 此處設(shè)置為低電平觸發(fā)
return 0;
}
void Int0_ISR() interrupt 0
{
unsigned char tt,length;
SJA_BCANAdr=REG_INTERRUPT;//中斷寄存器
if((*SJA_BCANAdr)&0x01) ? //產(chǎn)生了接收中斷
{
UART_Send_String("SJA1000 Has recieved data!\r\n");
SJA_BCANAdr=REG_RXBuffer1;//CAN地址16 ?TX幀信息 低四位DLC.3-DLC.0數(shù)據(jù)長度代碼為
tt=*SJA_BCANAdr;
length=tt&0x0F;//獲取數(shù)據(jù)長度代碼
if ((tt&0x40)!=0x40) ? ? ? ? ? ? ? ? //最高位為幀格式位=0數(shù)據(jù)幀 ? =1 為遠程幀
{
SJA_BCANAdr=REG_RXBuffer6; ? ? ? ? ? //宏定義的變量不能memcpy(RevceData,REG_RXBuffer4,8);
memcpy(RevceData,SJA_BCANAdr,length);//功能:由src所指內(nèi)存區(qū)域復(fù)制count個字節(jié)到dest所指內(nèi)存區(qū)域
//測試用的主要是把接收到的數(shù)據(jù)在發(fā)出去,驗證數(shù)據(jù)的正確
//以下代碼是發(fā)送到串
UART_Send_String(RevceData);
}
CAN_CMD_PRG(RRB_CMD); ? ? ? ? ? ? ? ?//釋放SJA1000接收緩沖區(qū),****已經(jīng)修改
}
}
[1] [2]
本網(wǎng)站轉(zhuǎn)載的所有的文章、圖片、音頻視頻文件等資料的版權(quán)歸版權(quán)所有人所有,本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認版權(quán)者。如果本網(wǎng)所選內(nèi)容的文章作者及編輯認為其作品不宜公開自由傳播,或不應(yīng)無償使用,請及時通過電子郵件或電話通知我們,以迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟損失。
總結(jié)
以上是生活随笔為你收集整理的sja1000 c语言,基于51单片机SJA1000 CAN通讯实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: dbvisualizer使用手册
- 下一篇: 高新技术企业申请条件是什么?