今天是2007年最後一天,還有幾個小時就迎來充滿期待的2008年了。元旦放假至今不到48個小時的時間裡,我至少有30多個小時坐在電腦前研究MF相關技術,在缺少必要的硬體的情況下,利用現有的資料,擴充了現有的模拟器功能。也希望像我這樣的窮人們,借助模拟器,能體驗一下以前隻有擁有硬體才能調試的功能。
以前為了介紹MF圖形方面的功能,我做了一個“北京2008奧運場館查詢”程式,現在看來那個程式,已經不足以展示MF整體功能的強大。既然Windows 2000 /XP/vista,Windows CE(Windows Mobile)程式都有Windows桌面和開始菜單,那麼我們的.Net Micro Framework也應該有一個。豈能光說不練,下面就是我們MF Windows的桌面和開始菜單。
看了這個截圖,也許有的網友會認為,這有什麼難,這不是從windows mobile系統上做了一個截圖嘛。實話實說,這樣認為還真是想簡單了,除了windows圖示和小喇叭外,其它部分全部用代碼實作,光字型就用了兩種不同大小的字庫,此外時鐘也不僅僅做個樣子,也是能正常重新整理顯示的。開始菜單我們也有,不僅能選擇,還能執行對應的功能,不要急,下面我們一一說起。
在上幾篇blog上我說了,我做的模拟器又擴充了兩個鍵(菜單鍵和傳回鍵),别說,這個程式在微軟的模拟器上運作起來還真有問題,因為它不支援菜單鍵,無法彈出菜單來。
菜單上項目也不僅僅是擺設,和模拟器新增的功能結合在一起,做了一個功能測試大荟萃。讓我們先看看GPIO測試的功能在“windows桌面”是怎樣的?
菜單上選中“GPIO測試”項,按一下鍵盤上的回車或者單擊模拟器上的“OK”鍵,就進入上圖界面。單擊模拟右下角的“>>>”項,展開模拟器上的GPIO測試面闆。
單擊模拟上的I輸入開關,桌面上顯示的輸入資訊也同步發生了變化,Q輸出是有使用者程式控制的,燈會一一亮起或關滅,桌面上的顯示也和模拟器像對應(插一句,千萬不要以為上面模拟器和模拟LCD中的程式為同一個,兩者彼此獨立,使用者程式通過正常的指令和模拟器互動(當然同樣的代碼對實際硬體也一樣))。
下面我們再看看“AD測試”功能。
通過開始菜單,我們進入“AD測試”子產品,相應的,我們單擊“<<<”旁邊的“GPIO”字元,彈出選擇菜單,我們單擊“AD”,模拟器呈現AD模拟資料操作面闆。
移動滑塊,我們發現桌面中的資料同步發生了改變,不好意思,模拟出部分被彈出菜單給擋住了,我們再來一張截圖。
QW0是由使用者程式控制的,看的出來,模拟器忠實的擷取了該資料并顯示了出來。說到這裡我還得多說幾句,其實模拟器的部分程式更像運作在實際硬體系統中的IO驅動程式,spi讀寫指令操作的是位元組數組,是以上傳的資料是否浮點型、是否整形等等,全都需要約定,這也決定了不同的廠家對同樣的實體信号進行采集,傳到MF系統中的資料有可能不同,不過通過特定的換算,最終的結果一定是差不多的。
下面說一下I2C總線,I2C我的了解和序列槽通信、CAN口通信差不多,都是兩個相對獨立的裝置進行資料互動,I2C和CAN通信一樣,需要設定裝置位址,此外還需設定一下時鐘主頻。下圖是測試程式界面。
前三個資料是使用者程式進行修改的,由于有時間差,二者資料重新整理時刻不同,是以不一緻,後五個資料是模拟輸入的,可以看出桌面上的顯示已經可以同步更新了。用這種方式模拟I2C,我也覺得有些不妥,以後有更好的方案我再修改。
細心的使用者一定會發現MF“Windows 桌面”右上角的時間在不斷的變化,第一幅圖是2007年12月31日21:39:23,最後一幅圖的時間是22:27:33,也就是說,寫這篇文章大概花了我50分鐘,這是我在word寫這篇文章的用時,接着再花一些時間寫到我blog上,我想所有的一切完畢後,我想大概就可以聆聽2008年的第一聲鐘聲了。
祝大家新年快樂!!!
附:部分核心代碼
public override void OnRender(DrawingContext dc)
{
//繪制背景
dc.DrawRectangle(new SolidColorBrush(ColorUtility.ColorFromRGB(41,113,189)),null , 0, 0, Width, Height);
//菜單條
LinearGradientBrush lgb = new LinearGradientBrush(ColorUtility.ColorFromRGB(51,160,241), ColorUtility.ColorFromRGB(16,75,161), 0, 0, Width, 0);
dc.DrawRectangle(lgb, null, 0, 0, Width, 26);
//開始菜單
dc.DrawImage(Resources.GetBitmap(Resources.BitmapResources.Win), 0, 0);
//分割線
dc.DrawLine(new Pen(Color.White), 26, 0, 26, 25);
//顯示“開始”
dc.DrawText("開始", YFFont, Color.White, 29, 7);
//顯示小喇叭
dc.DrawImage(Resources.GetBitmap(Resources.BitmapResources.Sound), 320 - 75, 6);
//狀态區
dc.DrawRectangle(new SolidColorBrush(ColorUtility.ColorFromRGB(189, 235, 255)), new Pen(Color.Black), 0, Height-26, Width, 26);
//辨別
dc.DrawText("葉帆工作室榮譽出品", YFFont, Colors.Gray, 200, 220);
switch (txtState.TextContent)
{
case "GPIO測試":
string strPace = " ";
dc.DrawText("輸入: I0 I1 I2 I3 I4 I5 I6 I7", YFFont, Colors.Black , 40, 50);
dc.DrawText((input[0].Read() ? "1" : "0") + strPace + (input[1].Read() ? "1" : "0") + strPace + (input[2].Read() ? "1" : "0") + strPace + (input[3].Read() ? "1" : "0") + strPace + (input[4].Read() ? "1" : "0") + strPace + (input[5].Read() ? "1" : "0") + strPace + (input[6].Read() ? "1" : "0") + strPace + (input[7].Read() ? "1" : "0"), YFFont, ColorUtility.ColorFromRGB(255, 255, 0), 78, 75);
dc.DrawText("輸出: Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7", YFFont, Colors.Black, 40, 100);
dc.DrawText((output[0].Read() ? "1" : "0") + strPace + (output[1].Read() ? "1" : "0") + strPace + (output[2].Read() ? "1" : "0") + strPace + (output[3].Read() ? "1" : "0") + strPace + (output[4].Read() ? "1" : "0") + strPace + (output[5].Read() ? "1" : "0") + strPace + (output[6].Read() ? "1" : "0") + strPace + (output[7].Read() ? "1" : "0"), YFFont, ColorUtility.ColorFromRGB(255, 255, 0), 78, 125);
break;
case "AD測試":
dc.DrawText("AD: AW0=" + ReadWriteAD((Int16)QAW).ToString() + " QW0=" + QAW.ToString(), YFFont, Colors.White, 60, 100);
case "I2C測試":
//I2C讀寫
byte[] bytRData = new byte[8];
byte[] bytWData = new byte[3];
bytWData[0] = (byte)IntI2CNum;
bytWData[1] = (byte)(IntI2CNum * 2);
bytWData[2] = (byte)(IntI2CNum * 3);
I2CDevice.I2CTransaction[] i2c = new I2CDevice.I2CTransaction[2];
i2c[0] = I2CBus.CreateReadTransaction(bytRData);
i2c[1] = I2CBus.CreateWriteTransaction(bytWData);
I2CBus.Execute(i2c, 100); //執行
string strPace1 = " ";
dc.DrawText("I2C(位元組0-7):", YFFont, Colors.Black, 50, 80);
string strInfo = bytRData[0].ToString() + strPace1 + bytRData[1].ToString() + strPace1 + bytRData[2].ToString() + strPace1 + bytRData[3].ToString() + strPace1 + bytRData[4].ToString() + strPace1 + bytRData[5].ToString() + strPace1 + bytRData[6].ToString() + strPace1 + bytRData[7].ToString();
dc.DrawText(strInfo, YFFont, ColorUtility.ColorFromRGB(255, 255, 0), 50, 105);
default:
//.Net Micro Framework
dc.DrawRectangle(new SolidColorBrush(Color.White), new Pen(Color.White), 55, 90, Width - 110, 50);
dc.DrawText(".Net Micro Framework", Resources.GetFont(Resources.FontResources.MF), Colors.Black, 60, 105);
}
//菜單顯示
if (bShowMenu)
menu.DrawMenu(dc);
}
}
//按鍵資訊
protected override void OnButtonDown(ButtonEventArgs e)
switch (e.Button)
//按下确定鍵
case Button.Select:
if (bShowMenu)
{
txtState.TextContent = menu.Text;
bShowMenu = false;
this.UpdateLayout();
}
//按下左鍵
case Button.Left:
//按下右鍵
case Button.Right:
//按向上
case Button.Up:
menu.SelectIndex--;
//按向下
case Button.Down:
{
menu.SelectIndex++;
//按下菜單
case Button.Menu:
bShowMenu = !bShowMenu;
if (bShowMenu) menu.SelectIndex = 0;
this.UpdateLayout();
//按下傳回鍵
case Button.Back:
txtState.TextContent = "就緒";
}
------------------------------------
附記:本來打算這篇文章作為2007年底最後一篇文章,沒有想到從22點半到零點,竟然無法上傳成功,隻好作為2008年第一篇文章了,這也不錯。