?? sja1000.c
字號:
//***************************************************************************************************
//描 述:獨立CAN控制器SJA1000基本的函數定義(PeliCAN 查詢工作方式),需引用time.c文件. *
//文 件 名:sja1000_pelican_ie.c *
//日 期:2007年8月16日 *
//***************************************************************************************************
//模擬 數據/地址總線 版
/*引用前需將以下外部定義包函進去
extern void sja1000_init(void); //SJA1000的初始化函數,初始化值在此函數中定義
extern INT8S can_data_write(INT8U *senddatabuf); //將待發送的數據(13個字節),寫入SJA1000內部的發送緩存區中,然后啟動SJA1000發送
extern INT8S can_data_receive(INT8U *rcvdatabuf); //將SJA1000內部接收緩沖器的13個字節的數據,存入微處理器保存接收數據的緩沖區(13個字節).
*/
/*
修改歷史記錄列表:
<修改日期> <修改內容簡述>
2007/08/28 發送和接收 狀態的查詢 從查詢 狀態寄存器 改為查詢 中斷寄存器(因單片機自動復位) -- 沒有效果,取消
//2007/09/29 增加 初始化 錯誤判定,由 symbol_CANInitError 判定
*/
//***************************************************************************************************
#include "sja1000.h"
//定義接收/發送緩沖區變量
CAN_BUFFER CAN_ReceiveBuffer;
CAN_BUFFER CAN_SendBuffer;
//***************************************************************************************************
//函數原型: void init_sja1000(void) *
//參數說明: 無 *
//返 回 值: 無 *
//說 明: CAN控制器的初始化函數。初始化操作之前請先將要初始化的各參數的值按數據手冊中的計算方法, *
// 正確的按實際需要計算好參數后,將參數寫入對應的寄存器 。 *
// 注 : 為了CAN控制器的正確運行,請務必仔細的閱讀sja1000的數據手冊 *
//***************************************************************************************************
void init_sja1000(void)
{
INT8U temp;
INT8U overtime_value = 200; //設置 超時值(10000us=10ms)
//****進入復位模式******************
temp = read_sja_reg(REG_MODE); //讀出模式寄存器狀態
while(((temp & Bit_RM) != Bit_RM) && overtime_value != 0) //在 成功進入復位模式 或 超時 后退出循環
{
write_sja_reg(REG_MODE,Bit_RM); //寫模式寄存器,使之進入 復位;非睡眠;雙驗收濾波器;非自檢測;非只聽模式.
delay_us(50); //延時
overtime_value--;
temp = read_sja_reg(REG_MODE); //讀出模式寄存器狀態
}
if(overtime_value == 0) //進入復位模式 超時
{
#ifdef DEBUG //調試用
uart1_printf_ch("!!!!!!!! Enter Reset Mode OverTime ERR !!!!!!!!\n\r");
#endif
error(CAN_ENTRESET_ERR); //轉到錯誤處理,SJA1000進入復位模式 超時 失敗
}
//**** 設置 輸出模式 , 時鐘分頻 ****
write_sja_reg(REG_OCR,0x1a); //正常輸出模式,TX1懸空,TX0上拉
write_sja_reg(REG_CDR,0xc8); //PeliCAN 模式,時鐘關閉,禁止TX1作為專用接收中斷輸出,禁止CAN輸入比較器
//**** 設置 中斷使能 ***************
// write_sja_reg(REG_IER,(Bit_RIE | Bit_TIE | Bit_DOIE)); //接收和發送中斷使能,數據溢出中斷使能位
write_sja_reg(REG_IER,0); //全部中斷禁能
//**** 設置 驗收代碼和屏蔽 *********
write_sja_reg(REG_ACR0,0x01); //全部接收 , 不屏蔽
write_sja_reg(REG_ACR1,0x01);
write_sja_reg(REG_ACR2,0x01);
write_sja_reg(REG_ACR3,0x01);
write_sja_reg(REG_AMR0,0xff);
write_sja_reg(REG_AMR1,0xff);
write_sja_reg(REG_AMR2,0xff);
write_sja_reg(REG_AMR3,0xff);
//**** 設置 CAN總線波特率 ***********
write_sja_reg(REG_BTR0,0x87); //CAN總線波特率 = 50KBPS
write_sja_reg(REG_BTR1,0xdc);
//16M晶振下:0x93,0xdc(20KBPS);0x87,0xdc(50KBPS);0x83,0xdc(100KBPS);0x80,0x25(800KBPS)
//**** 初始化 CAN錯誤 寄存器 ********
write_sja_reg(REG_RXERR,0x00); //初始化 RX 錯誤計數寄存器
write_sja_reg(REG_TXERR,0x00); //初始化 TX 錯誤計數寄存器
write_sja_reg(REG_EWLR,96); //初始化 錯誤報警限制寄存器
//**** 退出復位模式 *****************
temp = read_sja_reg(REG_MODE); //讀出模式寄存器狀態
overtime_value = 200; //重置 超時值(10000us=10ms)
while(((temp & Bit_RM) == Bit_RM) && overtime_value != 0) //在 成功退出復位模式 或 超時 后退出循環
{
write_sja_reg(REG_MODE,(temp & (~Bit_RM))); //清除 復位模式請求位
delay_us(50); //延時
overtime_value--;
temp = read_sja_reg(REG_MODE); //讀出模式寄存器狀態
}
if(overtime_value == 0) //退出復位模式 超時
{
#ifdef DEBUG //調試用
uart1_printf_ch("\n\r\n\r!!!!!!!! Exit Reset Mode OverTime ERR !!!!!!!!\n\r");
#endif
error(CAN_QUITRESET_ERR); //轉到錯誤處理,SJA1000退出復位模式 超時 失敗
}
else
{
#ifdef DEBUG //調試用
uart1_printf_ch("\n\r\n\r!!!!!!!! Init SJA1000 OK !!!!!!!!\n\r");
#endif
}
}
//***************************************************************************************************
//函數原型: INT8S can_data_send(void) *
//參數說明: 無 *
//返 回 值: 0 ; 表示將數據(13個字節)寫入SJA1000內部的發送緩沖區 成功 *
// -1 ; 表示發送緩沖區鎖定,將數據(13個字節)寫入SJA1000內部的發送緩沖區 失敗 *
//說 明: 將待發送的數據(13個字節),寫入SJA1000內部的發送緩存區中,然后啟動SJA1000發送。 *
// 本函數的返回值僅指示,將數據寫入SJA1000內部的發送緩存區并成功執行發送命令與否。 *
// 不指示SJA1000將該數據正確發送到CAN總線上完畢與否。 *
//***************************************************************************************************
INT8S can_data_send(void)
{
INT8U temp;
INT8U overtime_value = 250; //設置 超時值(2500us)
//狀態判斷
// temp = read_sja_reg(REG_INTERRUPT); //讀出中斷寄存器狀態
// while(((temp & Bit_TI) == 0) && overtime_value != 0) //在 上次發送完成 或 超時 后退出循環
// {
// temp = read_sja_reg(REG_INTERRUPT); //讀出中斷寄存器狀態
// delay_us(10);
// overtime_value--;
// }
//8.28 注釋
temp = read_sja_reg(REG_STATUS); //讀出狀態寄存器狀態
// if((temp & Bit_ES) != 0) //出錯狀態位 有效
// {
// init_sja1000(); //重新初始化SJA1000
//
// #ifdef DEBUG //調試用
// uart1_printf_ch("!!!!!!!!!!!!CAN Bit_ES in Error state!!!!!!!!!!!!\n\r");
// #endif
//
// error(CAN_COUNTERS_ERR); //轉到錯誤處理,SJA1000 錯誤計數器 超限錯誤
// }
while(((temp & Bit_TCS) == 0) && overtime_value != 0) //在 上次發送完成 或 超時 后退出循環
{
temp = read_sja_reg(REG_STATUS); //讀出狀態寄存器狀態
delay_us(10);
overtime_value--;
}
#ifdef DEBUG //調試用
if(overtime_value != 250)
{
uart1_printf_ch("CAN send wait ");
temp = (250 - overtime_value) * 10;
uart1_printf_num8(&temp);
uart1_printf_ch(" us!\n\r");
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -