忍者ブログ

Azukish

消えゆく世界と流れる未来に最後の灯を since 2006/4/3

2017/09/14

WPFからCOMポートを読み取る


実にシンプルなコードだけど、WPF慣れてないので、意外と苦労した。
あとサムネの画像が4Kにしたらでけえ 笑



MainWindow.xaml.cs
using System;
using System.Windows;
using System.IO.Ports;

namespace WpfApplication2 {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }

        SerialPort myPort = null;
        bool receiving = false;
        private void button_Click(object sender, RoutedEventArgs e) {
            if (receiving) {
                button.Content = "Receive";
                receiving = false;
                myPort.Close();
                return;
            }
            receiving = true;
            myPort = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
            textBox.Text = "receiving...";
            button.Content = "Stop";
            try {
                myPort.NewLine = "\r\n";
                myPort.Open();
                myPort.DataReceived += (s, ex) => {
                    var readData = myPort.ReadLine();
                    Dispatcher.Invoke(new Action(() => {
                        textBox.Text = readData;
                    }));
                };
            } catch (Exception err) {
                textBox.Text = err.ToString();
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
            if (myPort.IsOpen)
                myPort.Close();
            myPort.Dispose();
        }
    }
}

MainWindow.xaml
<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="191,94,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
        <Button x:Name="button" Content="Receive" HorizontalAlignment="Left" Margin="191,140,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
    </Grid>
</Window>

MainWindow.xaml.csについての説明を以下
シリアルポートを設定して、
myPort = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);

開いてデータが来たら、一行読み取る。
myPort.NewLine = "\r\n";
myPort.Open();
myPort.DataReceived += (s, ex) => {
  var readData = myPort.ReadLine();
  Dispatcher.Invoke(new Action(() => {
    textBox.Text = readData;
  }));
};

この際に、DataReceived+=云々が書いてあるけれど、これがイベントハンドラの代わりらしい。
要はデータが来たときに中括弧{}の中に入ってる内容を実行する。
これはbutton_Click()が実行される時から外れるので、Dispatcher.Invokeを入れないと非同期処理がどうとかこうとかのエラーが出る。
button_Click()の中で定義されたモノが、button_Click()の外から何かを弄ろうとするとダメらしい。
非同期勉強してないのでよく分からない・・・。

ボタンを押した後に再びボタンを押すとポートを閉じるようにした。
if (receiving) {
  button.Content = "Receive";
  receiving = false;
  myPort.Close();
  return;
}

最後にWindowを閉じる際にシリアルポートが開いてればそれを閉じて捨てる。
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
  if (myPort.IsOpen)
    myPort.Close();
  Port.Dispose();
}

MSP430G2で動作確認。
以下コードだけど、詳しくはAzukish | MSP430G2でUARTを使ってみる。を参照されたし。
#include <msp430.h>
#include <msp430g2553.h>

char str[] = {"Hello World\r\n"};
unsigned int i=0;

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer

    DCOCTL = 0; // Select lowest DCOx and MODx settings
    BCSCTL1 = CALBC1_1MHZ; // Set DCO
    DCOCTL = CALDCO_1MHZ;

    P1SEL |= BIT2;
    P1SEL2 |= BIT2; // Enable TXD (P1.2)

    UCA0CTL1 |= UCSSEL_2;   // USCI clock source = SMCLK = 1MHz at default
    UCA0BR0 = 0x68;         // Frequency divider for UART
    UCA0BR1 = 0x00;         // 9600Hz is needed, but 1MHz/104=9615Hz is set
    UCA0MCTL = UCBRS0;      // UCBRSx=1

    UCA0CTL1 &= ~UCSWRST;   // Initialize UCSI state machine
    UCA0TXBUF = str[i++];   // Send message
    UC0IE |= UCA0TXIE;      // USCI_A0 RX interrupt

    __bis_SR_register(CPUOFF + GIE);
}

// Send Interrupt
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void) {
    UCA0TXBUF = str[i++];
    if (i==sizeof(str)-1)
        UC0IE &= ~UCA0TXIE;
}

拍手

コメント













カウンター

カレンダー

11 2018/12 01
S M T W T F S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

アーカイブ

AD

Azkishはamazon.co.jpを宣伝しリンクすることによって サイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。