CAN總線標準
物理層
數據鏈路層
幀起始
仲裁段
控制段
數據段
CRC段
ACK段
遠程幀
過載幀
幀間隔
構建CAN節點
CAN協議應用層概述
CAN收發器
CAN控制器與MCU的連接方式
#define REG_BASE_ADDR 0xA000 // 寄存器基址
unsigned char *SJA_CS_Point = (unsigned char *) REG_BASE_ADDR ;
// 寫SJA1000寄存器
void WriteSJAReg(unsigned char RegAddr, unsigned char Value) {
*(SJA_CS_Point + RegAddr) = Value;
return;
}
// 讀SJA1000寄存器
unsigned char ReadSJAReg(unsigned char RegAddr) {
return (*(SJA_CS_Point + RegAddr));
}
?
?
?
將緩存區的數據連續寫入寄存器
……
for (i=0;i
{
WriteSJAReg(RegAdr+i,ValueBuf[i]);
}
……
將連續多個寄存器連續讀入緩存區
……
for (i=0;i
ReadSJAReg(RegAdr+i,ValueBuf[i]);
}
……
?
?
頭文件包含方案:
每個程序包含用到的頭文件
每個程序包含一個公用頭文件,公用頭文件包含所有其他頭文件
#ifndef __CONFIG_H__ // 防止頭文件被重復包含
#define __CONFIG_H__
#include <8051.h>// 包含80C51寄存器定義頭文件
#include "SJA1000REG.h" // 包含SJA1000寄存器定義頭文件
// 定義取字節運算
#define LOW_BYTE(x) (unsigned char)(x)
#define HIGH_BYTE(x) (unsigned char)((unsigned int)(x) >>8)
// 定義振蕩器時鐘和處理器時鐘頻率(用戶可以根據實際情況作出調整)
#define OSCCLK 11059200UL
// 宏定義MCU的時鐘頻率
#define CPUCLK (OSCCLK / 12)
#endif // __CONFIG_H__
SJA1000上電后處于復位狀態,必須初始化后才能工作。
(1)置位模式寄存器Bit0位進入復位模式;
(2)設置時鐘分頻寄存器選擇時鐘頻率、CAN模式;
(3)設置驗收濾波,設定驗證碼和屏蔽碼;
(4)設置總線定時器寄存器0、1設定CAN波特率;
(5)設置輸出模式;
(6)清零模式寄存器Bit0位退出復位模式;
模式寄存器
?
只檢測模式:SJA1000發送CAN幀時不檢查應答位;
只聽模式:此模式下SJA1000不會發送錯誤幀,用于自動檢測波特率;SJA1000以不同的波特率接收CAN幀,當收到CAN幀時,表明當前波特率與總線波特率相同。
波特率設置
CAN總線無時鐘,使用異步串行傳輸;波特率是1秒發送的數據位;
?
CAN幀發送:
發送CAN幀的步驟:1.檢測狀態寄存器,等待發送緩沖區可用;
2.填充報文到發送緩沖區;
3.啟動發送。
?
SJA1000具有一個12字節的緩沖區,要發送的報文可以通過寄存器16-28寫入,也可通過寄存器96-108寫入或讀出
?
?
?
設置發送模式
char SetSJASendCmd(unsigned char cmd) {
unsigned char ret;
switch (cmd) {
default:
case 0:
ret = SetBitMask(REG_CAN_CMR, TR_BIT); //正常發送
break;
case 1:
ret = SetBitMask(REG_CAN_CMR, TR_BIT|AT_BIT); //單次發送
break;
case 2:
ret = SetBitMask(REG_CAN_CMR, TR_BIT|SRR_BIT);//自收自發
break;
case 0xff:
ret = SetBitMask(REG_CAN_CMR, AT_BIT);//終止發送
break;
}
return ret;
}
?發送函數
unsigned char SJA_CAN_Filter[8] = { // 定義驗收濾波器的參數,接收所有幀
0x00, 0x00, 0x00, 0x00,
// ACR0~ACR3
0xff, 0xff, 0xff, 0xff
// AMR0~AMR3
};
unsigned char STD_SEND_BUFFER[11] = { // CAN 發送報文緩沖區
0x08, // 幀信息,標準數據幀,數據長度 = 8
0xEA, 0x60, // 幀ID = 0x753
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa // 幀數據
};
void main(void) // 主函數,程序入口
{
timerInit();// 初始化
D1 = 0;
SJA1000_RST = 1; // 硬件復位SJA1000
timerDelay(50); // 延時500ms
SJA1000_RST = 0;
SJA1000_Init(0x00, 0x14, SJA_CAN_Filter); // 初始化SJA1000,設置波特率為1Mbps
// 無限循環,main()函數不允許返回
for(;;) {
SJASendData(STD_SEND_BUFFER, 0x0);
timerDelay(100); // 延時1000ms
}
}
為什么幀ID是0x753,這與CAN幀在緩沖區的存儲格式有關。
?
?
終端電阻非常重要,當波特率較高而且沒加終端電阻時,信號過沖非常嚴重。
?
SJA1000有64個字節的接收緩沖區(FIFO),這可以降低對MCU的要求。MCU可以通過查詢或中斷的方式確定SJA1000接收到報文后讀取報文。
-END-
|?整理文章為傳播相關技術,版權歸原作者所有?|
|?如有侵權,請聯系刪除?|
【1】看了這20種運放典型電路,你還敢說你用不到嗎?
【2】直觀的讓人發毛!巧識濾波、穩壓、比較、運放電路
【3】干貨!運放的電壓追隨電路分析
【4】怎樣理解運放的軌至軌特性?這篇文章給你打開大門!
【5】運放的電壓追隨電路
免責聲明:本文內容由21ic獲得授權后發布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!