CAN 是Controller Area Network 的縮寫,ISO國際標准化的串行通信協議。最早應用在汽車上,在歐洲是汽車網絡的標准協議,目前已經廣泛應用在工業自動化、智能家居、船舶、紡織和醫療設備等領域(詳情請參見百度百科《CAN總線協議》)。
由於CAN總線接口.NET Micro Framework官方庫並不支持,所以我在串口類庫的基礎上,根據CAN總線的特點,設計出一套CAN總線通信庫。
CAN類庫的聲明如下:
public class CAN { public CAN(string canName, CanBaudRate baudRate); public CAN(string canName, CanBaudRate baudRate, CanConfig config); public int DatasToRead { get; } public int DatasToWrite { get; } public event CanEventHandler DataReceived; public event CanEventHandler ErrorReceived; public int Close(); public int DiscardInBuffer(); public int DiscardOutBuffer(); public int Flush(); public int IOControl(CanIOControl code, int parameter); public int Open(); public int Read(CanData data); public int SetFilter(int index, CanFilter filter); public int Write(CanData data); }
同時支持CAN2.0A和CAN2.0B協議,相對比較有特色的,一是CanData,二是過濾器設置。
一條CanData包含如下信息:
public class CanData { public CanData(); public CanData(uint id, bool IsEXID); public CanData(uint id, bool IsEXID, byte[] data); public int Count { get; } public byte[] Data { get; } public int Filter { get; } public uint ID { get; } public bool IsEXID { get; } public bool IsRemote { get; } }
和串口及網口通信不同,CAN一幀數據,最多能發8個字節的數據,ID可以是11位的標准ID也可以是29位的擴展ID,幀數據也可以定義為遠程幀(不含數據,僅含ID等信息)或標准幀。STM32F207(或STM32F103),發送緩沖區可緩存3個數據幀r,接收緩沖區是雙fifo,一個fifo可以接收3個數據包。但是僅僅這些還不夠,本類庫仿照串口通信,內置了可以任意定義發送和接收緩沖區大小的功能(其實對串口通信來說,發送和接收buffer卻是內部定死的,用戶不能自定義)。這樣用戶在大量發送和接收數據的時候,就無后顧之憂了。
過濾器(Filter)應該是CAN的精華所在了,要想理解和設置好,卻不是易事。所以為了便於用戶使用,對過濾器類重載了很多定義函數,過濾器類庫聲明如下:
public class CanFilter { public CanFilter(bool enable); public CanFilter(uint id, uint mask); public CanFilter(uint id0, uint id1, bool IsRemote); public CanFilter(uint id, uint mask, bool IsRemote, bool IsMaskMode); public CanFilter(ushort id0, ushort mask0, ushort id1, ushort mask1); public CanFilter(bool IsMaskMode, bool IsFifo0, bool IsWidth32, uint data1, uint data2); public CanFilter(ushort id0, ushort id1, ushort id2, ushort id3, bool IsRemote); public CanFilter(ushort id0, ushort mask0, ushort id1, ushort mask1, bool IsRemote, bool IsMaskMode); }
對STM32芯片集成的CAN功能來說,過濾器有兩種過濾模式,一種是ID列表模式,另外一種是ID掩碼模式。而這兩種又根據過濾數據的寬度不同,分為32位和16位。
限於篇幅,關於CAN通信庫具體的內容就不在此展開介紹了,詳情請參見YFSoft.CAN.rar壓縮包里面的文檔說明。
本文借助三個物聯網智能網關進行CAN總線網絡通信,來講解CAN總線的使用情況(順便介紹一下TinyGUI的觸摸屏事件使用)。

示例程序分兩種:一種是主控程序,上面設計了三個開關按鈕,並且可以切換需要控制的CAN設備。另外一種,就是從設備程序了,該程序部署分別部署到兩個設備上,程序的唯一區別就是,所要接收的ID標識號不同,一個是2#,一個是3#(程序界面如上圖所示)。
在說CAN總線通信之前,先介紹一下TinyGUI的觸摸屏事件的使用。
示例代碼如下,用法非常簡單。
Graphics screen = new Graphics();
screen.OnTouch += new TouchEventHandler(screen_OnTouch);
static void screen_OnTouch(int x, int y, int state)
{
//x-x坐標 y – y坐標
//state – 1 按下 0 抬起
}
² 主控CAN通信程序
第一步:創建一個CAN通信類,並綁定接收和錯誤事件
can = new CAN("CAN1", CanBaudRate.bps_100K);
can.ErrorReceived += new CanEventHandler(can_ErrorReceived);
第二步:根據選項不同,發送不同ID標識符和不同的CAN數據
can.Write(new CanData(canID, true, new byte[] { 0, 0 }));
canID 是2或者3,數據的第一個數,0~2 表示對應的3個燈。
² 從設備CAN通信程序
第一步:創建一個CAN通信類,並綁定接收和錯誤事件
can = new CAN("CAN1", CanBaudRate.bps_100K);
can.DataReceived += new CanEventHandler(can_DataReceived);
can.ErrorReceived += new CanEventHandler(can_ErrorReceived);
can.SetFilter(0, new CanFilter(2,0,false));
過濾器設定的ID標識符為2或3.
第二步:數據接收
static void can_DataReceived(int canPort, int parameter)
{
int count = can.DatasToRead;
CanData data = new CanData();
for (int i = 0; i < count; i++)
{
can.Read(data);
int index = data.Data[0];
LameState[index] = !LameState[index];
lamp[index].OnDraw(index, LameState[index]);
}
}
² TinyGUI界面設計
略,詳情請參見示例代碼。
程序部署后,時間運行的視頻如下:
http://v.youku.com/v_show/id_XNDM5NzI1MTg0.html
注意:為了正常運行本實例,物聯網智能網關固件版本需要升級到V1.8.17以上,(如果你當前TinyCLR版本低於V1.7.15以下,TinyBooter也需要同步升級)。
固件下載地址:http://www.sky-walker.com.cn/MFRelease/firmware/MFv42_YF_Wisteria207.rar
---------------------------------
類庫下載:http://www.sky-walker.com.cn/MFRelease/library/V42//YFSoft.CAN.rar
示例下載:http://www.sky-walker.com.cn/MFRelease/Sample/CAN_Test.rar
MF簡介:http://blog.csdn.net/yefanqiu/article/details/5711770


