C

CRC CCITT 16bit

       private ushort CRC_CCITT_LSBfirst_ALL(ushort len, byte[] bufp)
       {
          int i,j;
       byte    ch = 0x00;
       ushort  crc = 0xffff;
             ushort POLY = 0x8408;

        for(j = 0;j < len;j++)
        {
	        ch = bufp[j];
	        crc ^= (ushort)ch;
	        for (i = 0; i < 8; i++)
	        {
		        if((crc & 0x0001) == 0x0001)
                   {
                       crc = (ushort)(crc >> 1);
			        crc ^= POLY;
		        }
		        else
                   {
                       crc = (ushort)(crc >> 1);
		        }
	        }
        }

        return crc;
       }

string型のHEX文字をByte配列に変換する関数

using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Diagnostics;       

public Byte[] GetBytesFromHexString(string strInput)
       {
           Byte[] bytArOutput = new Byte[] { };
           if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0)
           {
               SoapHexBinary hexBinary = null;
               try
               {
                   hexBinary = SoapHexBinary.Parse(strInput);
                   if (hexBinary != null)
                       bytArOutput = hexBinary.Value;
               }
               catch (Exception ex)
               {
                   MessageBox.Show(ex.Message);
               }
           }
           return bytArOutput;
       }

シリアル通信受信時に取りこぼしが発生する際の対処方法

  • 処理するCPUコアを変更する
  • アプリの優先順位を変更する
  • デバイスのFIFOバッファサイズを変更する
(これは一番効果があるけど、大体最大サイズになっている)
  • 「ここ」を参照する
  • アクノリッチ(フリーソフト)の場合は、ソフトウェアバッファサイズを増やすと改善する。そのバッファが溢れるまでは大丈夫。

動作CPU指定

どのCPUコアで動作するかを指定する。
// 動作CPU指定
uint cpuno = 1;
Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)cpuno;
// 自身の動作CPUを取得する。
var processor = Process.GetCurrentProcess().ProcessorAffinity.ToInt32();
cpuinf = processor.ToString();

優先度指定

アプリの優先度を指定する。
       public ProcessPriorityClass PriorityClass
       {
           get;
           set;
       }
Process thisProcess = null;
uint priority;
           thisProcess = System.Diagnostics.Process.GetCurrentProcess();
           switch(priority)
           {
               case 0: thisProcess.PriorityClass = ProcessPriorityClass.Normal;        break;
               case 1: thisProcess.PriorityClass = ProcessPriorityClass.AboveNormal;   break;
               case 2: thisProcess.PriorityClass = ProcessPriorityClass.High;          break;
               case 3: thisProcess.PriorityClass = ProcessPriorityClass.RealTime;      break;
               default:
                       thisProcess.PriorityClass = ProcessPriorityClass.Normal;        break;
           }

C#からのGPIB

C#でGPIBを利用するには、ここの資料がわかりやくて良かった。
GPIBのドライバ等は、ここ

参考サイト


バージョン情報の表示

C#のバージョン情報は、「AssenmblyInfo.cs」に記述することが出来る。
以下のソースは、その情報をメッセージボックスで表示するだけ。
           string str;

           // バージョン情報の表示
           // http://www.atmarkit.co.jp/fdotnet/dotnettips/282verinfodlg/verinfodlg.html
           // http://jeanne.wankuma.com/tips/csharp/dialog/messagebox.html
           //---
           // バージョン名(AssemblyInformationalVersion属性)を取得
           string appVersion = Application.ProductVersion;
           // 製品名(AssemblyProduct属性)を取得
           string appProductName = Application.ProductName;
           // 会社名(AssemblyCompany属性)を取得
           string appCompanyName = Application.CompanyName; 

           // 表示情報
           str  = "製品名 " + appProductName + "\r\n";
           str += "\r\n";
           str += "Version " + appVersion + "\r\n";
           str += "\r\n";
           str += "会社名 " + appCompanyName + "\r\n";

           // 表示
           MessageBox.Show(str, "バージョン情報");

最小二乗法


タイムスタンプ

times = System.DateTime.Now.ToString() + "." + System.DateTime.Now.Millisecond.ToString("000");
str = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(dat);
log.Write(times + "," + str);

グラフ(Chart)の設定とか

chart1.Series.Clear();
chart1.Series.Add("PLL");
chart1.Series["PLL"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.ChartAreas[0].AxisY.Title = "レベル[a.u.]";
chart1.ChartAreas[0].AxisX.Title = "周波数[MHz]";
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Maximum = 15000;

// 凡例なし
chart1.Legends.Clear();

// グラフタイトル プロパティで事前にタイトルを追加しておく必要あり
chart1.Titles[0].Text = "test";

// 表示
chart1.Series["PLL"].Points.AddXY(((i + 1) * db_delta + db_offset) / 1000000, stArrayData[i]);

// グラフデータクリア
chart1.Series["CS0"].Points.RemoveAt(0);
               
// グラフクリア
chart1.Series.Clear();

C#でワーカースレッド

using System.Threading.Tasks;

Thread thread;
thread = new Thread(new ThreadStart(ThreadMethod));
thread.Start();

private void ThreadMethod()
{
  //ここに処理を書く
}

時刻取得(msオーダで取得)

DateTime dt = System.DateTime.Now;
times = dt.ToString("yyyy/MM/dd HH:mm:ss") + "." + dt.Millisecond.ToString("000");

時間シリアル値の取得

long nowtime;
long diff;
nowtime = DateTime.Now.ToUniversalTime().Ticks;
diff = (nowtime - prevtime)/10000; // [ms] prevtimeは前のnowtimeの値

文字検索

//改行コードがあれば整数(0以上)、なければ-1が返る
if (str.IndexOf("\n") < 0)
{
   // 文字の途中
}

ログ保存(テキスト)

バイナリ保存したいものを↓の方法で保存すると場合によってはおかしな値で保存されてしまう。
System.IO.StreamWriter log;
String logPath;
string file;

file = System.DateTime.Now.ToString("yyyyMMddHHmmss");
file = file.Replace("/", "");
file = file.Replace(":", "");
file = file.Replace(" ", "");
logPath = AppDomain.CurrentDomain.BaseDirectory + "Log_U3751_" + file + ".csv";
log = new System.IO.StreamWriter(logPath, true,  System.Text.Encoding.GetEncoding("shift_jis"));

log.Write("# Time/Freq,");
log.Flush(); // closeしなくても中身が反映される
log.Close();

ログ保存(バイナリ)

System.IO.FileStream jpg = null;
string file;

// ログ保存
file = System.DateTime.Now.ToString("yyyyMMddHHmmss");
file = file.Replace("/", "");
file = file.Replace(":", "");
file = file.Replace(" ", "");
filePath = AppDomain.CurrentDomain.BaseDirectory + file + ".jpg";
//http://codepanic.itigo.jp/cs/file_writebinary.html
jpg = new System.IO.FileStream(filePath, System.IO.FileMode.Create);

// jpg画像保存(バイナリ)
jpg.Write(dat, 0, dat.GetLength(0)); 
jpg.Close();

iniファイル

using System;
using System.IO;
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;

//クラスの中に書く
private String filePath { get; set; }

[DllImport("KERNEL32.DLL")]
public static extern uint
GetPrivateProfileString(string lpAppName,
string lpKeyName, string lpDefault,
StringBuilder lpReturnedString, uint nSize,
string lpFileName);

[DllImport("KERNEL32.DLL",
EntryPoint = "GetPrivateProfileStringA")]
public static extern uint
GetPrivateProfileStringByByteArray(string lpAppName,
string lpKeyName, string lpDefault,
byte[] lpReturnedString, uint nSize,
string lpFileName);

[DllImport("KERNEL32.DLL")]
public static extern uint
GetPrivateProfileInt(string lpAppName,
string lpKeyName, int nDefault, string lpFileName);

[DllImport("KERNEL32.DLL")]
public static extern uint WritePrivateProfileString(
string lpAppName,
string lpKeyName,
string lpString,
string lpFileName);

// ini読み出し
this.filePath = AppDomain.CurrentDomain.BaseDirectory + "SRAMcom.ini";
Form1.WritePrivateProfileString("COM", "baudrate", "8000000", filePath);
com_baudrate = Form1.GetPrivateProfileInt("COM", "baudrate", 8000000, filePath);
graph_width = Form1.GetPrivateProfileInt("Graph", "width", 100, filePath);

COMポート

try
               {
                   // シリアルポートのオープン
                   serialPort1.PortName = com_portname.ToString();
                   // シリアルポートの通信速度指定
                   serialPort1.BaudRate = (int)com_baudrate;
                   // シリアルポートのパリティ指定
                   serialPort1.Parity = System.IO.Ports.Parity.None;
                   // シリアルポートのビット数指定
                   serialPort1.DataBits = 8;
                   // シリアルポートのストップビット指定
                   serialPort1.StopBits = System.IO.Ports.StopBits.One;
                   // シリアルポートのRTS指定
                   serialPort1.RtsEnable = true;
                   // シリアルポートのオープン
                   serialPort1.Open();

               }
               catch (Exception ex)
               {
                   MessageBox.Show(ex.Message);

                   return;
               }

// シリアルポートのクローズ
serialPort1.Close();

シリアルポートがOpenしているのかのチェック

serialPort1.IsOpen == false // 閉じているなら真

シリアル送信

           Byte[] dat = new byte[10];

           // Once送信
           if (serialPort1.IsOpen == true)
           {
               serialPort1.Write(dat, 0, dat.GetLength(0));
           }

シリアル受信

       private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
       {         
           // 受信処理
           Byte[] dat = new Byte[serialPort1.BytesToRead];
           serialPort1.Read(dat, 0, dat.GetLength(0));
       }

シリアル受信の中でテキストボックスを更新(デリゲート)

// namespaceの外側に記載
delegate void MyDelegate(string text);

       private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
       {
           string str;

           // 受信処理
           Byte[] dat = new Byte[serialPort1.BytesToRead];
           serialPort1.Read(dat, 0, dat.GetLength(0));

           str = "";
           for (int i = 0; i < dat.GetLength(0);i++ )
               str += dat[i].ToString("X2");

           //スレッド内からデリゲートを介して以下のようにして呼ぶ
           //Invoke(new MyDelegate(AddText), str);
           BeginInvoke(new MyDelegate(AddText), str);

            // 少し待つ
            System.Threading.Thread.Sleep(1);
       }

       internal void AddText(string text)
       {
           textBox2.Text = text;
       }

Timer

通常のTimer(精度はあまりよくない55ms下限)、もっと精度が欲しいときは、「System.Timers.Timer」を使用するらしい。
// デザイナーのコード
private void InitializeComponent()
{
    this.timer1 = new System.Windows.Forms.Timer();
    this.timer1.Enabled = true;
    this.timer1.Interval = 200;
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}
スタートさせるときは、
timer1.Start();
ストップするときは、
timer1.Stop();

テキストボックス

変数をテキストボックスに表示するには、以下のようにする
this.textBox1.Text = "" + i;

種々の変換

  • 文字列から数字
string str = "123456789";
int num = int.Parse(str);
double num = double.Parse(str);
myData[0] = byte.Parse(stArrayData[0], System.Globalization.NumberStyles.AllowHexSpecifier);

  • 文字列から切り出し
str1.Substring( 0, 2);

  • float(IEEE754)変換
数字からHEXへ
float	flo_in;
byte[] chr = new byte[8];
byte	*p_flo;

flo_in = float.Parse(textBox1.Text);
p_flo = (byte *)&flo_in;
chr[0] = p_flo[0];
chr[1] = p_flo[1];
chr[2] = p_flo[2];
chr[3] = p_flo[3];

textBox2.Text = chr[3].ToString("X2") + chr[2].ToString("X2") + chr[1].ToString("X2") + chr[0].ToString("X2");
HEXから数字へ
string hexString = textBox3.Text;
uint num = uint.Parse(hexString, System.Globalization.NumberStyles.AllowHexSpecifier);

byte[] floatVals = BitConverter.GetBytes(num);
float f = BitConverter.ToSingle(floatVals, 0);

textBox4.Text = f.ToString();

  • 数字から数字(文字)
data.ToString("X2") //数字を16進数に変換
data.ToString("F3") //実数を少数3桁で表示
data.ToString("D2") //整数2桁で表示
  • 数字から文字列
str = num.ToString();
  • 区切り文字
string stCsvData = "5, Jitta, ABC";
// カンマ区切りで分割して配列に格納する
string[] stArrayData = stCsvData.Split(',');
  • 特定の文字の出現数を数える
 public static int CountChar(string s, char c) {
   return s.Length - s.Replace(c.ToString(), "").Length;
 }
Console.WriteLine(CountChar(s, 'の'));

テキストボックス

  • 最後の行までスクロールする
TextBox1.SelectionStart = TextBox1.Text.Length
//テキストボックスにフォーカスを移動
TextBox1.Focus();
//カレット位置までスクロール
TextBox1.ScrollToCaret();
  • 行数を得る
textBox1.Lines.Length
  • n行目の中身を得る
str = textBox1.Lines[i];
最終更新:2018年12月14日 00:13