Quantcast

Lập trình giao tiếp RS232 qua Matlab

Chào các bạn.

Mình xin tổng hợp lại một số bài viết của mình về lập trình giao tiếp RS232 trên PC bằng phần mềm Matlab.

I. Đối tượng Serial Object

Việc giao tiếp này cũng rất dễ dàng thực hiện, không có gì là quá cao siêu cả. Mình đã giao tiếp thành công rùi. Để test nó các bạn hãy đấu tắt 2 chân 2 và 3 (TX và RX) của cổng COM lại.
Đầu tiên mình sẽ đưa ra môt chương trình thật là đơn gian, thiết lập ít tham số, còn chi tiết về thiết lập tham số nó thế nào? ý nghĩa ra sao? thì sẽ nói sau, mình cứ làm đơn giản trước rùi phức tạp -> hiểu hết về thiết lập này sau.
Bài này mình giới thiệu cách tạo đối tượng, kết nối, viêt hàm callback.
Tạo đối tượng:
Chúng ta gõ lệnh và kết quả hiện luôn (nhớ là k có dấu ; ở cuối lệnh

>> s = serial('COM1')

   Serial Port Object : Serial-COM1

   Communication Settings
      Port:               COM1
      BaudRate:           9600
      Terminator:         'LF'

   Communication State
      Status:             closed
      RecordStatus:       off

   Read/Write State
      TransferStatus:     idle
      BytesAvailable:     0
      ValuesReceived:     0
      ValuesSent:         0

Như vậy đối tượng là Serial-COM1, tốc độ 9600,..

Tiếp theo, chúng ta xem các tham số của đối tượng như thế nào bằng lệnh get(s):

>> get(s)
    ByteOrder = littleEndian
    BytesAvailable = 0
    BytesAvailableFcn =
    BytesAvailableFcnCount = 48
    BytesAvailableFcnMode = terminator
    BytesToOutput = 0
    ErrorFcn =
    InputBufferSize = 512
    Name = Serial-COM1
    ObjectVisibility = on
    OutputBufferSize = 512
    OutputEmptyFcn =
    RecordDetail = compact
    RecordMode = overwrite
    RecordName = record.txt
    RecordStatus = off
    Status = closed
    Tag =
    Timeout = 10
    TimerFcn =
    TimerPeriod = 1
    TransferStatus = idle
    Type = serial
    UserData = []
    ValuesReceived = 0
    ValuesSent = 0

    SERIAL specific properties:
    BaudRate = 9600
    BreakInterruptFcn =
    DataBits = 8
    DataTerminalReady = on
    FlowControl = none
    Parity = none
    PinStatus = [1x1 struct]
    PinStatusFcn =
    Port = COM1
    ReadAsyncMode = continuous
    RequestToSend = on
    StopBits = 1
    Terminator = LF

Các bạn thấy là có rất nhiều tham số phải không? chúng ta ở đây quan tâm đến tham số: BytesAvailableFcn tham số này chưa thết lập. Tham số này chính là hàm callback mà nó sẽ gọi khi có byte nhận được ở bộ đệm nhận.Vậy chúng ta viết hàm này chính là viết hàm OnComm đáp ứng sự kiện ReceiveEvent như trong MSCOMM của MS vậy.

Thiết lập này phải thực hiện trước khi mở cổng để giao tiếp, nên chúng ta sẽ viết hàm callback trước. Bạn viết 1 m-file với tên Serial_Callback.m như sau:

function Serial_Callback(obj,event)
    ind = fscanf(obj)

Cú pháp của hàm callback như trên với obj là đối tượng kiểu Serial như trên. Hàm có tác dụng đọc dữ liệu và hiển thị luôn kết quả lên command window.

Chúng ta đưa tham số tên hàm vào cho đối tượng s của ta:

>> s.BytesAvailableFcn = @Serial_Callback;

Tiếp theo chúng ta bắt đầu giao tiếp:

>>fopen(s);
>>fprintf(s,"chao cac ban");

Sau đó các bạn xem kết quả thế nào, sau đó thử truyền các kí tự khác xem bằng lệnh fprintf(s,...), hoặc thử với vi xử lý xem cho nó truyền lên các bạn sẽ thấy rất hay.

Bạn không giao tiếp nữa thì đóng cổng lại:

>>fclose(s);

2. Chương trình RS232 Communication

Đây là  chương trình mình viết dùng GUI, đã test với mạch FPGA Spartan 3E rồi.

Cách dùng:

1/ Chọn tham số cho Rs232 rùi ấn nút Connect để bắt đầu kết nối với RS232 nhé.

2/ Nhập dữ liệu vào ô TX rùi nhấn nút Send để gửi dữ liệu.

3/ Để thay đổi tham số (tốc độ, ..) cho RS232 thì phải nhấn Disconnect trước rùi chỉnh tham số nhé. Sau đó quay lại bước 1.

Image may be NSFW.
Clik here to view.

Image may be NSFW.
Clik here to view.

Các bạn chú ý, đây là chương trình mình viết dưới dạng mở, tức là các bạn có thể thêm code vào các hàm để phục vụ mục đích của mình. Đó chính là các hàm ngắt nhận, ngắt gửi,...  BytesAvailableFcnCount là số byte nhận được trong bộ đệm nhận trước khi xảy ra ngắt nhận.

Các hàm đó là:

  • function ByteAvailable_Callback(obj, event)
  • function OutputEmpty_Callback(obj, event)
  • function Error_Callback (obj, event)
  • function PinStatus_Callback(obj, event)
  • function Timer_Callback (obj,event)
  • function BreakInterrupt_Callback(obj, event)
  • Khi các bạn muốn thao tác với dữ liệu vừa nhận được thì các bạn edit thêm code trong hàm sau:

    function ByteAvailable_Callback(obj, event)

    Các bạn hãy lấy chương trình này thử xem mình viết ra sao nào Image may be NSFW.
    Clik here to view.
    :D
    .

    Tải chương trình: RS232 Communication (1868)


    Hướng dẫn lập trình giao tiếp RS232 trên PC bằng Visual C++ 6.0

    Chào các bạn.

    Để cho website của mình thêm phong phú, nên mình cập nhật thêm một số tài liệu mà mình đã viết ở các diễn đàn điện tử. Có thể bản quyền vẫn thuộc về diễn đàn, nhưng mình nghĩ đây chỉ là sự chia sẻ cho những người chưa biết, chưa hiểu sâu về vấn đề đó nên chắc là cũng không có vấn đề gì.

    Đây là TUT mình viết từ năm thứ 3 trong chương trình đào tạo Moderator của www.picvietnam.com, hướng dẫn viết chương trình giao tiếp máy tính qua cổng RS232 bằng ngôn ngữ Visual C++ 6.0. Đã có nhiều thảo luận về vấn đề giao tiếp nối tiếp tại 2 diễn đàn:

    Ngô Hải Bắc, Serial Port - lập trình giao tiếp nối tiếp, www.dientuvietnam.net, 2005

    Ngô Hải Bắc, Giao tiếp RS232 trên PC bằng Visual Basic 6.0, www.dientuvietnam.net

    Phạm Thái Hòa, Terminal - chương trình cực cool để test cổng COM, www.dientuvietnam.net

    Ngô Hải Bắc, Giao tiếp RS232 trên PC qua Matlab, www.picvietnam.com

    Ngô Hải Bắc, Giao tiếp RS232 trên PC, www.picvietnam.com

    Mình xin gửi các bạn Tutorial này.

    Image may be NSFW.
    Clik here to view.

    TUT01.03.PVN.NOHB.100106.pdf

    Tạo file .exe cho giao diện GUI Matlab

    Chào các bạn.

    Sau khi các bạn đã biết cách để viết một giao diện GUI, biết cách dịch ra file .exe tự chạy trên một máy khác thì bây giờ mình kết hợp làm sao đây ??

    Bài này mình dịch một project GUI tương đối là nhiều thành phần: RS232 Communication đã được post trong bài Lập trình giao tiếp RS232 qua Matlab

    Bước 1: Thiết lập môi trường dịch (bước này bỏ qua nếu đã làm rồi )

    Bước 2: Gõ lệnh deploytool và vào menu File chọn New Project, chọn Standalone Application, chọn tên project và nơi lưu project.

    Image may be NSFW.
    Clik here to view.

    Giao diện Deployment Tool sẽ gồm có Main function, Other files và C/C++ files.

    Image may be NSFW.
    Clik here to view.

    Một project GUI sẽ gồm có 2 file .m và .fig và có thể thêm các file .m và .fig nếu gọi các figure khác. Như vậy file add vào trong Main Function là file .m là file chính sẽ chạy project GUI đó.

    Image may be NSFW.
    Clik here to view.

    Các bạn browse đến thư mục RS232 Communication và sẽ thấy nó chỉ cho phép chọn file .m. Ở đây mình phải chọn file RS232_Communication.m vì là file chính, còn modaldlg.m là file để mở cửa sổ yêu cầu chọn Yes, no.

    Tiếp tục, click chuột phải vào Other files, chọn Add files và add các file còn lại trong project (chỉ các file .m và .fig thôi).

    Image may be NSFW.
    Clik here to view.

    Xong xuôi thì giao diện sẽ ra như thế này:

    Image may be NSFW.
    Clik here to view.

    Bước 3: Dịch project

    Bây giờ là bước dịch, các bạn vào menu Tools -> Build (Ctr + B). Sau đó đi uống nước chờ nó dịch xong hehe. Cái này chờ lâu phết, đừng có nóng nhé. Không báo lỗi gì thì ok ngay.

    Image may be NSFW.
    Clik here to view.

    Xong vụ rồi thì vào thư mục \distrib sẽ thấy file .exe của mình. Nhấn thử vào chạy xem thế nào.

    Còn muốn đem sang máy khác thì phải đóng gói, vào Tools chọn Package (Ctr + P):

    Image may be NSFW.
    Clik here to view.

    Sang máy không cài Matlab thì copy đồng thời file package và McrInstaller vào một thư mục, chạy ngon lành luôn. Mình thử nghiệm rồi.

    Chạy nó sẽ ra thế này:

    Image may be NSFW.
    Clik here to view.

    Image may be NSFW.
    Clik here to view.

    RS232_Communication_exe.zip

    Mình có upload file .exe mà mình đã dịch làm bằng chứng he he.

    Vẽ đồ thị trong Matlab

    Mình đang làm đồ án về đề tài giao tiếp máy tính và vđk qua công com, mình có 1 thắc mắc mong được các bạn chỉ giáo: khi dữ liệu được truyền vào máy tính thì có sự kiện BytesAvailable, mình viết hàm serial_Callback() để đọc dữ liệu này như sau:

    function serial_CallBack(obj,event)
    inval=fread(obj,1);
    t=clock;
    load data;
    set(handles.edit1,'string',inval);

    axes(handles.axes1);
    plot(t(6),inval);

    Kết quả là cái edit1 hiển thị được số liệu nhận được, còn axes thì không làm gì cả, mà xuất hiện cái hình bên ngoài. Mode để nhận dữ liệu từ cổng com mình đặt là 'byte', các bạn chỉ giúp nha.

    Phan tich thuat toan: thuc hien lenh dieu khien tu PC qua RS232

    Chào các bạn.

    Không biết ai đã đọc bài viết của mình PIC16F887 – Điều khiển thời gian đóng cắt một led từ PC qua UART chưa. Trong này, mình có thực hiện đặt thời gian đóng cắt từ PC bằng lệnh với cú pháp.

    Txyzt#: trong đó  xyzt là thời gian tính theo hệ hexa.

    Đây là đoạn chương trình xử lý ngắt UART:

    void RxIntFcn(void){
    UART_Data = UART_Read();
    UART_PrChar(UART_Data);
    // Detect set time command
    // as format: Txy#
    switch (progress){
    case 0:                //Initialize
    if(UART_Data == 'T')
    progress = 1;
    else
    progress = 0;
    switch(UART_Data){
    case '1':
    //RB6       = 1;
    led1_cntL = 0x6F; // 1/9 s = 111 ms
    led1_cntH = 1;
    break;
    case '2':
    //RB6       = 1;
    led1_cntL = 0xDE; // 2/9
    led1_cntH = 0;
    break;
    case '3':
    //RB5      = 1;
    led1_cntL = 0x4D;    // 1s = 1000 = 0x03E8
    led1_cntH = 0x1;
    break;
    case '4':
    //RB5      = 1;
    led1_cntL = 0xBC;    // 5s = 5000 = 0x1388
    led1_cntH = 0x01;
    break;
    case '5':
    //RB5      = 1;
    led1_cntL = 0x2B;    // 5s = 5000 = 0x1388
    led1_cntH = 0x02;
    break;
    case '6':
    //RB5      = 1;
    led1_cntL = 0x9A;    // 5s = 5000 = 0x1388
    led1_cntH = 0x02;
    break;
    case '7':
    //RB5      = 1;
    led1_cntL = 0x09;    // 5s = 5000 = 0x1388
    led1_cntH = 0x03;
    &
    #160;                   break;
    case '8':
    //RB5      = 1;
    led1_cntL = 0x78;    // 5s = 5000 = 0x1388
    led1_cntH = 0x03;
    break;
    case '9':
    //RB5      = 1;
    led1_cntL = 0xE7;    // 5s = 5000 = 0x1388
    led1_cntH = 0x03;
    break;
    case '0':
    //RB5      = 1;
    led1_cntL = 0xE8;    // 5s = 5000 = 0x1388
    led1_cntH = 0x03;
    break;
    default:
    PORTB   &= 0x80;
    };
    break;
    case 1:                // Received 'T' character
    // Determind next state
    if (ishexa(UART_Data) == 1){
    progress = 2;
    // Write data to acc1
    acc1     = ascii2num(UART_Data);
    }
    else{
    UART_PrString(" Command error");
    progress = 0;
    };
    break;
    case 2:                // Received 'x' character
    if (ishexa(UART_Data) == 1){
    progress = 3;
    // Write data to acc2
    acc2     = ascii2num(UART_Data);
    }
    else{
    UART_PrString(" Command error");
    progress = 0;
    };
    break;
    case 3:                // Received 'x' character
    if (ishexa(UART_Data) == 1){
    progress = 4;
    // Write data to acc2
    acc3     = ascii2num(UART_Data);
    }
    else{
    UART_PrString(" Command error");
    progress = 0;
    };
    break;
    case 4:                // Received 'x' character
    if (ishexa(UART_Data) == 1){
    progress = 5;

    ;            // Write data to acc2
    acc4     = ascii2num(UART_Data);
    }
    else{
    UART_PrString(" Command error");
    progress = 0;
    };
    break;
    case 5:
    if (UART_Data == '#'){
    progress = 0;
    // Write 'OK' statement
    UART_PrString(" Timer is set");
    // Update data from ACC to led1_counter_acc
    led1_cnt_acc1 = (acc1<<4) | acc2;
    led1_cnt_acc2 = (acc3<<4) | acc4;
    }
    else{
    UART_PrString(" Command error");
    progress = 0;
    };
    break;
    default: progress = 0;
    break;
    };

    // On, off command
    switch(UART_Data){
    case 'P':        // On led
    // Update led1_counter
    led1_cntH = led1_cnt_acc1;
    led1_cntL = led1_cnt_acc2;
    break;
    case 'S':
    // Clear led1_counter content
    led1_cntH = 0;
    led1_cntL = 0;
    break;
    };
    }

    Thuật toán mình sử dụng rất đơn giản: dùng một biến progress là biến quá trình. Mặc định giá trị này là 0, khi nhận dc đúng kí tự T thì biến sẽ có giá trị = 1. Khi đó, nó sẽ kiểm tra tiếp theo có phải gõ vào là chữ số từ 0 đến 9, và từ A đến F hay không.Mỗi trạng thái, khi nhận đúng đều chuyển từ giá trị string sang giá trị số, ví dụ: kí tự ‘0’ chuyển thành giá trị unsigned char là 1. Xem hàm này trong hàm system.h. Nếu đúng thì progress tiếp tục tăng đến trạng thái kiểm tra tiếp theo, nếu không nó sẽ báo lỗi “Command Error” gửi lên PC.

    Tiếp tục, đến cuối cùng khi nhận xong kí tự # thì tức là đã nhận đúng lệnh và thực hiện gán dữ liệu để lấy ra byte cao và byte thấp của giá trị nhập vào.

    Đây là hàm system.h

    bit ishexa(unsigned char a){
    if ((a >= ‘0′ && a<= ‘9′) || (a>= ‘A’ && a<= ‘F’))
    return 1;
    else return 0;
    };

    // Convert from ASCII to number
    unsigned char ascii2num(unsigned char a){
    if( a >= ‘0′ && a<= ‘9′)
    return (a-’0′);
    else
    return (a-’A’ + 0×0A);
    }

    Hi vọng phân tích của mình làm các bạn hiểu được cách để thực hiện các lệnh điều khiển từ PC hiệu quả.

    Chúc các bạn thành công.

    Serial Port Complete Second Edition

    Homepage: http://lvr.com/

    Image may be NSFW.
    Clik here to view.

    Chào các bạn.

    Sau khi phiên bản thứ nhất của cuốn Serial Port Complete ra đời thì bây giờ tác giả Jan Axelson lại cho ra đời phiên bản thứ 2. Chúng ta hãy xem lời giới thiệu và content của tài liệu này.

    From the Introduction

    When I wrote the first edition of this book, the RS-232 serial port was the workhorse of PC interfaces. Modems and scores of other peripherals connected to PCs via the serial ports that were present on every machine. Read more.

    Contents

    Introduction
    Acknowledgments
    1 Options and Choices
    2 Formats and Protocols
    3 COM Ports on PCs
    4 Inside RS-232
    5 Designing RS-232 Links
    6 Inside RS-485
    7 Designing RS-485 Links and Networks
    8 Going Wireless
    9 Using .NET’s SerialPort Class
    10 Managing Ports and Transfers in .NET
    11 Ports for Embedded Systems
    12 Network Programming
    13 An RS-485 Network
    14 Inside USB
    15 Using Special-function USB Controllers
    16 Using Generic USB Controllers
    Index

    Detailed contents

    Xem chi tiết thêm tại: http://lvr.com/spc.htm

    Hồi năm thứ 3 khi mình nghiên cứu về lập trình RS232 thì đọc tài liệu này đầu tiên, tài liệu nói khá đầy đủ. Sau đó có viết một vài bài trên dientuvietnam dựa trên tài liệu này với một phần là dịch ở đây ra Image may be NSFW.
    Clik here to view.
    Big Grin
    .

    Vì vậy, mình khuyên bạn nào học giao tiếp RS232 nên đọc tài liệu này trước nhé.

    Tài liệu này có bản quyền, nên khuyến khích các bạn mua nhé. Riêng với sinh viên thì có thể lấy ở chỗ này

    Book Information

    Price: $39.95
    380 pages
    Publication date: Dec. 2007
    ISBN 978-1931448-06-2