轉自http://www.cnblogs.com/-song/archive/2012/05/10/3331873.html
mcp2515寄存器一覽
幾個寄存器名稱及地址TXBnCTRL——發送緩沖器n 控制寄存器(地址:30h, 40h, 50h)TXBnSIDH——發送緩沖器n 標準標識符高位(地址:31h, 41h, 51h)TXBnSIDL——發送緩沖器n 標準標識符低位(地址:32h, 42h, 52h)TXBnEID8——發送緩沖器n 擴展標識符高位(地址:33h, 43h, 53h)TXBnEID0——發送緩沖器n 擴展標識符低位(地址:34h, 44h, 54h)TXBnDLC——發送緩沖器n 數據長度碼(地址:35h, 45h, 55h)TXBnDm——發送緩沖器n 數據字節m(地址:36h - 3Dh, 46h - 4Dh, 56h - 5Dh)RXBnCTRL——接收緩沖器n 控制寄存器(地址:60h,70h)RXBnSIDH——接收緩沖器n 標準標識符高位(地址:61h, 71h)RXBnSIDL——接收緩沖器n 標準標識符低位(地址:62h, 72h)RXBnEID8——接收緩沖器n 擴展標識符高位(地址:63h, 73h)RXBnEID0——接收緩沖器n 擴展標識符低位(地址:64h, 74h)RXBnDLC——接收緩沖器n 數據長度碼(地址:65h, 75h)RXBnDM——接收緩沖器n 數據字段字節M(地址:66h - 6Dh, 76h - 7Dh)spi接口操作mcp2515使用的命令
can物理信號can信號使用差分電壓傳送,兩條信號線被稱為CAN_H和CAN_L。靜態時均是2.5v左右,此時狀態表示為邏輯“1”,也可以叫做隱性。用CAN_H比CAN_L高表示邏輯“0”,稱為顯性,此時通常電壓值為CAN_H=3.5V和CAN_L=1.5V。
1.標準幀結構--refer to mcp2515說明書
CAN 標準數據幀如圖所示。與其他所有幀一樣,幀以起始幀(SOF)位開始, SOF 為顯性狀態,允許所有節點的硬同步。SOF之后是仲裁字段,由12個位組成,分別為11個標識位和一個遠程發送請求(Remote Transmission Request,RTR)位。RTR 位用于區分報文是數據幀(RTR 位為顯性狀態)還是遠程幀(RTR 位為隱性狀態)。仲裁字段之后是控制字段,由6 個位組成。控制字段的第一位為標識擴展(Identifier Extension,IDE)位,該位應是顯性狀態來指定標準幀。標識擴展位的下一位為零保留位(RB0),CAN 協議將其定義為顯性位。控制字段的其余4 位為數據長度碼(Data Length Code,DLC),用來指定報文中包含的數據字節數(0 到8 字節)。控制字段之后為數據字段,包含要發送的任何數據字節。數據字段長度由上述DLC 定義(0 到8 字節)。數據字段之后為循環冗余校驗(CRC)字段,用來檢測報文傳輸錯誤。CRC 字段包含一個15 位的CRC 序列,之后是隱性的CRC 定界位。最后一個字段是確認字段(ACK),由2 個位組成。在確認時隙(ACK Slot)位執行期間,發送節點發出一個隱性位。任何收到無錯誤幀的節點會發回一個顯性位(無論該節點是否配置為接受該報文與否)來確認幀收到無誤。確認字段以隱性確認定界符結束,該定界符可能不允許被改寫為顯性位。標準幀和mcp2515的寄存器對應關系一覽:詳見mcp2515手冊對于接受操作:
對于發送操作:
2.擴展幀結構
在擴展CAN 數據幀中(如圖2-2 所示),緊隨SOF 位的是32 位的仲裁字段。仲裁字段的前11 位為29 位標識符的最高有效位(Most Significant bit,MSb)(基本lD) 。緊隨這11 位的是替代遠程請求(Substitute Remote Request, SRR)位,定義為隱性狀態。SRR位之后是lDE 位,該位為隱性狀態時表示這是擴展的CAN 幀。應該注意的是,如果發送完擴展幀標識符的前11 位后,總線仲裁無果,而此時其中一個等待仲裁的節點發出標準CAN 數據幀(11 位標識符),那么,由于節點發出了顯性lDE 位而使標準CAN 幀贏得總線仲裁。另外,擴展CAN 幀的SRR 位應為隱性,以允許正在發送標準CAN 遠程幀的節點發出顯性RTR 位。SRR和lDE位之后是標識符的其余18位(擴展lD)及一個遠程發送請求位。為使標準幀和擴展幀都能在共享網絡上發送,應將29位擴展報文標識符拆成高11 位和低18 位兩部分。拆分后可確保lDE 位在標準數據幀和擴展數據幀中的位置保持一致。仲裁字段之后是6 位控制字段。控制字段前兩位為保留位,必須定義為顯性位。其余4 位為DLC,用來指定報文中包含的數據字節數。擴展數據幀的其他部分(數據字段、CRC 字段、確認字段、幀結尾和間斷)與標準數據幀的結構相同(見第2.1 節“標準數據幀”)。擴展幀和mcp2515的寄存器對應關系一覽:詳見mcp2515手冊對于接受操作:接收時,若得到IDE位為1,表示接收到的是擴展幀。
對于發送操作:發送時,置IDE位為1,表示發送的是擴展幀。
can的無地址編碼與485的有地址編碼比如485的modbus幀發出:01 03 00 00 00 03 05 CB //01站地址,03功能號,00 00 起始地址,00 03要讀的數據個數接收:01 03 06 00 00 00 01 00 02 F1 74 //01站地址,03功能號,06返回的字節數,00 00 00 01 00 02 對應6個字節3個數(03讀取保持寄存器,保持寄存器為可讀可寫,http://blog.csdn.net/songQQnew/article/details/6938039)主機發出的幀中的第一個字節是目的地址即01。所有的設備都可以收到這個幀,只有地址是01的設備才需要響應這個幀,響應幀的第一個字節規定必須是本機地址即01.而can的幀/* * Controller Area Network Identifier structure * * bit 0-28 : CAN identifier (11/29 bit) * bit 29 : error frame flag (0 = data frame, 1 = error frame) * bit 30 : remote transmission request flag (1 = rtr frame) * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) */ typedef __u32 canid_t; /** * struct can_frame - basic CAN frame structure * @can_id: the CAN ID of the frame and CAN_*_FLAG flags, see above. * @can_dlc: the data length field of the CAN frame * @data: the CAN frame payload. */ struct can_frame { canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ __u8 can_dlc; /* data length code: 0 .. 8 */ __u8 data[8] __attribute__((aligned(8))); }; 主機向總線發出如下幀,幀的內容是hello,并設置標示符為123,這樣總線上123號站應當對此幀有反應。由于都可以作為主機而主動向總線發數據,所以就沒必要向modbus那樣非得要主機發命令讓從機干嘛從機才可以干嘛。比如1號站有可用數據了,那么他直接將數據發送can總線,希望得到哪個站的處理就設置標示符為哪個站比如為123。在硬件層和驅動層,can總線上的所有非123號站也會收到站1發來的數據。但只有123號站應該對其處理--在應用層可以設置是只將驅動接收到的指定can標示符的can_frame上報給應用層,如下 struct can_filter rfilter;//過濾 rfilter.can_id = 0x123;//選擇監聽can_frame中標示符是0x123的can幀,不過濾則監聽所有。 rfilter.can_mask = CAN_SFF_MASK; setsockopt(m_can, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)); 站123處理完了之后,根據需要要么回復一下(要不不回復),回復的時候也會使用相同的幀結構,回復的時候身份就變成了主機。看來can總線上流動的數據都是某個站主動發出的。而modbus總線上僅可以有一個主機,通信必須采用一問一答的形式,由于主機問的問題有好幾種,所以從機針對每個問題回復的modbus幀也些差別。不像can的幀,僅有一種(僅討論標注幀),每幀最大限制為8個字節。DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[1]=24//TXBnSIDH--? DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[2]=60//TXBnSIDL--? DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[3]=1//TXBnEID8--? DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[4]=23//TXBnEID0--? DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[5]=5//TXBnDLC DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[6]=68//TXBnD0 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[7]=65//TXBnD1 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[8]=6c//TXBnD2 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[9]=6c//TXBnD3 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[10]=6f//TXBnD4 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[11]=0//TXBnD5 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[12]=0//TXBnD6 DBG(drivers/net/can/mcp251x.c, mcp251x_hw_tx(), 482): buf[13]=0//TXBnD7 can的多主與485的單主Can總線本身就是為多主系統設計的,可以在一根總線上有多個主站。而485本身只能是單主的,只能通過其他的辦法(如令牌)來變成一個多主系統。這是由硬件特點決定的。485總線上如果有兩個節點同時都發送了信號,總線狀態無法不確定的,即發送的報文可能已經被破壞了,為了解決這個問題,在某一時刻只能有一個站點主動發起通訊,其他站點都可看成從站。而Can的對比的主要優點在于可以實現非破壞仲裁,為此在硬件上進行了特殊設計,從總線可以看成是一個線與的結構,如果兩個或以上節點發送信號電平不一致,總線電平顯示為顯性,這意味著至少有一個站點的報文沒有被破壞。為了仲裁節點在發送信號的同時還在監測總線,如果發送和檢測不一致則認為本節點發送報文已經被破壞。節點會自動退出發送狀態等待發送結束以后開始下一次發送。而報文始終正確的站點最終取得總線控制權。有一個問題哦,can是多主的總線,spi是單主的總線,那么6410的spi和mcp2515連起來之后怎么就變成了多主了呢?以圖說明
每個6410下只掛一個mcp2515。6410的cs引腳配置為輸出,用于選中從機。當6410.1有數據要發送時,6410.1作為spi主機向mcp2515.1發送數據,然后mcp2515.1作為主機,向總線發送數據。當mcp2515.2從can總線上接收到數據時,它會向6410.2產生一個中斷,此時6410.2會作為spi主機從mcp2515.2中主動讀到數據。看來是多虧了那根中斷線,使得6410都可以作為spi主機主動從與之相連的mcp2515讀數據。can的錯誤檢測
|
新聞熱點
疑難解答