1.先從工具箱拉SerialPort元件(要記得程式碼加入System.IO.Ports)
2.點選元件可以調整BaudRate.DataBit.ParityBit.HandShake...等
3.也可以從程式碼中新增: serialPort1 = new SerialPort(COM幾(String), 9600, Parity.None, 8, StopBits.One);
4.如果要抓取電腦現有的COM,可以使用string[] port_name = SerialPort.GetPortName();
可以用foreach() loop + comboBox的add來新增到comboBox裡面
5.讀取部分
private byte[] Port_read()
{
//---------------------------讀取部分---------------------------------//
int B2R = serialPort1.BytesToRead;//有多少
byte[] Buffer = new byte[B2R];//new多少byte 陣列
if (B2R > 0)
{
serialPort1.Read(Buffer, 0, B2R);//有多少就讀入多少(共85byte)
}
return Buffer;
//---------------------------讀取部分-End------------------------------//
}
6.寫入部分
//---------------------------寫入部分----------------------------------//
//先檢查有幾個modbus,
try
{
serialPort1.Write(byte陣列, 0, 寫多少byte);
}
catch (InvalidOperationException)
{
MessageBox.Show("關閉通訊埠");//關閉通訊埠
}
catch (IOException IOE)
{
MessageBox.Show(IOE.Message);
MessageBox.Show("IO錯誤");//IO exception
}
大致上就完成簡單的通訊程式
其餘比較有用的:
System.Text.Encoding.Default.GetBytes(String); //string轉byte[]
System.Text.Encoding.Default.GetString(byte[]);//byte[]轉String
2014年2月7日 星期五
[C#] Class小記 - 以 CRC 16為例
先看程式碼,如下
class CRC_16
{
public byte CRC_1 { get; set; }
public byte CRC_2 { get; set; }
public void CRC16_counter(byte[] data, int CRC_length) //跑兩個 1.送出去產生CRC(length = 6) 產生後 = 8
{ // 2.接收時驗證CRC(length = 83) 產生後 = 85
ushort CRCFull = 0xFFFF;
byte CRChigh = 0xFF, CRClow = 0xFF;
char CRC_LSB;
for (int i = 0; i < CRC_length; i++)
{
CRCFull = (ushort)(CRCFull ^ data[i]); //指令的第i組數字與CRCFull做XOR
for (int j = 0; j < 8; j++)//8bit,所以跑八次
{
CRC_LSB = (char)(CRCFull & 0x00000001);//取得最後一個位元的值
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); //右移一位,第一位補0
//檢查
if (CRC_LSB == 0) //如果右移的值為0
{
//就把剛剛右移+第一位補零的數值存入暫存(不過已經做了,這邊只是註解)
}
if (CRC_LSB == 1) // 如果右移的值為1
{
CRCFull = (ushort)(CRCFull ^ 0xA001); //跟0xA001去做XOR,存入暫存器
}
}
}
//跑完要讓高低register對調
//CRChigh = (byte)((CRCFull >> 8) & 0xFF); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1
//CRClow = (byte)(CRCFull & 0xFF); //低的變成高的
CRChigh = (byte)(CRCFull >> 8); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1,不用&0xff也可
CRClow = (byte)CRCFull; //低的變成高的,不用&0xff也可
if (CRC_length == 6)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
if (CRC_length == 83)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
}
}
本例Protocol有兩種1.傳送(8byte)2.接收(85byte)
因此先用6byte 算出CRC(最後2byte) = 8 / 83byte 算出CRC(最後2byte) = 85,
用以驗證CRC-16是否正確。
Class部份假如要使用到CRC_1,CRC_2 則需要 這樣呼叫
1.先new好Class
CRC_16 CRC = new CRC_16();
2.存取Class內部資料
CRC.CRC_1 ,CRC.CRC_2
3.如果內部將CRC_1宣告成 public static .... ,則呼叫需改為
namespace名稱.Class名稱.CRC_1
class CRC_16
{
public byte CRC_1 { get; set; }
public byte CRC_2 { get; set; }
public void CRC16_counter(byte[] data, int CRC_length) //跑兩個 1.送出去產生CRC(length = 6) 產生後 = 8
{ // 2.接收時驗證CRC(length = 83) 產生後 = 85
ushort CRCFull = 0xFFFF;
byte CRChigh = 0xFF, CRClow = 0xFF;
char CRC_LSB;
for (int i = 0; i < CRC_length; i++)
{
CRCFull = (ushort)(CRCFull ^ data[i]); //指令的第i組數字與CRCFull做XOR
for (int j = 0; j < 8; j++)//8bit,所以跑八次
{
CRC_LSB = (char)(CRCFull & 0x00000001);//取得最後一個位元的值
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF); //右移一位,第一位補0
//檢查
if (CRC_LSB == 0) //如果右移的值為0
{
//就把剛剛右移+第一位補零的數值存入暫存(不過已經做了,這邊只是註解)
}
if (CRC_LSB == 1) // 如果右移的值為1
{
CRCFull = (ushort)(CRCFull ^ 0xA001); //跟0xA001去做XOR,存入暫存器
}
}
}
//跑完要讓高低register對調
//CRChigh = (byte)((CRCFull >> 8) & 0xFF); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1
//CRClow = (byte)(CRCFull & 0xFF); //低的變成高的
CRChigh = (byte)(CRCFull >> 8); //右移8Bit,也就是變成低位元,跟FF(1111 1111)做& 0還是0 1還是1,不用&0xff也可
CRClow = (byte)CRCFull; //低的變成高的,不用&0xff也可
if (CRC_length == 6)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
if (CRC_length == 83)
{
CRC_2 = CRChigh;//現在是低
CRC_1 = CRClow; //現在是高
}
}
}
本例Protocol有兩種1.傳送(8byte)2.接收(85byte)
因此先用6byte 算出CRC(最後2byte) = 8 / 83byte 算出CRC(最後2byte) = 85,
用以驗證CRC-16是否正確。
Class部份假如要使用到CRC_1,CRC_2 則需要 這樣呼叫
1.先new好Class
CRC_16 CRC = new CRC_16();
2.存取Class內部資料
CRC.CRC_1 ,CRC.CRC_2
3.如果內部將CRC_1宣告成 public static .... ,則呼叫需改為
namespace名稱.Class名稱.CRC_1
2014年2月6日 星期四
[C#/winform] 讀寫ini檔
ini檔為windows內常用來儲存setting的檔案,C#範例如下。
dllimport為必須要的,會動態連結到system32的檔案,
WritePrivateProfileString(string section, string key, string val, string filePath)寫入ini檔案
GetPrivateProfileString( string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString,uint nSize, string lpFileName)讀取ini檔案
P.S.此範例為自動抓取RS-232 port放入comboBox1內,尚未寫完,但讀寫ini的部分是完整的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
namespace Test_INI
{
public partial class Form1 : Form
{
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public Form1()
{
InitializeComponent();
string[] port_list = SerialPort.GetPortNames();
foreach (string port in port_list)
{
//MessageBox.Show("本機可用serial port: " + port); //測試用
comboBox1.Items.Add(port);
}
//當select port index換的時候 ,加入WritePrivateProfileString("Port Name", "name", 選擇的port
//string, @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("Port Name", "name", "COM1", @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("ModBus", "number", "1", @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("ModBus", "number", "2", @"D:\myConfig.ini");//寫入ini檔
}
private void button1_Click(object sender, EventArgs e)
{
StringBuilder data = new StringBuilder(255);
GetPrivateProfileString("Port Name", "name", "NA", data, 255,
@"D:\myConfig.ini");//section/key/def/ stringbuilder的變數/長度/路徑
MessageBox.Show(data.ToString());
}
}
}
dllimport為必須要的,會動態連結到system32的檔案,
WritePrivateProfileString(string section, string key, string val, string filePath)寫入ini檔案
GetPrivateProfileString( string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString,uint nSize, string lpFileName)讀取ini檔案
P.S.此範例為自動抓取RS-232 port放入comboBox1內,尚未寫完,但讀寫ini的部分是完整的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO.Ports;
namespace Test_INI
{
public partial class Form1 : Form
{
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public Form1()
{
InitializeComponent();
string[] port_list = SerialPort.GetPortNames();
foreach (string port in port_list)
{
//MessageBox.Show("本機可用serial port: " + port); //測試用
comboBox1.Items.Add(port);
}
//當select port index換的時候 ,加入WritePrivateProfileString("Port Name", "name", 選擇的port
//string, @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("Port Name", "name", "COM1", @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("ModBus", "number", "1", @"D:\myConfig.ini");//寫入ini檔
WritePrivateProfileString("ModBus", "number", "2", @"D:\myConfig.ini");//寫入ini檔
}
private void button1_Click(object sender, EventArgs e)
{
StringBuilder data = new StringBuilder(255);
GetPrivateProfileString("Port Name", "name", "NA", data, 255,
@"D:\myConfig.ini");//section/key/def/ stringbuilder的變數/長度/路徑
MessageBox.Show(data.ToString());
}
}
}
[C#/winform] 不同解析度調整視窗大小
利用DPI取得螢幕解析度比例,進而改變WinForm的大小
廢話不多說
如上,DPI可能為
DPI | 大小百分比 |
96 | 100% |
120 | 125% |
144 | 150% |
廢話不多說
// 找出字體大小,並算出比例
float dpiX, dpiY;
Graphics graphics = this.CreateGraphics();
dpiX = graphics.DpiX;
dpiY = graphics.DpiY;
int intPercent = (dpiX == 96) ? 100 : (dpiX == 120) ? 125 : 150;
// 針對字體變更Form的大小
this.Height = this.Height * intPercent / 100;
this.Width = this.Width * intPercent / 100;
end.
位置:
台灣
訂閱:
文章 (Atom)