본문으로 바로가기

C# 시리얼 통신 아스키 외 값 읽기

category 프로그래밍/C# 2020. 8. 17. 00:00
반응형

오늘 포스팅할 내용은 시리얼 통신에 관한 내용입니다.

 

C#을 이용한 시리얼 통신 방법은 아래의 포스팅을 참조 해주세요.

2019/04/15 - [프로그래밍/C#] - C#을 이용한 시리얼 통신(포트 검색/연결/해제)


최근에 시리얼 통신 프로그램을 만들었는데, 당연히 된다고 생각했던 것이 안돼서 당황을 했습니다.

C#을 제대로 배운 것이 아니라 다 안다고 착각을 했던... 후후...

 

시리얼 통신을 할 때 수신 데이터를 읽기 위해서 Serial.ReadExisting을 사용하는데 이 부분에서 문제가 발생을 한 것이었습니다.

ReadExisting으로 받은 String 값을 Hex로 변환을 하면서 문제가 발생하였는데요, 해당 메서드는 아스키만 표현된다는 것을 알게 되었습니다.

 

즉, 코드 테이블 영역의 0xB0를 ReadExisting 메소드로 읽게 되면 0x3F('?')로 읽힌다는 것...

그렇다면 아스키 영역(0x00 ~ 0x7F)코드 테이블 영역(0x80 ~ 0xFF) 모두 읽으려면?

Serial.Read를 사용하여 Byte로 Read를 하면 됩니다.

 

아래 Serial Read 예제 입니다.

 

 

  Serial.Read 데이터 읽기

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports; // 직렬 포트 제어 클래스 포함
 
namespace Port_Open
{
    public partial class Form1 : Form
    {
        string str;
 
        public Form1()
        {
            InitializeComponent();
            string[] PortNames = SerialPort.GetPortNames();  // 포트 검색.
 
            foreach (string portnumber in PortNames)
            {
                Port_Combox.Items.Add(portnumber);          // 검색한 포트를 콤보박스에 입력. 
            }
 
        }
 
        private void Close_btn_Click(object sender, EventArgs e)
        {
            if (SerialPort.IsOpen == true)
            {
                SerialPort.Close();
                Timer.Stop();             // Timer Stop
                textBox1.Text += "해제되었습니다." + Environment.NewLine;
            }
            else textBox1.Text += "해제되어 있습니다 ." + Environment.NewLine;           
        }
 
        private void Open_btn_Click(object sender, EventArgs e)
        {
            if (SerialPort.IsOpen == false)
            {
                SerialPort.PortName = Port_Combox.SelectedItem.ToString();                     //콤보 박스에서 선택.
                SerialPort.BaudRate = int.Parse(Baud_Combox.SelectedItem.ToString());          //콤보 박스에서 Baud Rate 선택.
                SerialPort.DataBits = 8;
                SerialPort.StopBits = StopBits.One;
                SerialPort.Parity = Parity.None;
                SerialPort.Open();
                Timer.Start();            // Timer Stop
                SerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); //데이터 받기.
                textBox1.Text += "연결되었습니다." + Environment.NewLine;
 
                SerialPort.WriteLine("abcd\r\n");                                                    // abcd\r\n Send
            }
            else
            {
                textBox1.Text += "연결되어 있습니다." + Environment.NewLine;
            }
        }
        /*
         * SerialPort.DataReceived Event
         */
        private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            int RecvSize = Serial.BytesToRead;
            string RecvStr = string.Empty;
            // Recv Data가 있는 경우...
            if (RecvSize != 0)
            {
                byte[] buff = new byte[RecvSize];
            
                // Size 만큼 Read...
                Serial.Read(buff, 0, RecvSize );
                for (int i= 0; i < RecvSize ; i++)
                {
                  // Hex 변환...
                 
                      RecvStr += " " + buff[i].ToString("X2");
                }
                textBox.Text += RecvStr ;
            }
        }
        /*
         * Serial 통신 Setting Box
         */
        private void Port_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Baud_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Databits_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Stopbits_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
 
        private void Parity_Combox_SelectedIndexChanged(object sender, EventArgs e)
        {
 
        }
        /*
         * Send/Receive 데이터 표시
         */
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            textBox1.SelectionStart = textBox1.TextLength;     //스크롤 자동으로 내린다.
            textBox1.ScrollToCaret();
        }
    }
}
 
 

SerialPort.DataReceived Event쪽을 자세히 보면 RecvSize를 확인하고 RecvSize만큼 Read를 합니다.

 

 

 

  정리

 

Serial.ReadExisting

데이터 처리 방식 : String으로 데이터를 받음.

데이터 범위 : ASCII영역(0x80 ~ 0xFF영역의 코드 테이블 영역의 데이터를 받게 되는 경우 다른 값으로 표현됨.)

 

Serial.Read

데이터 처리 방식 : Byte로 데이터를 받음.

데이터 범위 : 0x00 ~ 0xFF

 

ASCII영역과 코드 테이블 영역을 모두 받으려면 Serial.Read를 사용.

 

 

2019/04/15 - [프로그래밍/C#] - C#을 이용한 시리얼 통신(포트 검색/연결/해제)

2019/08/25 - [프로그래밍/C#] - C# 마우스 제어(클릭, 좌표 이동)

2020/06/22 - [프로그래밍/C#] - C# 유튜브 동영상 다운로더 만들기(MP3, MP4)

 

 

 

 

반응형