一.實驗目的
通過調用CAN 程序庫SJA1000_PELI.LIB 的基本函數,實現實驗板上CAN 節點
的初始化以及CAN 節點的自發自收測試。
二. 驗設備及器件
IBM PC 機 一臺
DP-51PROC 單片機綜合仿真實驗儀 一臺
三. 實驗內容
編寫一段程序,調用SJA1000_PELI.LIB 中的函數,實現CAN 節點的初始化,
能夠進行數據的自發自收,并能在LED 上顯示相關的信息。
四. 實驗要求
學會對CAN 節點的基本操作,理解實現CAN 通信的基本流程。
五. 實驗步驟
1. 將CAN-bus PARK 插在到A6 區中,用導線連接A6 區的P1_IO2 到A2 區的P10,
連A6 區的P1_CS 到和A2 區的A15。
2. 使用導線把A2 區的P16 和P17 分別于D5 區的SCL 和SDA 相連。使用導線把
D5 區的RST_L 與VCC 相連
3. 如果用戶采用中斷方式,將A6 區的P1_INT 接到A2 區的INT0 或INT1 另外改
相應的程序即可。
4. 利用SJA1000_PELI 庫編寫CAN 節點的初始化和自發自收程序。
5. 利用ZLG7290,將CAN 節點自發自收數據的成功與否顯示出來。
六. 實驗預習要求
1. 閱讀關于CAN 和CAN 相關器件的基本介紹,具備CAN 和CAN 相關器件的基本知
識。
2. 閱讀配套光盤中的《SJA1000_PELI 庫說明及其使用》文檔,了解在如何在程序中
應用SJA1000_PELI 庫。
七. 實驗參考程序
#include <REG52.H>
#include "VIIC_C51.h" //I2C程序庫頭文件
#include "Sja1000_peli.h" //CAN程序庫頭文件
#define uchar unsigned char
#define ZLG7290 0x70
sbit RESET_PIN=P1^0;
uchar Display_Buffer[5]={0x0d,0x15,0x15,0x10}; //顯示GOOD
uchar CAN_Baudrate_Filter_Buffer[9]={14,0,0,0,0,0xff,0xff,0xff,0xff};
//存放設置波特率和濾波器的數據
uchar Send_CAN_Info_ID[5]={0x88,0x00,0x00,0x00,0x00};
//存放信息幀的數據,符合CAN2.0B
uchar Send_Data_For_Self[8]={ 0x01,0x02,0x03,0x04,
0x05,0x06,0x07,0x08};
//存放數據幀的數據
uchar ScanNum[1];
/*------------------------------------------------------------------------------------
** 函數原型: void Delay_ms(uchar j)
** 功能描述: 該函數用于不精確的延時。在12M,6CLK下,大約延時j*1ms
** 參數說明: 0-255
** 返回值: 無
/*----------------------------------------------------------------------------------*/
void Delay_ms(uchar j)
{
uchar k,l;
for(l=0;l<=j;l++)
{
for(k=0;k<=250;k++)
{
;
}
}
}
/*------------------------------------------------------------------------------------
** 函數原型: unsigned char ZLG7290_SendCmd( unsigned char Data1,
unsigned char Data2)
** 功能描述: 發送命令(對子地址7、8)
** 參數說明: DATA1: 命令1
** DATA2: 命令2
** 返回值: 0 失敗
** 1 成功
/*----------------------------------------------------------------------------------*/
unsigned char ZLG7290_SendCmd( unsigned char Data1,
unsigned char Data2)
{
unsigned char Data[2];
Data[0]=Data1;
Data[1]=Data2;
ISendStr(ZLG7290,0x07,Data,2);
Delay_ms(10);
return 1;
}
/*------------------------------------------------------------------------------------
** 函數原型: void ZLG7290_SendDisBuf( unsigned char *disp_buf,
unsigned char num)
** 功能描述: 向顯示緩沖區發送數據
** 參數說明: *disp_buf 要發送數據的起始地址
** num 發送個數
** 返回值: 無
/*----------------------------------------------------------------------------------*/
void ZLG7290_SendDisBuf(unsigned char *disp_buf,unsigned char num)
{
unsigned char i;
for(i=0;i<num;i++)
{
ZLG7290_SendCmd(0x60+i,*disp_buf);
disp_buf++;
}
}
/*------------------------------------------------------------------------------------
** 函數原型: void SJA1000_Config_Self(void)
** 功能描述: 對SJA1000的在自發自收模式下的初始化配置
** 參數說明: 無
** 返回值: 無
/*----------------------------------------------------------------------------------*/
void SJA1000_Config_Self(void)
{
SJAEntryResetMode(); //進入復位模式
WriteSJAReg(REG_CAN_CDR,0xc8); //選擇PeliCAN模式
SetBitMask(REG_CAN_MOD,AFM_BIT); //選擇單濾波模式
SetBitMask(REG_CAN_MOD,STM_BIT); //選擇自檢測模式
WriteSJARegBlock(16,&CAN_Baudrate_Filter_Buffer[1],8);
//設置驗收代碼/屏蔽寄存器
WriteSJAReg(REG_CAN_OCR,0x1a); //設置輸出管腳
SJASetBaudrateStandard(CAN_Baudrate_Filter_Buffer[0]);
//設置總線定時器,確定波特率
SJAQuitResetMode(); //退出復位模式
}
/*------------------------------------------------------------------------------------
** 函數原型: unsigned char Send_Sja1000_Self(void)
** 功能描述: 把數據傳送到SJA1000的接收緩沖區,并進行自發自收的測試
** 參數說明: 無
** 返回值: 0 失敗
** 1 成功
/*----------------------------------------------------------------------------------*/
unsigned char Send_Sja1000_Self(void)
{
uchar i;
SJA1000_Config_Self();
WriteSJAReg(REG_CAN_IER,0x03); //使能接收發送中斷標志位
Delay_ms(100);
for(i=0;i<2;i++)
{
if((ReadSJAReg(REG_CAN_SR)&0x0c)==0x0c)//判斷是否可以發送
{
WriteSJARegBlock(16,Send_CAN_Info_ID,5);
//擴展幀,向發送緩沖區寫入5個數據
WriteSJARegBlock(21,Send_Data_For_Self,8);
//擴展幀,向發送緩沖區寫入8個數據
SetBitMask(REG_CAN_CMR,SRR_BIT); //使能自發送請求標志位
return(1); //返回發送成功標志
}
else
{
Delay_ms(200); //延時200ms
}
return(0); //返回發送失敗標志
}
}
/*------------------------------------------------------------------------------------
** 函數原型: void main(void)
** 功能描述: 主函數
** 參數說明: 無
** 返回值: 無
/*----------------------------------------------------------------------------------*/
void main()
{
RESET_PIN=0;
//將SJA1000的復位線與P1.0相連接
Delay_ms(1);
RESET_PIN=1;
//控制P1.0來實現SJA1000的復位
SJA_CS_Point=&CAN_SJA_BaseAdr; //確定SJA1000的基址
ScanNum[0]=0; //不顯示
Display_Buffer[0]=0x1f;
ZLG7290_SendDisBuf(Display_Buffer,0);
ISendStr(ZLG7290,0x0d,ScanNum,1);
Delay_ms(100);
if(Send_Sja1000_Self())
{
Delay_ms(200);
if((ReadSJAReg(REG_CAN_IR)==0x03)) //查詢接收/發送中斷位
{
WriteSJAReg(REG_CAN_CMR,4); //釋放接收緩沖區
ScanNum[0]=3; //掃描4位
Display_Buffer[0]=0x0d; //顯示Good
Display_Buffer[1]=0x15;
Display_Buffer[2]=0x15;
Display_Buffer[3]=0x10;
ISendStr(ZLG7290,0x0d,ScanNum,1);
ZLG7290_SendDisBuf(Display_Buffer,4);
}
else
{
ScanNum[0]=4; //掃描5位
Display_Buffer[0]=0x18; //顯示Error
Display_Buffer[1]=0x15;
Display_Buffer[2]=0x18;
Display_Buffer[3]=0x18;
Display_Buffer[4]=0x0e;
ISendStr(ZLG7290,0x0d,ScanNum,1);
}
else
{
ScanNum[0]=4; //掃描5位
Display_Buffer[0]=0x18; //顯示Error
Display_Buffer[1]=0x15;
Display_Buffer[2]=0x18;
Display_Buffer[3]=0x18;
Display_Buffer[4]=0x0e;
ISendStr(ZLG7290,0x0d,ScanNum,1);
ZLG7290_SendDisBuf(Display_Buffer,5);
}
while(1)
{
; //死循環
}
}
在本示范程序中,采用了查詢中斷標志位的方式來判斷自發自收數據是否成功。用戶也
可以將SJA1000的INT管腳連接到MCU的外部中斷管腳上,并使能相應的中斷位,在程序
中編寫中斷服務程序來實現同樣的功能。采用中斷的方式,可以提高系統的實時性。特別是
在接收數據的時候,采用中斷方式可以在效率和實時性上比采用查詢方式得到很大的提高。
接收數據采用中斷方式的程序流程圖如下所示。
八. 實驗程序流程圖
圖3.42 CAN 節點自發自收基本流程圖
九. 實驗思考題
(1) 請用戶思考一下,如何編寫CAN 總線數據的正常發送程序。
(2) 請用戶再思考一下,如何編寫CAN 總線數據的接收程序。
評論
查看更多