目前可以成為.NET MF開發闆調試口的信道有,序列槽、USB和網口,一般情況下,一旦具體設定哪個信道,在不更換固件的情況下,是無法動态改變的。
所謂調試口,就是供windows平台上的VS2008/VS2010調試的信道,當然MFDeploy和我編寫的工具YFAccessFlash也是通過這個信道和開發闆實作通信的。不過,這些通信過程,作為運作到開發闆上的應用程式是無從知道的,這些基于開發闆底層的通信,完全由TinyCLR進行全權管理。
有了以上知識,我們很自然地想到,借助這個通信協定,我們是否可以擴充一下,自定義我們所需要的通信指令,這樣借助WireProtocol協定通道,我們就可以傳輸任意長度的資料了。
不過,說起來容易,做起來難,這就像練武之人想打通任督二脈一樣,打通的意義雖然重大,但是實作起來卻環節衆多。考慮到複雜性,是以我這裡不打算詳細介紹所有實作的細節,由點帶面,簡要說一下實作的過程,我們需要修改或建立的檔案(或代碼)如下:
PC 平台:改造MFDeployEngine.dll和Microsoft.SPOT.Debugger.dll檔案,建立UsbStream類。
MF 平台:修改TinyCLR_Debugging.h和Debugger.CPP檔案,添加c_Monitor_Custom指令,此外再實作一個P/Invoke接口,讓運作在開發闆上的使用者程式可以通路該通道。
P/Invoke接口中的UsbStream類的定義(.NET Micro Framework代碼)如下:
public class UsbStream
{
public UsbStream();
public int BytesToRead { get; }
public int BytesToWrite { get; }
public event UsbStreamDataReceivedEventHandler DataReceived;
public void Close();
public void DiscardInBuffer();
public void DiscardOutBuffer();
public bool Open();
public int Read(byte[] buffer, int offset, int count);
public int Write(byte[] buffer, int offset, int count);
}
和序列槽的定義類似,不過不用設定通信參數。
運作在PC機上的UsbStream類的定義(.NET Framework代碼)如下:
public class UsbStream
public UsbStream(YFDeploy deploy);
二者代碼幾乎相同,不過後者構造函數中有參數,并且沒有事件函數。
我們做一個Demo,來示範我們所實作的功能,很簡單的做法,就是PC向開發闆發送資料,開發闆原樣傳回。
PC機上的主要代碼如下:
private void btnSend_Click(object sender, EventArgs e)
{
if (txtOutput.Text.Length <= 0) return;
if (usb == null)
{
usb = new UsbStream(deploy);
if (!usb.Open())
{
txtOutput.BackColor = Color.Red;
usb = null;
return;
}
else
txtOutput.BackColor = Color.White;
trmRead.Enabled = true;
}
byte[] inData = System.Text.ASCIIEncoding.UTF8.GetBytes(txtOutput.Text);
if (usb.Write(inData, 0, inData.Length)>0)
txtOutput.BackColor = Color.White;
}
else
txtOutput.BackColor = Color.Red;
}
private void trmRead_Tick(object sender, EventArgs e)
if (usb != null)
if (usb.BytesToRead > 0)
byte[] bytData = new byte[usb.BytesToRead];
usb.Read(bytData, 0, bytData.Length);
txtInput.Text += new String(System.Text.ASCIIEncoding.UTF8.GetChars(bytData));
}
開發闆上的代碼如下:
public static void Main()
UsbStream usb = new UsbStream();
if (usb.Open())
Debug.Print("open ok");
Graphics.Print("open ok/r/n");
usb.DataReceived += new UsbStreamDataReceivedEventHandler(usb_DataReceived);
while (true)
Thread.Sleep(100);
//usb.Close();
static void usb_DataReceived(object sender, EventArgs e)
UsbStream usb = (UsbStream)sender;
string strInfo = "[" + usb.BytesToRead.ToString()+"]";
if (usb.BytesToRead > 0)
byte[] bytData=new byte[usb.BytesToRead];
usb.Read(bytData,0,bytData.Length);
for (int i = 0; i < bytData.Length; i++)
strInfo += bytData[i].ToString() + " ";
usb.Write(bytData, 0, bytData.Length);
Graphics.Print(new string(System.Text.UTF8Encoding.UTF8.GetChars(bytData)));
Debug.Print(strInfo);
代碼都非常簡單,這裡就不過多介紹了,我們看一下效果圖。

PC機上的程式,類似序列槽調試工具,可以發送和接收資料。
開發闆的LCD屏上顯示從PC接收的資料。
調試序列槽輸出的調試資訊,可以看到開發闆接收的位元組資料。
以上功能的實作還是非常有意義的,特别是我們做一個産品的時候,我們可以很友善的通過PC配置我們産品的參數,并且可以和該産品進行通信。這樣就不需要通過其它的通信口,來完成該功能了。并且難能可貴的是,實作了私有通信,但是并沒有犧牲掉調試口。