?? can._c
字號(hào):
/********************************************************************
* 函數(shù)庫說明:CAN總線驅(qū)動(dòng)函數(shù)庫 *
* 版本說明: 1.0 Bate *
* 作者: andylee *
* 日期: 2006年7月 *
* 平臺(tái): mega16 16M *
* 說明: 為上層提供CAN控制器的基本讀寫函數(shù),數(shù)據(jù)發(fā)送、接受函數(shù)*
********************************************************************/
#include "can.h"
#include "delay.h"
//#define DEBUG
#define TransBuffer TransmitMessage
/*********************
* 全局變量定義 *
*********************/
//unsigned char CanMode[14];
unsigned char TransmitMessage[13];
unsigned char RxBuffer[13];
#ifdef DEBUG
unsigned char temp1;
#endif
/********************************************************** **********
* 函數(shù)說明:CAN控制器引腳初始化 *
* 輸入: *
* 輸出:無 *
********************************************************************/
void sja_port_init(void)
{
//CAN數(shù)據(jù)線設(shè)置
PORTC=0x00;
DDRC=0xff;
PORTD=0b11000000; //INT引腳輸入不上拉
DDRD =0b11111000;
//CAN 控制引腳設(shè)置
CAN_DDR|=(1<<WR)|(1<<RD)|(1<<ALE)|(1<<CS);
WR_H;
RD_H;
ALE_L;
CS_H;
}
/********************************************************************
* 函數(shù)說明:模擬CAN收發(fā)時(shí)序,寫一個(gè)字節(jié)到CAN控制器 *
* 輸入:data,address *
* 輸出:無 *
********************************************************************/
void sja_write_data(unsigned char addr,unsigned char data)
{
RD_H;
DDRC=0xFF; //總線設(shè)置為輸出
// ALE_L;
PORTC=addr;
ALE_H;
NOP();
ALE_L; //下降沿地址鎖存
NOP();
PORTC=data;
CS_L;
WR_L;
NOP();
WR_H; //上升沿?cái)?shù)據(jù)寫入
NOP();
// ALE_H;
CS_H;
}
/********************************************************************
* 函數(shù)說明:模擬CAN收發(fā)時(shí)序,從CAN控制器讀一個(gè)字節(jié) *
* 輸入:address *
* 輸出:data *
********************************************************************/
unsigned char sja_read_data(unsigned char addr)
{
unsigned char data;
WR_H;
DDRC=0xFF; //總線設(shè)置為輸出
ALE_L;
PORTC=addr;
ALE_H;
NOP();
ALE_L; //地址鎖存
NOP();
PORTC=0xFF;
DDRC=0x00; //總線設(shè)置為輸入,內(nèi)部上拉
CS_L;
RD_L;
NOP();
RD_H;
NOP();
data=PINC;
CS_H;
return data;
}
/********************************************************************
* 函數(shù)說明:初始化SJA1000的相關(guān)寄存器:設(shè)置工作模式,波特率,驗(yàn)收碼*
* 輸入:無 *
* 輸出:無 *
********************************************************************/
void sja_init(void)
{
unsigned char temp;
unsigned int k ;
CLI();
sja_write_data(MODE,0x09); //單個(gè)驗(yàn)收濾波,復(fù)位模式
sja_read_data(IR); //讀取CAN的中斷標(biāo)識(shí),除接受中斷外的所有中斷復(fù)位
while(!( sja_read_data(MODE)&0x01)) //檢測(cè)SJA1000是否達(dá)到復(fù)位工作模式
{
sja_write_data(MODE,0x09); //進(jìn)入復(fù)位工作模式
}
delay_nus(5); //延時(shí)約5us
sja_write_data(CDR,REG_CDR_DATA); //PeliCAN 模式,旁路輸入比較器,禁能CLOCKOUT引腳
delay_nus(5); //延時(shí)約5us
sja_write_data(BTR0,BTR0_Rate_250k); //同步跳轉(zhuǎn)寬度4;時(shí)鐘4分頻,波特率250Kb/s
sja_write_data(BTR1,BTR1_Rate_250k); //采樣3次;時(shí)間段1,2=10,5
sja_write_data(OCR,REG_OCR_DATA); //輸出控制,推拉結(jié)構(gòu),正邏輯
sja_write_data(RXERR,0x00); //收發(fā)錯(cuò)誤寄存器清零
sja_write_data(TXERR,0x00);
sja_write_data(ECC,0x00); //錯(cuò)誤代碼捕捉寄存器清零
sja_write_data(RBSA,0x00); //緩存器起始地址寄存器設(shè)置為0
sja_write_data(ACR0,ACR0_ID); //驗(yàn)收屏蔽
sja_write_data(ACR1,ACR1_ID);
sja_write_data(ACR2,ACR2_ID);
sja_write_data(ACR3,ACR3_ID);
sja_write_data(AMR0,AMR0_ID);
sja_write_data(AMR1,AMR1_ID);
sja_write_data(AMR2,AMR2_ID);
sja_write_data(AMR3,AMR3_ID);
sja_write_data(IER,REG_IER_DATA); //開放接收中斷
sja_write_data(CMR,COS_CMD); //清除數(shù)據(jù)溢出
delay_nus(10);
sja_write_data(CMR,RRB_CMD); //釋放接收緩沖器
do
{
//sja_write_data(MODE,0x04); //設(shè)置SJA1000 工作模式;zijiance
sja_write_data(MODE,0x08); //設(shè)置SJA1000 工作模式
}
while((sja_read_data(MODE)&0x01)); //確認(rèn)復(fù)位標(biāo)志是否被刪除
SEI();
}
/********************************************************************
* 函數(shù)說明:SJA1000中斷發(fā)送服務(wù)程序,若有待發(fā)送報(bào)文則及時(shí)發(fā)送 *
* 輸入:無 *
* 輸出:無 *
********************************************************************/
void sja_tx_service(void)
{
unsigned char Length;
unsigned char FF,i;
if(flag.mess_wait==TRUE)
{
led_on;
flag.mess_wait=FALSE; //清報(bào)文待發(fā)送標(biāo)志
FF=TransmitMessage[0]&0x80; //取貞格式
Length=TransmitMessage[0]&0x0f; //取數(shù)據(jù)長度代碼
if(Length=0x08)
{
Length = 0x80;
}
sja_write_data(TXEFF,TransmitMessage[0]); //寫TX貞報(bào)文
sja_write_data(TXID0,TransmitMessage[1]); //寫TX標(biāo)識(shí)碼1
sja_write_data(TXID1,TransmitMessage[2]);
if(FF) //FF=0:標(biāo)準(zhǔn)CAN格式
{ //FF=1:擴(kuò)展CAN格式
sja_write_data(TXID2,TransmitMessage[3]);
sja_write_data(TXID3,TransmitMessage[4]);
}
for (i=0;i<Length;i++)
{
if(FF)
sja_write_data(TXDATA0+i,TransmitMessage[5+i]);
else
sja_write_data(TXDATA0+i,TransmitMessage[3+i]);
}
led_off;
//置位發(fā)送請(qǐng)求
//sja_write_data(CMR,0x10); //發(fā)送請(qǐng)求命令:zijieshou
sja_write_data(CMR,0x01); //發(fā)送請(qǐng)求命令當(dāng)錯(cuò)誤時(shí)可重發(fā)
}
}
/********************************************************************
* 函數(shù)說明:SJA1000發(fā)送服務(wù)程序 *
* 輸入:RAM中以TransmitMessage開始的CAN的發(fā)送報(bào)文 *
* 輸出:無 *
********************************************************************/
void sja_tx(unsigned char *TransmitMessage)
{
unsigned char Length;
unsigned char FF,i,state;
unsigned char sreg;
sreg=SREG; //保存全局中斷標(biāo)志
CLI();
state=sja_read_data(SR); //讀狀態(tài)寄存器
while(state&(1<<4)); //正在接受則等待
// while(state&(1<<3)); //上次發(fā)送未完成則等待
if(state&(1<<2)) //判斷發(fā)送緩沖是否釋放
{
led_on;
FF=TransmitMessage[0]&0x80; //取貞格式
Length=TransmitMessage[0]&0x0f; //取數(shù)據(jù)長度代碼
#ifdef DEBUG
rprintfCRLF();
rprintfStr("begin transmit...");
rprintfCRLF();
#endif
if(Length>8)
{
Length = 8;
}
sja_write_data(TXEFF,TransmitMessage[0]); //寫TX貞報(bào)文
sja_write_data(TXID0,TransmitMessage[1]); //寫TX標(biāo)識(shí)碼1
sja_write_data(TXID1,TransmitMessage[2]);
if(FF) //FF=0:標(biāo)準(zhǔn)CAN格式
{ //FF=1:擴(kuò)展CAN格式
sja_write_data(TXID2,TransmitMessage[3]);
sja_write_data(TXID3,TransmitMessage[4]);
}
for (i=0;i<Length;i++)
{
if(FF)
sja_write_data(21+i,TransmitMessage[5+i]);
else
sja_write_data(19+i,TransmitMessage[3+i]);
}
//置位發(fā)送請(qǐng)求
//sja_write_data(CMR,0x10); //發(fā)送請(qǐng)求命令
sja_write_data(CMR,0x01); //發(fā)送請(qǐng)求命令當(dāng)錯(cuò)誤時(shí)可重發(fā)
led_off;
#ifdef DEBUG
rprintfStr("transmit over");
rprintfCRLF();
rprintfCRLF();
#endif
}
else //發(fā)送緩沖被鎖,將數(shù)據(jù)存入RAM緩存
{
flag.mess_wait=TRUE;
}
SREG=sreg;
SEI();
}
/********************************************************************
* 函數(shù)說明:SJA1000接受中斷服務(wù)函數(shù), *
* 輸入:無 *
* 輸出:正確讀取返回TURE否則返回FALSE 。 *
* 影響變量:接受緩沖在正確讀取時(shí)被刷新 *
********************************************************************/
void sja_rx_service(void)
{
unsigned char number,i,ptr;
ptr=RXEFF;
if((sja_read_data(RXEFF)&0x40)==0x40) //如果RTR=1,為遠(yuǎn)程幀
{
sja_write_data(CMR,0x04); //則釋放接收緩沖
}
else //為0,則是數(shù)據(jù)幀
{
number=(sja_read_data(RXEFF)&0x0f);//取第一個(gè)字節(jié)的低四位,即數(shù)據(jù)長度
if (number>0x08)
number=0x08;
if ((sja_read_data(RXEFF))&0x80) //判斷是標(biāo)準(zhǔn)幀還是擴(kuò)展幀
{
number=number+5; //擴(kuò)展幀,則幀的總長度加5(13字節(jié))
}
else
{
number=number+3; //標(biāo)準(zhǔn)幀,則幀的總長度加3(11字節(jié))
}
for(i=0;i<number;i++) //讀取數(shù)據(jù)
{
RxBuffer[i]=sja_read_data(RXEFF+i);
ptr++;
}
sja_write_data(CMR,0x04); //最后釋放FXFIFO
}
}
/********************************************************************
* 函數(shù)說明:SJA1000查詢方式接收函數(shù), *
* 輸入:無 *
* 輸出:無 *
********************************************************************/
void Search(void)
{
unsigned char SearchStatus;
SearchStatus=sja_read_data(SR); //讀取狀態(tài)寄存器
#ifdef DEBUG
rprintfStr("SR: ");
rprintfu08(SearchStatus);
rprintfCRLF();
#endif
// if((SearchStatus & 0x83)) //是否存在總線關(guān)閉、錯(cuò)誤狀態(tài)、數(shù)據(jù)溢出、有數(shù)據(jù)位等狀態(tài)
// {
if(SearchStatus&(1<<7))//如果總線關(guān)閉
{
#ifdef DEBUG
rprintfStr("****bus shut off****");
rprintfCRLF();
#endif
sja_read_data(IR); //讀取中斷寄存器,清除中斷位
sja_write_data(MODE,0x08);
}
if(SearchStatus&0x02)//如果有數(shù)據(jù)溢出
{
#ifdef DEBUG
rprintfStr("****data overflow****");
rprintfCRLF();
#endif
sja_write_data(CMR,0x0c); //在命令寄存器中清除數(shù)據(jù)溢出和釋放接收緩沖區(qū)
}
if(sja_read_data(IR) & 0x01)//IR.0=1,接收緩沖區(qū)有數(shù)據(jù)
{
led_on;
#ifdef DEBUG
rprintfStr("****receive buffer have data****");
rprintfCRLF();
#endif
}
// }
}
//=============================================================================
//顯示緩沖區(qū)內(nèi)容
void play_buffer(unsigned char *ptr)
{
unsigned char i;
for (i=0;i<13;i++)
{
rprintfu08(*ptr);
// rprintfStr("--");
ptr++;
}
rprintfCRLF();
}
//=============================================================================
//初始化換沖區(qū),在此監(jiān)控卡上只有模擬管理系統(tǒng)降低充電電壓的情況
void buffer_init(void)
{
TransmitMessage[0]=0x88; //擴(kuò)展貞,8個(gè)數(shù)據(jù)字節(jié)
TransmitMessage[1]=192; //管理系統(tǒng)優(yōu)先級(jí)7: ID.28--ID.21=111-00-111
TransmitMessage[2]=168; //PF=255- 235 ID.20--ID.13=01011-000
TransmitMessage[3]=0x00; //PS=252- 22 ID.12--ID.5 =10110-000
TransmitMessage[4]=0x00; //As=0x11 ID.4--ID.0 =10001-000
TransmitMessage[5]=0xFF; //楨編號(hào)
TransmitMessage[6]=0x00;
TransmitMessage[7]=0xff;
TransmitMessage[8]=0xff;
TransmitMessage[9]=0xff;
TransmitMessage[10]=0xff;
TransmitMessage[11]=0xff;
TransmitMessage[12]=0xff;
}
void test_can(void)
{
rprintfCRLF();
rprintfStr("***CAN BUS DEBUG:***");
rprintfCRLF();
rprintfStr("content of transmit buffer ");
rprintfCRLF();
play_buffer(TransmitMessage);
CLI();
sja_tx(TransmitMessage);
SEI();
rprintfCRLF();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -