ถึงแม้ว่าคอมพิวเตอร์จะพัฒนาไปไกล จนถึงระดับ 64 บิตแล้วก็ตาม สิ่งหนึ่งที่ยังเป็นที่นิยม ยังมีใช้อยู่ทั่วไปก็คือ พอร์ตอนุกรม โดยเฉพาะในโลก Embedded system แล้ว หากคุณต้องการที่จะรับส่งข้อมูลระหว่างอุปกรณ์ภายนอก และโปรแกรมภายในคอมพิวเตอร์แล้ว พอร์ตอนุกรม หรือ Serial Port ก็ยังเป็นที่นิยมอยู่ ด้วยความที่มันติดต่อกันในรูปแบบที่ไม่ซับซ้อน สามารถเข้าใจได้ง่าย ช่วยให้งานจบได้เร็ว จึงทำให้ทุกวันนี้ เรายังพบเห็นโปรแกรมที่รับส่งข้อมูลทางพอร์ตอนุกรมอยู่ ถึงแม้่ว่าคอมพิวเตอร์บางเครื่องจะไม่มีพอร์ตอนุกรมแล้วก็ตาม เราก็ยังสามารถที่จะใช้ตัวแปลง USB to Serial ทำงานได้เหมือนๆ กัน
วันนี้เรามาเขียนโปรแกรมรับส่งข้อมูลทางพอร์ตอนุกรมกันครับ โดยผมจะเขียน application เพื่อรับส่งข้อมูลระหว่างคอมพิวเตอร์ กับ ไมโครคอนโทรลเลอร์ผ่านทาง Serial Port โดยมีเงือนไขดังนี้
MCU ทำการส่งข้อมูลออกไป โดยมีรูปแบบดังนี้ #ADC1,ADC2,ADC3*
โดยเราให้
- # แสดงการเริ่มต้นส่งข้อมูล
- ADCx ค่าอนาล๊อกที่อ่านได้จากช่อง Analog input ของ MCU มีค่าอยู่ระหว่าง 0-1023
- * แสดงจุดสิ้นสุดข้อมูล
ซึ่ง Visual C# จะรับข้อมูลแล้วไปประมวลผลตามที่เราออกแบบไว้ จากนั้น Visual C# สามารถส่งข้อมูลออกไปหาที่ตัว MCU ได้ด้วยรูปแบบดังนี้ #Button1,Button2,Button3*
โดยเราให้
- # แสดงการเริ่มต้นส่งข้อมูล
- Buttonx แสดงค่าสถานะการกดปุ่ม 0:ปุ่มไม่ถูกกด, 1:ปุ่มถูกกด
- * แสดงจุดสิ้นสุดข้อมูล
ผมออกแบบหน้าต่างฟอร์มแบบนี้ครับ
ในส่วนของโค๊ด
เริ่มจากเราต้อง using System.IO.Ports; เพื่อจะสร้างออปเจค serial port จาก class SerialPort เมื่อเราได้ using เข้ามาแล้ว เราจึงสามารถทีจะสร้างออปเจคได้
serial = new SerialPort(comportComboBox.SelectedItem.ToString(), 9600, Parity.None, 8, StopBits.One);
เราทำการเพิ่ม event handler ให้กับออปเจค เพื่อจะแยกโค๊ดไปเขียนการรับค่าทาง serial port
serial.DataReceived += new SerialDataReceivedEventHandler(serial_DataReceived); // พิมพ์ serial.DataReceived += แล้่วกด Tab 2 ครั้ง โปรแกรม Visual C# ide เขาจะสร้าง method serial_DataReceived ให้อัตโนมัติ
แล้วผมก็เขียนโค๊ดจัดการการรับข้อมูลใน event handler นี้
void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string d = serial.ReadLine();
int intBegin = d.IndexOf("#");
int intEnd = d.IndexOf("*");
int length = intEnd - (intBegin+1);
char[] ch = { ','};
raw = d;
data = d.Substring(intBegin + 1, length).Split(ch);
this.BeginInvoke(new updateAnalogLabel(updateLabel));
}
ส่วนการอัพเดทตัวเลขที่ได้รับมาไปที่ control ต่างๆบนฟอร์มนั้น เราต้องอาศัย delegate พังก์ชั่นจัดการในส่วนนี้ เพราะในระหว่างที่รับข้อมูลอยู๋นั้น มันไม่มีส่วนไหนของโปรแกรมไปอัพเดทข้อมูลบนฟอร์มเลย เราจึงต้องพึง delegate เพื่อทำ callback ฟังก์ชั่น
private delegate void updateAnalogLabel();
private void updateLabel()
{
analog1Label.Text = data[0];
analog2Label.Text = data[1];
analog3Label.Text = data[2];
serialRecieveTextBox.AppendText(raw);
}
ในส่วนของการส่งข้อมูลออกจากโปรแกรมไปทาง serial port ที่เราได้ตกลงกันไว้คือ โปรแกรม C# จะทำการส่งสถานะการกดปุ่มบนฟอร์ม เพื่อไปบอกให้ MCU ขับหลอด LED
private void sendStateButton()
{
string s = "#" + Convert.ToInt32(stateButton1).ToString() + "," + Convert.ToInt32(stateButton2).ToString() + "," + Convert.ToInt32(stateButton3).ToString() + "*";
if (serial != null)
{
if (serial.IsOpen)
{
serial.Write(s);
}
}
}
ผมอัพไว้ที่ dropboxแล้ว
https://dl.dropboxusercontent.com/u/65353188/easySerial2013.zip
อ้างอิง : SerialPort Class , Delegates Tutorial
หรืออ่านเต็มๆ ได้ที่นี่ครับ คลิก
1 ความคิดเห็น:
ถ้ามีข้อมูลที่ต้องการใส่ค่าผ่าน C# ไปยัง MCU ในที่นี้ต้องการให้อยู่ใน EEPROM โดยข้อมูลนี้เป็นตารางขนาด 30x30 เราจะสามารถใช้วิธีใดในการรับและส่งค่าไปยัง MCU ครับ
ขอคำแนะนำด้วยครับมือใหม่มากๆ
Post a Comment