.Net Micro Framework研究—串列埠操作
.Net Micro Framework研究—串列埠操作
試驗平臺:Digi MF開發板
Digi提供的示例中包含了串列埠的示例程式,主要程式碼如下:
- public bool EchoByte()
- {
- SerialPort serial;
- bool exceptionRaised = false;
- bool testResult = true;
- string message = " This is an echo test. Enter the character to echo, or ESC to exit. ";
- byte[] encodedMessage = c_encoding.GetBytes(message);
- byte[] buffer = new byte[1];
- try
- {
- serial = new SerialPort(new SerialPort.Configuration(Cpu.Serial.COM1, Cpu.BaudRate.Baud115200, false));
- serial.Write(encodedMessage, 0, message.Length);
- while (buffer[0] != 0x1b)
- {
- serial.Read(buffer, 0, buffer.Length, Timeout.Infinite);
- serial.Write(buffer, 0, buffer.Length);
- }
- serial.Dispose();
- }
- catch
- {
- exceptionRaised = true;
- }
- if (exceptionRaised == true)
- testResult = false;
- return testResult;
- }
部署執行後,你可以用超級終端進行測試,測試圖如下:
(圖MF10280001.JPG)
注意:如果串列埠程式非正常退出,有可能導致開發板無法傳送資料(接收倒是正常),重啟開發板即可。
用測試程式還是體現不出.Net Micro Framework的優勢,我決定用MF實現Modbus Rtu Slave服務端(支援Modbus Rtu 3號命令),並且地址為0的資料存放了GPIO入的資訊,這樣在上位機就很方面的檢測IO訊號了。
用了大約15分鐘,就把我以前用C++開發的Modbus Rtu Slave程式移植到MF平臺上來的,我想如果用單片來開發,雖然也有可能借用以前的程式碼,但很方便的把IO訊號也非常快捷的整合進來,恐怕不容易。
值得一提的是VS2005 的除錯功能非常強大,很容易新增斷點及監控當前變數的值,同時用debug.print()命令也非常好使,這樣除錯程式絕對比除錯單片舒服。
下面貼出我寫的Modbus RtuSlave程式碼
- using System;
- using Microsoft.SPOT;
- using System.Threading;
- using Microsoft.SPOT.Hardware;
- namespace MFModbus
- {
- public class ModbusRtu
- {
- private Thread m_worker;
- private bool m_RunFlag;
- private byte bytRtuDataFlag=0;
- private byte bytRtuDataIdx;
- private byte[] bytRtuData = new byte[8];
- //裝置地址,預設為1
- private byte ModbusAddr = 1;
- //資料區(注意,Modbus讀寫是以字(雙位元組)為單位的)
- private byte[] DataBuff = new byte[128];
- SerialPort serial = null;
- InputPort[] input = new InputPort[5];
- Cpu.Pin[] pin = new Cpu.Pin[5] { (Cpu.Pin)0, (Cpu.Pin)1, (Cpu.Pin)2, (Cpu.Pin)5, (Cpu.Pin)6 };
- public ModbusRtu(byte mModbusAddr)
- {
- ModbusAddr=mModbusAddr;
- for (int i = 0; i < 5; i++)
- {
- input[i] = new InputPort(pin[i], false, Port.ResistorMode.PullUp);
- }
- }
- ~ModbusRtu()
- {
- Stop();
- }
- //CRC16校驗
- private UInt16 GetCheckCode(byte[] buf, int nEnd)
- {
- UInt16 crc = (UInt16)0xffff;
- int i, j;
- for (i = 0; i < nEnd; i++)
- {
- crc ^= (UInt16)buf[i];
- for (j = 0; j < 8; j++)
- {
- if ((crc & 1) != 0)
- {
- crc >>= 1;
- crc ^= 0xA001;
- }
- else
- crc >>= 1;
- }
- }
- return crc;
- }
- //啟動Modbus服務
- public void Run()
- {
- try
- {
- //僅有波特率選項,竟然沒有奇偶校驗控制
- serial = new SerialPort(new SerialPort.Configuration(Serial.COM1, BaudRate.Baud9600, false));
- Debug.Print("Open Serial OK");
- m_worker = new Thread(new ThreadStart(this.ModbusThreadProc));
- m_RunFlag = true;
- m_worker.Start();
- }
- catch
- {
- Debug.Print("Serial Error");
- }
- }
- //停止Modbus服務
- public void Stop()
- {
- m_RunFlag = false;
- if (serial != null)
- serial.Dispose();
- }
- //Modbus Slave服務
- private void ModbusThreadProc()
- {
- Debug.Print("Start Modbus Slave");
- byte[] bytData=new byte[1];
- while (m_RunFlag)
- {
- serial.Read(bytData, 0, bytData.Length, Timeout.Infinite);
- RtuSlave(bytData[0]);
- }
- }
- //串列埠資料處理
- private void RtuSlave(byte bytData)
- {
- //Debug.Print(bytRtuDataIdx.ToString() + " - " + bytData.ToString());
- if (bytRtuDataFlag == 0)
- {
- //如果資料為首地址
- if (bytData == ModbusAddr)
- {
- bytRtuDataFlag = 1;
- bytRtuDataIdx = 0;
- bytRtuData[bytRtuDataIdx++] = bytData;
- }
- }
- else
- {
- bytRtuData[bytRtuDataIdx++] = bytData;
- if (bytRtuDataIdx >= 8)
- {
- //資訊處理
- UInt16 intCRC16 = GetCheckCode(bytRtuData, 8 - 2);
- //Debug.Print("CRC:" + bytRtuData[8 - 2].ToString() + " " + ((byte)(intCRC16 & 0xFF)).ToString() +"|" + bytRtuData[8 - 1].ToString() + " " + ((byte)((intCRC16 >> 8) & 0xff)).ToString());
- //CRC16校驗檢驗
- if (bytRtuData[8 - 2] == (intCRC16 & 0xFF) && bytRtuData[8 - 1] == ((intCRC16 >> 8) & 0xff))
- {
- byte[] bytSendData = new byte[255];
- byte bytErrorFlag = 0;
- byte bytErrorNo = 1;
- //Debug.Print("CRC OK");
- //讀資料
- if (bytRtuData[1] == 3)
- {
- UInt16 lngDataAddr = bytRtuData[2];
- lngDataAddr = (UInt16)((lngDataAddr << 8) + bytRtuData[3]); //地址
- UInt16 lngDataNum = bytRtuData[4];
- lngDataNum = (UInt16)((lngDataNum << 8) + bytRtuData[5]); //數量
- if (lngDataAddr * 2 + lngDataNum * 2 > 1024 || lngDataNum > 120)
- {
- bytErrorNo = 2;
- bytErrorFlag = 0;
- }
- else
- {
- bytSendData[0] = bytRtuData[0];
- bytSendData[1] = bytRtuData[1];
- bytSendData[2] = (byte)(lngDataNum * 2);
- //讀GPIO訊號
- DataBuff[0] = 0;
- DataBuff[1] = (byte)((input[0].Read() ? 1 : 0) | (input[1].Read() ? 2 : 0) | (input[2].Read() ? 4 : 0) | (input[3].Read() ? 8 : 0) | (input[4].Read() ? 16 : 0));
- for (int i = 0; i < bytSendData[2]; i++)
- {
- bytSendData[3 + i] = DataBuff[lngDataAddr * 2 + i];
- }
- intCRC16 = GetCheckCode(bytSendData, 3 + lngDataNum * 2);
- bytSendData[3 + lngDataNum * 2] = (byte)(intCRC16 & 0xFF); //CRC校驗低位
- bytSendData[4 + lngDataNum * 2] = (byte)((intCRC16 >> 8) & 0xff); //CRC校驗高位
- //傳送資料
- int intRet=serial.Write(bytSendData, 0, 5 + lngDataNum * 2);
- //Debug.Print("SendData OK " + intRet.ToString() );
- bytErrorFlag = 1;
- }
- }
- if (bytErrorFlag == 0)
- {
- //協議不支援
- bytSendData[0] = bytRtuData[0];
- bytSendData[1] = (byte)(bytRtuData[1] | 0x80);
- bytSendData[2] = bytErrorNo;
- intCRC16 = GetCheckCode(bytSendData, 3);
- bytSendData[3] = (byte)(intCRC16 & 0xFF); //CRC校驗低位
- bytSendData[4] = (byte)((intCRC16 >> 8) & 0xff); //CRC校驗高位
- //傳送資料
- serial.Write(bytSendData, 0, 5);
- }
- }
- bytRtuDataFlag = 0;
- }
- }
- return;
- }
- //串列埠號
- public static class Serial
- {
- public const SerialPort.Serial COM1 = (SerialPort.Serial)0;
- public const SerialPort.Serial COM2 = (SerialPort.Serial)1;
- }
- //串列埠波特率
- public static class BaudRate
- {
- public const SerialPort.BaudRate Baud4800 = (SerialPort.BaudRate)4800;
- public const SerialPort.BaudRate Baud9600 = (SerialPort.BaudRate)9600;
- public const SerialPort.BaudRate Baud19200 = (SerialPort.BaudRate)19200;
- public const SerialPort.BaudRate Baud38400 = (SerialPort.BaudRate)38400;
- public const SerialPort.BaudRate Baud57600 = (SerialPort.BaudRate)57600;
- public const SerialPort.BaudRate Baud115200 = (SerialPort.BaudRate)115200;
- public const SerialPort.BaudRate Baud230400 = (SerialPort.BaudRate)230400;
- }
- }
- }
程式部署執行後,直接用標準的Modbus Rtu客戶端程式測試即可,我用的是我以前編寫的Modbus Rtu Client程式,測試如下:
(圖MF10280002.JPG)
這時候,你直接操作SW2的撥碼,該數字就會發生變化(前提SW1的撥碼都撥到右邊)。
缺點:很奇怪的是串列埠的引數僅能配置波特率,奇偶校驗,資料位卻無法配置。
總的印象:用MF開發嵌入式系統還是非常有前景的,至少使產品的開發週期大大縮短,並且程式碼升級維護方便。
相關文章
- .NET Compact Framework下的串列埠通訊Framework串列埠
- 微軟將.Net Micro Framework原始碼移交社群微軟Framework原始碼
- QT串列埠助手(五):檔案操作QT串列埠
- 串列埠UART串列埠
- 帶內串列埠 在串列埠中輸入命令串列埠
- Linux下串列埠通訊詳解(下)讀寫串列埠及關閉串列埠Linux串列埠
- 在Java中操作串列埠實現簡訊收發Java串列埠
- 串列埠資料抓取及串列埠通訊模擬串列埠
- 你真的瞭解串列埠嗎(示波器串列埠波形分析)串列埠
- 串列埠流控串列埠
- 串列埠通訊串列埠
- 串列埠blog串列埠
- Linux下PCI轉串列埠卡及USB轉串列埠Linux串列埠
- IBM串列埠線序以及串列埠線的做法(轉)IBM串列埠
- Linux 串列埠程式設計 串列埠裝置程式開發Linux串列埠程式設計
- QT實現串列埠助手中串列埠名的實時更新QT串列埠
- 【STM32】串列埠串列埠
- 串列埠小工具串列埠
- mina serial 串列埠串列埠
- android串列埠程式Android串列埠
- putty能使用串列埠串列埠
- 串列埠通訊 (轉)串列埠
- 沒有真實串列埠裝置時使用"虛擬串列埠驅動"除錯你的串列埠程式碼串列埠除錯
- 樹莓派已經通過網路連線通過串列埠通訊在串列埠除錯小助手列印與操作樹莓派串列埠除錯
- .NET Framework 4 和 .NET Framework 4 Client ProfileFrameworkclient
- 9針串列埠引腳定義 25針串列埠引腳定義串列埠
- 串列埠,COM口,UART,USART串列埠
- linux 串列埠通訊Linux串列埠
- 串列埠通訊協議串列埠協議
- Android 串列埠通訊Android串列埠
- ubuntu繫結串列埠號Ubuntu串列埠
- 9針串列埠除錯串列埠除錯
- 初學串列埠問題串列埠
- C# 串列埠通訊C#串列埠
- 11. 串列埠通訊串列埠
- 串列埠通訊型別串列埠型別
- (10)uart串列埠通訊串列埠
- .net framework 5.0Framework