?? can.c.bak
字號:
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;Beijing Hengyi Embedded System Co.,Ltd (www.hyesco.com)
;File Name:
;Description: source for can sja1000
;Date: 2006-03-15
;Author: Wujh origin from jzm
;E_mail: wujh@hyesco.com
*****************************************************************************/
#include "can.h"
#include <stdlib.h>
#include <string.h>
extern void AT91F_DBGU_Printk(char *buf,...);
//發(fā)送緩存,接受緩存
unsigned char TXdata[12]={3,4,5,6,7,8,9,10,11,12,13,14};
unsigned char RXdata[100];
unsigned char bNewData=0;//接收到新的數(shù)據(jù)
unsigned char NewDataLength=0;//接收到新的數(shù)據(jù)長度
unsigned char NewDataMode=0;//接收到新的數(shù)據(jù)格式
//定義了16M晶體下,波特率預設值
unsigned char SJA_BTR_CODETAB[]={
0x18,0x1C, //;20KBPS的預設值
0x87,0xFF, //;40KBPS的預設值
0x09,0x1C, //;50KBPS的預設值
0x83,0xFF, //;80KBPS的預設值
0x04,0x1C, //;100KBPS的預設值
0x03,0x1c, //;125KBPS的預設值
0X81,0xfa, //;200KBPS的預設值
0x01,0x1c, //;250KBPS的預設值
0x80,0xfa, //;400KBPS的預設值
0x00,0x1c, //;500KBPS的預設值
0x80,0xb6, //;666KBPS的預設值
0x00,0x16, //;800KBPS的預設值
0x00,0x14, //;1000KBPS的預設值
};
#define BTR_INDEX 0
//延時函數(shù)
void Delay(char x,char y)
{
char z;
do {
z=y;
do {; } while(--z);
}while(--x);
}
//寫can寄存器
void Write_CAN_REG(unsigned char can_reg_addr, unsigned char data)
{
WRITE_CAN_ADDR(can_reg_addr);//寫寄存器抵制
WRITE_CAN_DATA(data);//寫數(shù)據(jù)
}
//讀CAN寄存器
unsigned char Read_CAN_REG(unsigned char can_reg_addr)
{
unsigned char data;
WRITE_CAN_ADDR(can_reg_addr);//寫寄存器抵制
data=READ_CAN_REG();
return data;
}
//初始化can
/*
初始化程序主要完成以下寄存器的設計:
(1)通過對SJA1000的時鐘分頻寄存器定義,判斷是使用BassicCAN模式還是使用PeliCAN模式;
是否使能CLOCKOUT及輸出時鐘頻率;是否使用旁路CAN輸入比較器;
TX1輸出是否采用專門的接收中斷。
(2)通過寫驗收碼寄存器和驗收屏蔽寄存器定義接收報文的驗收碼,
以及對報文和驗收碼進行比較的相關位定義驗收屏蔽碼。
(3)通過寫總線定時寄存器定義總線的位速率、位周期內的采樣點和一個位周期內的采樣數(shù)量。
(4)通過寫輸出寄存器定義CAN總線輸出管腳TX0、TX1的輸出模式和輸出配置。
(5)清除SJA1000的復位請求標志,進入正常工作模式,這樣SJA1000方可進行報文的發(fā)送和接收。
*/
unsigned char Init_CAN(void)
{
unsigned char reg;
int i;
unsigned char ucFlag;
//檢測sja1000存在
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_TEST,0x5a);
reg=Read_CAN_REG(CAN_REG_TEST);
if(reg==0x5a)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_NO_CAN;//沒有找到sja1000
//初始化模式寄存器進入復位模式,選擇單濾波方式
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_MOD,0x01);
reg=Read_CAN_REG(CAN_REG_MOD);
if(reg & 0x01)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RESET;//進入復位狀態(tài)
//設置總線控制,btr0
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_BTR0,SJA_BTR_CODETAB[BTR_INDEX]);//設置波特率,現(xiàn)在設置成20kbps
reg=Read_CAN_REG(CAN_REG_BTR0);
if(reg==SJA_BTR_CODETAB[BTR_INDEX])
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_BTR;
//btr1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_BTR1,SJA_BTR_CODETAB[BTR_INDEX+1]);
reg=Read_CAN_REG(CAN_REG_BTR1);
if(reg==SJA_BTR_CODETAB[BTR_INDEX+1])
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_BTR;//錯誤返回錯誤代碼
//設置輸出控制
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_OCR,PARAM_OCR);//設置成正常模式,0xda
reg=Read_CAN_REG(CAN_REG_OCR);
if(reg==PARAM_OCR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_OCR;
//時鐘分頻器
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_CDR,PARAM_CDR);//設置成pelican模式,cbp=1,關閉時鐘輸出
reg=Read_CAN_REG(CAN_REG_CDR);
if(reg==PARAM_CDR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_CDR;
//接收錯誤計數(shù)器清零
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_RXERR,0x00);
reg=Read_CAN_REG(CAN_REG_RXERR);
if(reg==0x00)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RXERR;
//發(fā)送錯誤計數(shù)器清零
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_TXERR,0x00);
reg=Read_CAN_REG(CAN_REG_TXERR);
if(reg==0x00)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_TXERR;
//初始化接收代碼寄存器 0x0000
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR0,PARAM_ACR0);
reg=Read_CAN_REG(CAN_REG_ACR0);
if(reg==PARAM_ACR0)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR1,PARAM_ACR1);
reg=Read_CAN_REG(CAN_REG_ACR1);
if(reg==PARAM_ACR1)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR2
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR2,PARAM_ACR2);
reg=Read_CAN_REG(CAN_REG_ACR2);
if(reg==PARAM_ACR2)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//ACR3
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_ACR3,PARAM_ACR3);
reg=Read_CAN_REG(CAN_REG_ACR3);
if(reg==PARAM_ACR3)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_ACR;
//驗收屏蔽,0xffff
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR0,PARAM_AMR0);
reg=Read_CAN_REG(CAN_REG_AMR0);
if(reg==PARAM_AMR0)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR1
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR1,PARAM_AMR1);
reg=Read_CAN_REG(CAN_REG_AMR1);
if(reg==PARAM_AMR1)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR2
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR2,PARAM_AMR2);
reg=Read_CAN_REG(CAN_REG_AMR2);
if(reg==PARAM_AMR2)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//AMR3
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_AMR3,PARAM_AMR3);
reg=Read_CAN_REG(CAN_REG_AMR3);
if(reg==PARAM_AMR3)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_AMR;
//中斷
//中斷使能寄存器
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_IER,PARAM_IER);
reg=Read_CAN_REG(CAN_REG_IER);
if(reg==PARAM_IER)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_IER;
//接收緩存器起始地址設為0
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_RBSA,PARAM_RBSA);
reg=Read_CAN_REG(CAN_REG_RBSA);
if(reg==PARAM_RBSA)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_RBSA;
//返回工作模式,選擇單濾波模式,
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_MOD,PARAM_RET_MOD);
reg=Read_CAN_REG(CAN_REG_MOD);
if((reg & 0x09)==0x08)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_MOD;
return 0;
}
//發(fā)送數(shù)據(jù)
int CAN_TRANSMIT(void)
{
unsigned char reg;
unsigned char ucFlag;//錯誤標志位
int i;
unsigned char ucRegTXSFF;
//發(fā)送緩存器鎖定否
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
reg=Read_CAN_REG(CAN_REG_SR);
if((reg==0x0c))
{
ucFlag=0;
break;
}
}
if(ucFlag)
return STATUS_TBS;
#ifndef SEND_EFF_DATA
//寫TX楨信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_SFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//發(fā)送數(shù)據(jù),數(shù)據(jù)長度8,標準楨格式
//寫TX楨信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//發(fā)送數(shù)據(jù)識別碼
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//發(fā)送數(shù)據(jù)識別碼
//填寫發(fā)送數(shù)據(jù)緩存
for(i=0;i<8;i++)
Write_CAN_REG((CAN_REG_TX_SFF_BUFFER+i),TXdata[i]);//包頭
#else
//寫TX楨信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_EFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//發(fā)送數(shù)據(jù),數(shù)據(jù)長度8,EFF楨格式
//寫TX楨信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//發(fā)送數(shù)據(jù)識別碼
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//發(fā)送數(shù)據(jù)識別碼
Write_CAN_REG(CAN_REG_TX_ID2,PARAM_TX_ID2);//發(fā)送數(shù)據(jù)識別碼
Write_CAN_REG(CAN_REG_TX_ID3,PARAM_TX_ID3);//發(fā)送數(shù)據(jù)識別碼
//填寫發(fā)送數(shù)據(jù)緩存
for(i=0;i<8;i++)
Write_CAN_REG((CAN_REG_TX_EFF_BUFFER+i),TXdata[i]);//包頭
#endif
//發(fā)送數(shù)據(jù)
Write_CAN_REG(CAN_REG_CMR,0x01);//正常發(fā)送數(shù)據(jù)
//判斷發(fā)送數(shù)據(jù)失敗
ucFlag=1;
for(i=0;i<REPEART_TIMES*10;i++)
{
reg=Read_CAN_REG(CAN_REG_SR);
if((reg & 0x08))
{
ucFlag=0;
break;
}
Delay(200,200);
}
if(ucFlag)
return STATUS_TCS;
return 0;
}
//CAN接收數(shù)據(jù)
//can中斷分發(fā)向量函數(shù)
void Eint2CanInt(void)
{
unsigned char reg,i;
//重新打開中斷
//ClearPending(BIT_EINT2);
//訪問地址指向狀態(tài)寄存器,判斷FIFO中的數(shù)據(jù)有沒有,其實在查詢的時候需要,在中斷的時候
//不需要
/*
reg=Read_CAN_REG(CAN_REG_SR);//
if((reg&0x01)==0) //判斷報文是否有效
{
exit(0);//
}*/
//讀出中斷狀態(tài)寄存器內容,判斷當前是那種中斷發(fā)生,并轉到響應的中斷處理
//當然必須在初始化過程中將相應的中斷屏蔽位打開了。
reg=Read_CAN_REG(CAN_REG_IR);//讀出中斷狀態(tài)寄存器內容
switch(reg)
{
//置位;當CAN控制器檢測到總線錯誤且中斷使能寄存器中的BEIE被置位時此位被置位
case 0x80:
break;//自己添加處理程序了
//置位;當CAN控制器丟失仲裁,變?yōu)榻邮掌骱椭袛嗍鼓芗拇嫫鞯腁LIE為被置位時,此位被置位
case 0x40:
break;//自己添加處理程序了
//置位;當CAN控制器到達錯誤消極狀態(tài)(至少一個錯誤計數(shù)器超過協(xié)議規(guī)定的值127)或從錯誤消極狀態(tài)又進入錯誤活動狀態(tài)以及中斷
//寄存器的EPIE位被置位時此位被置1
case 0x20:
break;//自己添加處理程序了
//置位;當CAN控制器在睡眠模式中檢測到總線的活動且中斷寄存器的WUIE位被置1時此位被置位
case 0x10:
break;//自己添加處理程序了
//置位;數(shù)據(jù)溢出狀態(tài)位有0-1 跳變且中斷寄存器的DOIE位被置位時此位被置1
case 0x08:
break;//自己添加處理程序了
//置位;錯誤狀態(tài)位和總線狀態(tài)位的改變和中斷寄存器的EIE位被置位時此位被置1
case 0x04:
break;//自己添加處理程序了
//置位;發(fā)送緩沖器狀態(tài)從’0-1’(釋放)跳變且中斷寄存器的TIE位被置位時此位被置1
case 0x02:
break;//自己添加處理程序了
//置位;接收FIFO不空且中斷寄存器的RIE位被置位時此位被置1
case 0x01:
CanIntReceiveData();
break;
}
/*
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_IER,PARAM_IER);
reg=Read_CAN_REG(CAN_REG_IER);
if(reg==PARAM_IER)
{
break;
}
}*/
}
//響應中斷接受數(shù)據(jù)
void CanIntReceiveData(void)
{
unsigned char TempCount;
unsigned char reg;
unsigned char i;
//判斷楨信息SFF,EFF OR SFF
reg=Read_CAN_REG(CAN_REG_RX_SFF);
if((reg&0x80)==0x80)//eff,楨
{
if((reg & 0x40)==0x40)//遠程楨
TempCount=2;////遠程楨
else
TempCount=(reg & 0x0f)+4;////計算報文中數(shù)據(jù)的個數(shù)
for(i=0;i<TempCount;i++)
RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);
Write_CAN_REG(CAN_REG_CMR,0x04);
bNewData=1;
NewDataMode=1;
NewDataLength=TempCount;
}
else//sff楨
{
if((reg & 0x40)==0x40)//遠程楨
TempCount=2;////遠程楨
else
TempCount=(reg & 0x0f)+2;////計算報文中數(shù)據(jù)的個數(shù)
for(i=0;i<TempCount;i++)
RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);
Write_CAN_REG(CAN_REG_CMR,0x04);
bNewData=1;
NewDataMode=0;
NewDataLength=TempCount;
}
}
//不停發(fā)送數(shù)據(jù)主程序
void CanSendData(void)
{
int ret;
ret=CAN_TRANSMIT();
if(ret)
{
AT91F_DBGU_Printk("Can send data error,error id=%d!\n",ret);
}
else
{
AT91F_DBGU_Printk("Can send data success!\n");
}
}
//不停接收數(shù)據(jù)主程序
void CanReceiveData(void)
{
unsigned char i;
if(bNewData == 1)
{
bNewData=0;
if(NewDataMode)
AT91F_DBGU_Printk("EFF Data,Data Lenght=%d\n",NewDataLength);//數(shù)據(jù)格式和長度
else
AT91F_DBGU_Printk("SFF Data,Data Lenght=%d\n\r",NewDataLength);
for(i=0;i<NewDataLength;i++)
AT91F_DBGU_Printk("RXdata[%d]=0x%x\n\r",i,RXdata[i]);//輸出數(shù)據(jù)
NewDataLength=0;
NewDataMode=0;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -