?? can.c
字號(hào):
/*****************************************************************************
;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ù)長(zhǎng)度
unsigned char NewDataMode=0;//接收到新的數(shù)據(jù)格式
//定義了16M晶體下,波特率預(yù)設(shè)值
unsigned char SJA_BTR_CODETAB[]={
0x18,0x1C, //;20KBPS的預(yù)設(shè)值
0x87,0xFF, //;40KBPS的預(yù)設(shè)值
0x09,0x1C, //;50KBPS的預(yù)設(shè)值
0x83,0xFF, //;80KBPS的預(yù)設(shè)值
0x04,0x1C, //;100KBPS的預(yù)設(shè)值
0x03,0x1c, //;125KBPS的預(yù)設(shè)值
0X81,0xfa, //;200KBPS的預(yù)設(shè)值
0x01,0x1c, //;250KBPS的預(yù)設(shè)值
0x80,0xfa, //;400KBPS的預(yù)設(shè)值
0x00,0x1c, //;500KBPS的預(yù)設(shè)值
0x80,0xb6, //;666KBPS的預(yù)設(shè)值
0x00,0x16, //;800KBPS的預(yù)設(shè)值
0x00,0x14, //;1000KBPS的預(yù)設(shè)值
};
#define BTR_INDEX 0
//延時(shí)函數(shù)
void Delay(char x,char y)
{
char z;
do {
z=y;
do {; } while(--z);
}while(--x);
}
//寫(xiě)can寄存器
void Write_CAN_REG(unsigned char can_reg_addr, unsigned char data)
{
WRITE_CAN_ADDR(can_reg_addr);//寫(xiě)寄存器抵制
WRITE_CAN_DATA(data);//寫(xiě)數(shù)據(jù)
}
//讀CAN寄存器
unsigned char Read_CAN_REG(unsigned char can_reg_addr)
{
unsigned char data;
WRITE_CAN_ADDR(can_reg_addr);//寫(xiě)寄存器抵制
data=READ_CAN_REG();
return data;
}
//初始化can
/*
初始化程序主要完成以下寄存器的設(shè)計(jì):
(1)通過(guò)對(duì)SJA1000的時(shí)鐘分頻寄存器定義,判斷是使用BassicCAN模式還是使用PeliCAN模式;
是否使能CLOCKOUT及輸出時(shí)鐘頻率;是否使用旁路CAN輸入比較器;
TX1輸出是否采用專門的接收中斷。
(2)通過(guò)寫(xiě)驗(yàn)收碼寄存器和驗(yàn)收屏蔽寄存器定義接收?qǐng)?bào)文的驗(yàn)收碼,
以及對(duì)報(bào)文和驗(yàn)收碼進(jìn)行比較的相關(guān)位定義驗(yàn)收屏蔽碼。
(3)通過(guò)寫(xiě)總線定時(shí)寄存器定義總線的位速率、位周期內(nèi)的采樣點(diǎn)和一個(gè)位周期內(nèi)的采樣數(shù)量。
(4)通過(guò)寫(xiě)輸出寄存器定義CAN總線輸出管腳TX0、TX1的輸出模式和輸出配置。
(5)清除SJA1000的復(fù)位請(qǐng)求標(biāo)志,進(jìn)入正常工作模式,這樣SJA1000方可進(jìn)行報(bào)文的發(fā)送和接收。
*/
unsigned char Init_CAN(void)
{
unsigned char reg;
int i;
unsigned char ucFlag;
//檢測(cè)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;//沒(méi)有找到sja1000
//初始化模式寄存器進(jìn)入復(fù)位模式,選擇單濾波方式
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;//進(jìn)入復(fù)位狀態(tài)
//設(shè)置總線控制,btr0
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_BTR0,SJA_BTR_CODETAB[BTR_INDEX]);//設(shè)置波特率,現(xiàn)在設(shè)置成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;//錯(cuò)誤返回錯(cuò)誤代碼
//設(shè)置輸出控制
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_OCR,PARAM_OCR);//設(shè)置成正常模式,0xda
reg=Read_CAN_REG(CAN_REG_OCR);
if(reg==PARAM_OCR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_OCR;
//時(shí)鐘分頻器
ucFlag=1;
for(i=0;i<REPEART_TIMES;i++)
{
Write_CAN_REG(CAN_REG_CDR,PARAM_CDR);//設(shè)置成pelican模式,cbp=1,關(guān)閉時(shí)鐘輸出
reg=Read_CAN_REG(CAN_REG_CDR);
if(reg==PARAM_CDR)
{
ucFlag=0;
break;
}
}
if(ucFlag)
return ERROR_CDR;
//接收錯(cuò)誤計(jì)數(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ā)送錯(cuò)誤計(jì)數(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;
//驗(yàn)收屏蔽,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;
//接收緩存器起始地址設(shè)為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;//錯(cuò)誤標(biāo)志位
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
//寫(xiě)TX楨信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_SFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//發(fā)送數(shù)據(jù),數(shù)據(jù)長(zhǎng)度8,標(biāo)準(zhǔn)楨格式
//寫(xiě)TX楨信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//發(fā)送數(shù)據(jù)識(shí)別碼
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//發(fā)送數(shù)據(jù)識(shí)別碼
//填寫(xiě)發(fā)送數(shù)據(jù)緩存
for(i=0;i<8;i++)
Write_CAN_REG((CAN_REG_TX_SFF_BUFFER+i),TXdata[i]);//包頭
#else
//寫(xiě)TX楨信息SFF
ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_EFF;
Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//發(fā)送數(shù)據(jù),數(shù)據(jù)長(zhǎng)度8,EFF楨格式
//寫(xiě)TX楨信息id0和id1
Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//發(fā)送數(shù)據(jù)識(shí)別碼
Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//發(fā)送數(shù)據(jù)識(shí)別碼
Write_CAN_REG(CAN_REG_TX_ID2,PARAM_TX_ID2);//發(fā)送數(shù)據(jù)識(shí)別碼
Write_CAN_REG(CAN_REG_TX_ID3,PARAM_TX_ID3);//發(fā)送數(shù)據(jù)識(shí)別碼
//填寫(xiě)發(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;
//unsigned char i;
//重新打開(kāi)中斷
//ClearPending(BIT_EINT2);
//訪問(wèn)地址指向狀態(tài)寄存器,判斷FIFO中的數(shù)據(jù)有沒(méi)有,其實(shí)在查詢的時(shí)候需要,在中斷的時(shí)候
//不需要
/*
reg=Read_CAN_REG(CAN_REG_SR);//
if((reg&0x01)==0) //判斷報(bào)文是否有效
{
exit(0);//
}*/
//讀出中斷狀態(tài)寄存器內(nèi)容,判斷當(dāng)前是那種中斷發(fā)生,并轉(zhuǎn)到響應(yīng)的中斷處理
//當(dāng)然必須在初始化過(guò)程中將相應(yīng)的中斷屏蔽位打開(kāi)了。
reg=Read_CAN_REG(CAN_REG_IR);//讀出中斷狀態(tài)寄存器內(nèi)容
switch(reg)
{
//置位;當(dāng)CAN控制器檢測(cè)到總線錯(cuò)誤且中斷使能寄存器中的BEIE被置位時(shí)此位被置位
case 0x80:
break;//自己添加處理程序了
//置位;當(dāng)CAN控制器丟失仲裁,變?yōu)榻邮掌骱椭袛嗍鼓芗拇嫫鞯腁LIE為被置位時(shí),此位被置位
case 0x40:
break;//自己添加處理程序了
//置位;當(dāng)CAN控制器到達(dá)錯(cuò)誤消極狀態(tài)(至少一個(gè)錯(cuò)誤計(jì)數(shù)器超過(guò)協(xié)議規(guī)定的值127)或從錯(cuò)誤消極狀態(tài)又進(jìn)入錯(cuò)誤活動(dòng)狀態(tài)以及中斷
//寄存器的EPIE位被置位時(shí)此位被置1
case 0x20:
break;//自己添加處理程序了
//置位;當(dāng)CAN控制器在睡眠模式中檢測(cè)到總線的活動(dòng)且中斷寄存器的WUIE位被置1時(shí)此位被置位
case 0x10:
break;//自己添加處理程序了
//置位;數(shù)據(jù)溢出狀態(tài)位有0-1 跳變且中斷寄存器的DOIE位被置位時(shí)此位被置1
case 0x08:
break;//自己添加處理程序了
//置位;錯(cuò)誤狀態(tài)位和總線狀態(tài)位的改變和中斷寄存器的EIE位被置位時(shí)此位被置1
case 0x04:
break;//自己添加處理程序了
//置位;發(fā)送緩沖器狀態(tài)從’0-1’(釋放)跳變且中斷寄存器的TIE位被置位時(shí)此位被置1
case 0x02:
break;//自己添加處理程序了
//置位;接收FIFO不空且中斷寄存器的RIE位被置位時(shí)此位被置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;
}
}*/
}
//響應(yīng)中斷接受數(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)//遠(yuǎn)程楨
TempCount=2;////遠(yuǎn)程楨
else
TempCount=(reg & 0x0f)+4;////計(jì)算報(bào)文中數(shù)據(jù)的個(gè)數(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)//遠(yuǎn)程楨
TempCount=2;////遠(yuǎn)程楨
else
TempCount=(reg & 0x0f)+2;////計(jì)算報(bào)文中數(shù)據(jù)的個(gè)數(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ù)格式和長(zhǎng)度
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;
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -