serial port

21
Lập trình Serial Port trong nhiều môi trường I- Các thông số cơ bản a. Tốc độ: 300, 1200, 2400, 9600, 19200 .. . Chú ý khi thiết lập tốc đố của cổng Comm và thiết bị ghép nối phải bằng nhau, nếu không dẫn đến dữ liệu trả về sẽ bị sai lệch. b. Bít dữ liệu ( Data bits) 7 ( ASCII), 8 ( 1 byte) c. Phương thức kiểm tra lỗi ( Parity) Các phương thức bao gồm none (N), odd (O), even (E), mark (M), hoặc space (S).

Upload: doanthienminh10832925

Post on 27-Oct-2014

228 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Serial Port

Lập trình Serial Port trong nhiều môi trường

I- Các thông số cơ bảna. Tốc độ: 300, 1200, 2400, 9600, 19200 .. . Chú ý khi thiết lập tốc đố của cổng

Comm và thiết bị ghép nối phải bằng nhau, nếu không dẫn đến dữ liệu trả về sẽ bị sai lệch.

b. Bít dữ liệu ( Data bits)7 ( ASCII), 8 ( 1 byte)

c. Phương thức kiểm tra lỗi ( Parity)Các phương thức bao gồm none (N), odd (O), even (E), mark (M), hoặc space (S).

d. Stop bits =1 e. Luồng điều khiển ( Flow Control )f. Bắt tay ( Handshaking )

Page 2: Serial Port

II- Tool và ví dụ

a.Visual Basic 6.0

i. Giới thiệuVisual Basic 6.0 là ngôn ngữ lập trình cơ bản và dễ dàng nhất để tiếp cận việc lập trình giao tiếp truyền thống qua cổng nối tiếp. Cho nên bài này sẽ hướng dẫn chi tiết cách tạo 1 phần mềm cơ bản có thể giao tiếp được với các thiết bị khác qua cổng Comm

ii. Đưa control MSComm.ocx vào form design

iii. Lập trình giao tiếp

b.Visual C++ 6

i. Giới thiệu

ii. Lập trình1. Sử dụng class CSerialPort2. Cầu hính cổng3. Gửi và nhận dữ liệu4. Xử lý sự kiện

Page 3: Serial Port

c.DotNET 2003 ( C# )

i. Giới thiệu sơ qua về ngôn ngữDotNET là bước cải tiến đáng nể về ngôn ngữ lập trình do Microsoft

cung cấp. Trong phiên bản này (chạy dưới nền Framework 1.1) không có sẵn lớp (managed class) để thực hiện giao tiếp với cổng Comm. Chính vì thế đã có nhiều hãng thứ 3 cung cấp dưới dạng ActiveX các module giao tiếp với cổng Comm, tuy nhiên với giá thành chưa hợp lý cho sinh viên Việt Nam. Chính vì thế tôi xin giới thiệu một phương pháp ít tốn kém hơn đó là sử dụng lại ActiveX MS Communications Control của bộ Visual Studio 6.0 . Khi Add component vào project, .NET sẽ sử dụng Platform Invoke ( P/Invoke) để chuyển .ocx thành unmanaged class.

ii. Thêm đối tượng MSComm1. Tạo mới Window Form 2. Thêm đối tượng MSComm.ocx vào project3. Gán đối tượng vào form design

iii. Ý nghĩa các thông số1. com.CommPort

a. Gán hoặc lấy tên cổng nối tiếp ( VD COM1,COM2)

Page 4: Serial Port

2. com.PortOpena. Đóng hoặc mở cổng nối tiếp

3. com.Rthresholda. Thiết lập số ký tự tối thiểu từ cổng nối tiếp để sự kiện OnComm

thực hiện (quan trọng)4. com.InputMode

a. Xác định kiểu dữ liệu nhận về là text hoặc binary, sử dụng hằng MSCommLib.InputModeConstants

5. com.Settingsa. Thiết lập “baud,d,p,s” trong đó baud = baud rate, p = parity, d =

# data bits, and s = # stop bits .Ví dụ : “9600,8,n,1”6. com.Handshaking

a. Xác định kiểu bắt tay sử dụng hằng MSCommLib.HandshakeConstants

7. com.InBufferCounta. Trả về số ký tự trong bộ đệm nhận ( receive buffer)

8. com.Inputa. Lấy và xóa bộ đệm nhận, trả về là chuỗi nếu InputMode là text

hoặc trả về là mảng byte nếu InputMode là binary9. com.Output

a. Gửi dữ liệu ra cổng Comm10. com.CommEvent

Page 5: Serial Port

a. Trả về các thông báo của đối tượng MSComm thông qua các hằng MSCommLib.CommEventConstants, MSCommLib.ErrorConstants, MSCommLib.OnCommConstants

11. com.NullDiscarda. Nếu thiết lập = true thì cổng nối tiếp sẽ bỏ qua ký tự null ( 0x00)

và ngược lại .12. com.InputLen

a. Xác định số ký tự khi lệnh Input đọc từ bộ đệm nhận, mặc định 0 là lấy tất cả.

13. OnComm Eventa. Sự kiện xảy ra khi có dữ liệu trong bộ đệm nhận hoặc gửi, chú ý

sự kiện chỉ xảy ra khi thiết lập Rthreshod >0 hoặc Sthreshod >0.b. Ví dụ

public MyForm(){ InitializeComponents(); // Initialize Form Components com.RThreshold = 1; // Sự kiện OnComm xảy ra khi dữ liệu trong bộ đệm nhận

Page 6: Serial Port

là 1 com.OnComm += new System.EventHandler(this.OnComm); // Gán handler cho sự kiện}

private void OnComm(object sender, EventArgs e){ if (com.InBufferCount > 0) ProcessData((string) com.Input); if (com.CommEvent == MSCommLib.OnCommConstants.comEvCTS) Console.WriteLine("CTS Line Changed");

iv. Gửi và nhận dữ liệu1. Gửi dữ liệu ra cổng Comm

a. Theo định dạng text

Page 7: Serial Port

i. Ví dụcom.Output=”@S01#”

b. Theo định dạng binaryi. Ví dụ

com.Output = new byte[] {0, 0x41, (byte) 'A', 255};2. Nhận dữ liệu ở cổng Comm

a. Chú ýi. Dữ liệu nhận về từ cổng Comm không dễ dàng quản lý. Ví

dụ : Để nhận được chuỗi “Viet Nam” thì cổng Comm có thể nhận thành nhiều gói như “Vie” “t N” và “am” chẳng hạn. Do đó ta phải sử dụng các phương pháp phù hợp để nhận dữ liệu.Sau đây là 3 cách phổ biến

b. Nhận dữ liệu theo frame ( có bit start và bit stop )i. Với dữ liệu được đóng khung trước khi gửi thì chỉ khi nào

có đủ bit start và bit stop thì mới xác định đâu là 1 frame.ii. Ví dụ: Ta quy định bit start “@” bit stop “#”.Đoạn code sau

minh họa chi tiết

using System.Text.RegularExpressions;private string ComBuffer = "";

Page 8: Serial Port

private void OnComm(object sender, EventArgs e{ // Nhận dữ liệu từ cổng Comm ComBuffer += (string) com.Input; // Tạo một regular expression Regex r = new Regex("@.*?#"); // Cycle through the matches for (Match m = r.Match(ComBuffer); m.Success; m = m.NextMatch()) { Console.WriteLine(m.Value); // Xóa chuỗi đã dọc khỏi buffer ComBuffer = ComBuffer.Replace(m.Value, ""); }}

c. Nhận dữ liệu theo khoảng thời gian nhất định

Page 9: Serial Port

i. Nếu xác định chính xác khoảng thời gian cho từng gói dữ liệu thì có thể áp dụng phương pháp này

ii. Ví dụ:

using System.Timers;private string ComBuffer = "";private Timer tmrWaitData = new Timer();private void ExtraInitCode(){ // Khoảng thời gian cho từng gói dữ liệu tmrWaitData.Interval = 1000; // Sự kiện khi thời gian thay đổi tmrWaitData.Elapsed += new ElapsedEventHandler(tmrWaitData_Elapsed);}private void OnComm(object sender, EventArgs e{ // Kiểm tra dữ liệu trong bộ đệm if (com.InBufferCount > 0) { // Nhận dữ liệu vào biến ComBuffer += (string) com.Input; tmrWaitData.Stop(); // Reset

Page 10: Serial Port

timer tmrWaitData.Start(); }}private void tmrWaitData_Elapsed(object sender, ElapsedEventArgs e){ Console.WriteLine("Data Packet: " + ComBuffer tmrWaitData.Stop();}

d. Nhận dữ liệu theo kích thước nhất địnhi. Thiết lập Rthreshod bừng kích thước của gói dữ liệu.

d.DotNET 2005 (C#)

i. Giới thiệuPhiên bản DotNET tiếp theo này đã khắc phục được sự thiếu sót giao

tiếp với cổng Comm

Page 11: Serial Port

ii. Đối tượng SerialPort

e.Java

i. Giới thiệuKhác với các ngôn ngứ ở trên đều do hãng Microsoft cung cấp, Java được

phát triển bởi hãng Sun , Java với thế mạch trong môi trường mạng.. Để giao tiếp với các thiết bị nhúng cũng như để thực hiện truyền thống hãng Sun cung cấp gói mở rộng Java Communications 3.0 API (javax.comm)

ii. Java Communications 3.0 API

InterfaceCommDriver Driver cho truyền thốngCommPortOwnershipListener

Sự kiện cho truyền thông cơ bản

ParallePortEventListener

Sự kiện cho truyền thông qua cổng //

SerialPortEventListener

Sự kiện cho truyền thông qua cổng nối tiếp

Page 12: Serial Port

ClassCommPort Cổng truyền thôngCommPortIdentifier Quản lý cổng truyền thôngParallePort Cổng song songParallePortEvent Sự kiện cho cổng song songSerialPort Cổng nối tiếpSerialPortEvent Sự kiện cho cổng nối tiếp

ExceptionNoSuchPortException

Xảy ra khi không tìm thấy cổng xác định

PortInUseException Xảy ra khi cổng đã được sử dụng

UnSupportedCommOpereationException

Driver không hỗ trợ phương thức này ( function)

iii. Lập trình1. Cấu hình cổng

Page 13: Serial Port

private SerialPort sPort;

sPort.portName = “1”;sPort.baudRate = 9600;sPort.flowControlIn = SerialPort.FLOWCONTROL_NONE;sPort.flowControlOut = SerialPort.FLOWCONTROL_NONE;sPort.databits = SerialPort.DATABITS_8;sPort.stopbits = SerialPort.STOPBITS_1;sPort.parity = SerialPort.PARITY_NONE;

2. Đóng mở cổng

import javax.comm.*;private CommPortIdentifier portId;private SerialPort sPort;//Tạo đối tượng cổng nối tiếptry {portId =

Page 14: Serial Port

CommPortIdentifier.getPortIdentifier(“1”);} catch (NoSuchPortException e) {throw new SerialConnectionException(e.getMessage());}//Mở cổng nối tiếptry {sPort = (SerialPort) portId.open("BKSerial", 30000);} catch (PortInUseException e) {throw new SerialConnectionException(e.getMessage());}// Thiết lập notifyOnDataAvailable cho phép sự kiện khi nhận

sPort.notifyOnDataAvailable(true);

// Thiết lập notifyOnBreakInterrup cho phép sự kiện khi dừng

sPort.notifyOnBreakInterrupt(true);

// Thiết lập timeout nhậntry { sPort.enableReceiveTimeout(30);} catch

(UnsupportedCommOperationException e) {}

Page 15: Serial Port

//Đóng cổngsPort.close();

3. Gửi và nhận

private OutputStream os;private InputStream is;os = sPort.getOutputStream();is = sPort.getInputStream();

4. Sự kiện khi có dữ liệu trong bộ đêm cổng Comm

public void serialEvent(SerialPortEvent e) {

StringBuffer inputBuffer = new StringBuffer();

int newData = 0;switch (e.getEventType()) {case SerialPortEvent.DATA_AVAILABLE:

Page 16: Serial Port

while (newData != -1) { try {

newData = is.read(); if (newData == -1) {

break; }

if ('\r' == (char) newData) {

inputBuffer.append('\n');} else {inputBuffer.append((char)

newData);}

} catch (IOException ex) {

System.err.println(ex); return;

} case SerialPortEvent.BI:

//BREAK RECEIVED }

}