程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 在.Net Micro Framework中訪問硬件 - part1

在.Net Micro Framework中訪問硬件 - part1

編輯:關於.NET

摘要:本文介紹了.Net Micro Framework中對硬件的簡單而獨特的訪問方式。涉及GPIO,RS232串口等。通過簡明的例程說明了如何創建IO口,如何發送接受數據的過程。

1.GPIO

通常來說,一塊MCU要與周邊環境進行交流,使用GPIO(General Purpose Input/Output)無疑是最常用的方式。一個GPIO口在被初始化之後可以被用於輸入或輸出的通道。一個GPIO口可以由兩種狀態來描述 - 低(約為0伏)和高(通常認為是3.3伏的正向電壓)。

在.Net Micro Framework中,GPIO的狀態被定義為布爾型,false->低, true->高。

Tips這裡說的低(0伏)和高(3.3伏)是指你在設置GPIO的時候,實際加在GPIO口的電壓。而在考慮輸入的時候一般1v以下會被認為是邏輯低,1.7~5.5伏通常認為是邏輯高。超過5.5的電壓是如果不加保護電路通常是會損壞你的硬件的。

1.1輸出

在Microsoft.SPOT.Hardware命名空間下,你可以找到OutputPort類,它繼承自Microsoft.SPOT.Hardware.Port---一個用於描述GPIO的基礎類。

定義OutputPort一般都會初始化一個默認值(true代表高,false表示低)。

OutputPort outputPort = new OutputPort(MyPins.StatusLED, true);

/*第一個參數是枚舉類型Microsoft.SPOT.Hardware.Cpu.Pin,不過為了使你的代碼更靈活,非常建議你使用自己封裝的類來綁定CPU的管腳名稱和GPIO口的編號。*/

接著,outputPort的Write和Read方法就可以使用了,Write方法控制了管腳的電平狀態,Read方法用於返回當前狀態,也即上一次設置的狀態。

下面的例子用於讓自定義pin的led按1hz的頻率閃爍(實際上是亮暗各0.5s左右)。

OutputPort outputPort = new OutputPort(MyPins.StatusLED, true);
while (true)
{
Thread.Sleep(500);
outputPort.Write(!outputPort.Read()); //toggle port
}

1.2 輸入

和OutputPort相類似,Microsoft.SPOT.Hardware.InputPort扮演了輸入的功能。它同樣繼承自Microsoft.SPOT.Hardware.Port。下面的例子演示了如何在一個無限循環中輪詢inputPort的狀態。

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
…
InputPort inputPort = new InputPort(Cpu.Pin.GPIO_Pin2,//管腳號
false,//是否過濾毛刺信號
Port.ResistorMode.PullDown);//電阻模式,這裡設為下拉即合上開關(按下按鈕)時GPIO狀態為高
while (true)
{
bool state = inputPort.Read(); //polling of port state
Debug.Print("GPIO input port at pin " + inputPort.Id +
" is " + (state ? "high" : "low"));
//留一點時間讓設備或者模擬器能夠對VS反應
Thread.Sleep(10);
}

另外,還有一個可以在運行時動態改變狀態地邏輯端口Tristate Port。聽名字似乎是三態端口,不過事實上目前它只能在高和低之間切換。

1.3 中斷

如果你僅僅只是想等待一個按鍵的按下,那麼使用前面那種使用無限循環的方式來讀取輸入口的狀態的辦法,無疑顯得太耗了點,我們不並希望Cpu總是處於這麼忙碌的狀態,比如某些狀況下(例如電池)。我們只是希望某些外部消息和請求以中斷的形式告訴Cpu,在.Net MF中我們使用InterruptPort類來實現相應地功能,中斷可以理解為硬件之間的事件。如果MCU除了等待某個GPIO口的事件而沒有其他事情做的話,該處理器就可以放心的進入省電模式了。當一個信號的改變發生在相應的輸入管腳的時候,MCU會“醒”來,然後相應的中斷服務程序(ISR)會被執行

你可以把中斷端口設置為上升沿觸發或者下降沿觸發。或者兩者都觸發,也可以是高低電平觸發。如下程序演示了如何在一個脈沖的上升沿和下降沿都引起中斷,中斷服務程序的入口點由相應的委托OnInterrupt來指派。

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
…
InterruptPort port =
new InterruptPort(Cpu.Pin.GPIO_Pin3,
false, //不過濾毛刺
Port.ResistorMode.PullDown,
Port.InterruptMode.InterruptEdgeBoth);//中斷模式設為雙邊沿觸發
port.OnInterrupt += new GPIOInterruptEventHandler(port_OnInterrupt);//指定中斷服務程序
Thread.Sleep(Timeout.Infinite);
…
private static void port_OnInterrupt(Cpu.Pin port,
bool state,
TimeSpan time)
{
Debug.Print("Pin=" + port + " State=" + state + " Time=" + time);
}

下面的例子演示了電平觸發的過程:

…
interruptPort =
new InterruptPort(Cpu.Pin.GPIO_Pin2,false, Port.ResistorMode.PullUp,
Port.InterruptMode.InterruptEdgeLevelLow);//中斷模式設置為低電平觸發
interruptPort.OnInterrupt +=
new GPIOInterruptEventHandler(port_OnInterrupt);
Thread.Sleep(Timeout.Infinite);//除了等待中斷以外,該線程休眠
…
private static void port_OnInterrupt(Cpu.Pin port,
bool state,
TimeSpan time)
{
Debug.Print("Pin=" + port + " State=" + state + " Time=" + time);
//清除當前中斷端口的狀態以便下一次指定電平到來時仍能觸發中斷
interruptPort.ClearInterrupt();
}

2 串口(RS-232)

盡管如今USB盛行,串口設備仍然有著他們自己的生存空間,比如一些測量儀器,GPS接收器等等。

和.NET Framework以及.NET Compact Framework中的類型相應的,.Net Micro Framework中也有SerialPort類,只不過它被放在了Microsoft.SPOT.Hardware程序集中而不是它的前輩們的System.IO.Ports下。使用前需要先對SerialPort.Configuration進行配置。

下面的例子演示了如何通過串口發送數據:

using System;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
…
SerialPort.Configuration config =
new SerialPort.Configuration(SerialPort.Serial.COM1,
SerialPort.BaudRate.Baud9600,
false);//不做任何流控制
SerialPort serialPort = new SerialPort(config);
byte[] outBuffer = Encoding.UTF8.GetBytes("Hello World!"r"n");
serialPort.Write(outBuffer, 0, outBuffer.Length);//MF中無需先Open再寫入
serialPort.Dispose();
//keeps the emulator running to see results
Thread.Sleep(Timeout.Infinite);

讀數據的方法也和PC上差不多:

SerialPort.Configuration config =
new SerialPort.Configuration(SerialPort.Serial.COM1,
SerialPort.BaudRate.Baud115200,
false);
SerialPort serialPort = new SerialPort(config);
byte[] inBuffer = new byte[32];
while (true)
{
int count = serialPort.Read(inBuffer, 0, inBuffer.Length, 0);//讀的時候需要指定buffer
if (count > 0) //minimum one byte read
{
char[] chars = Encoding.UTF8.GetChars(inBuffer);
string str = new string(chars, 0, count);
Debug.Print(str);
}
}

3.管腳的使用和保留

保留CPU的管腳,你可以顯示的控制管腳的用途,避免管腳復用造成的沖突。通過注冊你的Hardware Provider(Microsoft.SPOT.HardwareProvider),你可以約定你的管腳使用情況。

串行通信不僅僅包括RS232的串口,還有SPI和I2C總線等方式。HardwareProviderHardwareProvider也不只為RS232提供硬件信息服務。當你自定義HWP的時候,你需要從HWP繼承過來,並重寫GetI2CPins, GetSerialPins, and GetSpiPins三個虛方法中的至少一個,它們在缺省狀況下均返回Cpu.Pin.GPIO_NONE.,之後需要調用靜態方法Register()來完成注冊。

下面是一個自定義的HardwareProvider用以設定RS232串口的保留管腳。它實現了GetSerialPins方法,返回的是CPU的輸入輸出管腳號。

internal sealed class MyHardwareProvider : HardwareProvider
{
public override void GetSerialPins(SerialPort.Serial com,
out Cpu.Pin rxPin,
out Cpu.Pin txPin)
{ switch (com)
{
case SerialPort.Serial.COM1:
rxPin = Cpu.Pin.GPIO_Pin0;
txPin = Cpu.Pin.GPIO_Pin1;
break;
case SerialPort.Serial.COM2:
rxPin = Cpu.Pin.GPIO_Pin2;
txPin = Cpu.Pin.GPIO_Pin3;
break;
default:
rxPin = Cpu.Pin.GPIO_NONE;
txPin = Cpu.Pin.GPIO_NONE;
break;
}
}
}
  
//注冊HWP
HardwareProvider.Register(new MyHardwareProvider());
SerialPort.Configuration config =
new SerialPort.Configuration(SerialPort.Serial.COM1,
SerialPort.BaudRate.Baud9600,
false);
//如果此時serialPortB從 config創建時,serialPortA尚未釋放的話,會導致運行時錯誤。
SerialPort serialPortA = new SerialPort(config);
//SerialPort serialPortB = new SerialPort(config); //出錯,因為這時COM1被A占用
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved