新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > SJA1000 CAN驅(qū)動程序演示實驗

SJA1000 CAN驅(qū)動程序演示實驗

作者: 時間:2016-12-14 來源:網(wǎng)絡(luò) 收藏
一.實驗?zāi)康?p>本驅(qū)動程序展示了如何在Small RTOS中編寫SJA1000 的驅(qū)動程序。通過調(diào)用CAN
序庫SJA1000_PEI.LIB 的基本函數(shù),實現(xiàn)實驗板上CAN 節(jié)點的初始化以及CAN 節(jié)點數(shù)據(jù)
收發(fā)測試。
二.實驗設(shè)備及器件
PC 機 一臺
DP-51PROC 單片機綜合仿真實驗儀 一臺
CAN PARK 模塊 一臺
CAN 連接線 一根
三.實驗步驟
1、 將CAN-bus PARK 插入到A6 區(qū)中,用導(dǎo)線連接A6 區(qū)的P1_IO2 到A2 區(qū)的P10,
連接A6 區(qū)的P1_CS1 到A2 區(qū)的A15。
2、 使用導(dǎo)線把A2 區(qū)的P16 和P17 分別于D5 區(qū)的SCL 和SDA 相連。使用導(dǎo)線把D5
區(qū)的/RST 與VCC 相連。
3、 由于本程序使用中斷方式響應(yīng)SJA1000 中斷,故將A5 區(qū)的P1_INT 接到A2 區(qū)的
INT0。
4、 利用CAN 連接線將兩臺已經(jīng)安裝了CAN-Bus 模塊的DP-51PROC 連接起來,以組
成簡單的CAN 網(wǎng)絡(luò)實現(xiàn)CAN 的接收和發(fā)送。
5、 本驅(qū)動程序已經(jīng)將輸出文件路徑設(shè)置為“E:Temp”,用戶可自行更改輸出文件路徑。
將路徑“E:Temp”中的CAN. hex 文件下載到兩臺DP-51PROC 中運行。
四.實驗參考程序主要部分
/******************************************************
*描述: 獨立的CAN 控制器SJA1000PeliCAN 在small rtos 中的應(yīng)用示例
*文件名: PELIRTOS.c
*應(yīng)用語言: KEIL C51
*應(yīng)用系統(tǒng): small rtos
*版本 : V1.0
*廣州周立功單片機發(fā)展有限公司 保留所有的版權(quán)
****************************************************/
#define _TIME_MODULE_H
#define _SERIAL_H
/********************************************************
** 導(dǎo)入頭文件
******************************************************/
#include "INCLUDES.h"
#include "Sja1000_peli.h"
sfr IPH=0xb7;

本文引用地址:http://butianyuan.cn/article/201612/329641.htm

sbit RESET_PIN=P1^0;
// 驗收代碼/屏蔽寄存器的內(nèi)容(4+4)
uint8 xdata Send_CAN_Filter[8]={0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xff};
// 幀信息和標(biāo)示碼(1+4)分別對應(yīng) TX,TX1,TX2,TX3,TX4
uint8 xdata Send_CAN_Info_ID[3]={0xc7,0x0A,0x0B};
uint8 xdata Recv_CAN_Info_ID[3];
// 待發(fā)送數(shù)據(jù)(8)
uint8 xdata
Send_CAN_Data[13]={0xc7,0x0A,0x0B,0x04,0x05,0x06,0x07,0x08,0x07,0x08,0x07,0x08,
0x08};
uint8 xdata Recv_CAN_Data[14];
uint8 xdata time_Counter=0;
uint8 xdata BTR0,BTR1;
uint16 xdata *p;
uint8 xdata disp_buf[8];
void CAN_Send(void);
void display(void);
void CAN_Rcv(void);
void TimeSum(void);
void Delay_ms(uint8 j);
void SJA1000_Config_Normal(void);
void Init(void)
{
CKCON=1; //應(yīng)用6clock
TMOD = (TMOD & 0XF0) | 0X01;
TCON=TCON|0x04; //MCU 的INT1 下降沿觸發(fā),INT0 電平觸發(fā)
TH0 = (65536 - (11059200 / 12) / 100) / 256;
TL0 = (65536 - (11059200 / 12) / 100) % 256;
TR0 = 1;
ET0 = 1;
TF0 = 0;
}
/****************************************************************
**函數(shù)名稱:void CAN_Init(void)
**功能描述:復(fù)位SJA1000,并設(shè)置其工作在正常模式
*****************************************************************/
void CAN_Init(void)
{

RESET_PIN=0; //將SJA1000 的復(fù)位線與P1.0 相連接
Delay_ms(1);
RESET_PIN=1; //控制P1.0 來實現(xiàn)SJA1000 的復(fù)位
SJA_CS_Point=&CAN_SJA_BaseAdr;
SJA1000_Config_Normal();
WriteSJAReg(REG_CAN_IER,RIE_BIT); //使能SJA1000 接收中斷
EX0=1;
}
/**************************************************************
** 函數(shù)原型: void Delay_ms(uchar j)
** 功能描述: 該函數(shù)用于不精確的延時。在12M,6CLK 下,大約延時j*1ms
***************************************************************/
void Delay_ms(uint8 j)
{
uint8 k,l;
for(l=0;l<=j;l++)
{
for(k=0;k<=250;k++)
{
;
}
}
}
/************************************************************
** 函數(shù)原型: void SJA1000_Config_Normal(void)
** 功能描述: 對SJA1000 的正常模式的初始化配置
***************************************************************/
void SJA1000_Config_Normal(void)
{
BTR0=0x00;
BTR1=0x14; //設(shè)置為80k 波特率通信
SJAEntryResetMode(); //進入復(fù)位模式
WriteSJAReg(REG_CAN_CDR,0xc8); //配置時鐘分頻寄存器,選擇PeliCAN 模式
WriteSJAReg(REG_CAN_MOD,0x01); //配置模式寄存器,選擇雙濾波、正常模式
WriteSJARegBlock(16,Send_CAN_Filter,8); //配置驗收代碼/屏蔽寄存器
WriteSJAReg(REG_CAN_BTR0,BTR0); //配置總線定時器0
WriteSJAReg(REG_CAN_BTR1,BTR1); //配置總線定時器1
WriteSJAReg(REG_CAN_OCR,0x1a); //配置輸出管腳
SJAQuitResetMode(); //退出復(fù)位模式,進入工作模式
}
/*********************************************************** 函數(shù)原型: void CAN_Data_Send(void)
** 功能描述: SJA1000 的單次發(fā)送子函數(shù)(注意在這個函數(shù)的末尾要置位接收中斷)
*************************************************************/
void CAN_Data_Send(void)
{
// 發(fā)送數(shù)據(jù)
WriteSJAReg(REG_CAN_IER,0x02); //使能SJA1000 發(fā)送中斷位
WriteSJARegBlock(16,Send_CAN_Data,13);
WriteSJAReg(REG_CAN_CMR,1); //使能發(fā)送請求
Delay_ms(10);
WriteSJAReg(REG_CAN_IER,RIE_BIT); //使能SJA1000 接收中斷
}
/**************************************************************
** 函數(shù)原型: void SJA1000_INT0 (void) interrupt 0
** 功能描述: SJA1000 中斷響應(yīng)函數(shù)
***************************************************************/
void SJA1000_INT0(void) interrupt 0
{
OS_INT_ENTER();
EX0 = 0;
OSIntSendSignal(0); //無條件的令CAN 接收中斷處理任務(wù)(CAN_Rcv ())處于就緒狀
態(tài)
//由于CAN_Rcv ()的優(yōu)先級最高,故中斷退出后立刻執(zhí)行
CAN_Rcv ().
OSIntExit();
}
void main(void)
{
uint8 i ;
OSInit();
Init();
CAN_Init();
//初始化顯示緩存
for(i=0;i<8;i++)
{
disp_buf[i]=31;
}
//創(chuàng)建任務(wù)
OSTaskCreate(CAN_Rcv, NULL, 0);

OSTaskCreate(display, NULL, 1);
OSTaskCreate(CAN_Send, NULL, 2);
OSTaskCreate(TimeSum, NULL, 3);
while(1)
{
PCON = PCON | 0x01; //令CPU 進入睡眠狀態(tài)
}
}
/*****************************************************************
**鍵值發(fā)送任務(wù)
*****************************************************************/
void CAN_Send(void)
{
uint8 key_data;
while(1)
{
key_data = ZLG7290_GetKey();
if(key_data)
{
Send_CAN_Data[3] = key_data;
CAN_Data_Send();
disp_buf[4] = key_data % 10;
disp_buf[5] = (key_data / 10) % 10;
}
OSWait(K_TMO,5);
}
}
/****************************************************************
**顯示任務(wù)
*****************************************************************/
void display(void)
{
while(1)
{
OSWait(K_TMO,5);
OS_ENTER_CRITICAL();
ZLG7290_SendBuf(&disp_buf[0], 8);
OS_EXIT_CRITICAL();
}
}
/***************************************************************
**CAN 接收中斷處理任務(wù)

***************************************************************/
void CAN_Rcv(void)
{
while(1)
{
OSWait(K_SIG, 0); //掛起當(dāng)前任務(wù),等待喚醒信號
if(ReadSJAReg(REG_CAN_IR)&0x01)
{
//數(shù)據(jù)接收一定在釋放緩沖區(qū)之前,釋放后數(shù)據(jù)不確定
ReadSJARegBlock(16,Recv_CAN_Data,13);
WriteSJAReg(REG_CAN_CMR,4); //釋放SJA1000 接收緩沖區(qū)
disp_buf[0] = Recv_CAN_Data[3] % 10;
disp_buf[1] = (Recv_CAN_Data[3] / 10) % 10;
}
EX0 = 1;
}
}
/*****************************************************
* *計數(shù)任務(wù)
***************************************************************/
void TimeSum(void)
{
while(1)
{
OSWait(K_TMO, 5);
disp_buf[7]++;
if(disp_buf[7] > 9)
{
disp_buf[7] = 0;
}
}
}
五.實驗例程簡析
本驅(qū)動程序采用中斷方式接收CAN 總線數(shù)據(jù)。采用中斷的方式,可以提高系統(tǒng)的實時性。特別的在接收數(shù)據(jù)的時候,采用中斷方式可以在效率和實時性上比采用非中斷方式得到很大的提高。
按下D5 區(qū)的按鍵時,左邊的LED 將顯示按鍵鍵值,同時程序調(diào)用CAN_Data_Send ( )
將檢測到的鍵值通過CAN 總線發(fā)送到另一臺實驗儀上。實驗儀將從CAN 總線上接收到的
鍵值數(shù)據(jù)顯示在D5 區(qū)的右邊LED 上。
D5 區(qū)中最右邊的LED 管循環(huán)地顯示0~9,目的是為了顯示系統(tǒng)正在運行。
有關(guān)SJA1000_PEI 庫的使用請閱讀配套光盤中的《SJA1000_PEI 庫說明及其使用》文檔。



評論


技術(shù)專區(qū)

關(guān)閉