You are on page 1of 78

Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.

03 
Ngày:  10/01/06  Trang:  1/78 

Tutorial no 01.02 
 
Gửi đến:  Đoàn Hiệp, Doãn Minh Đăng, Huỳnh Châu Thuận  
picvietnam@googlegroups.com
Nội dung:  Lập trình giao tiếp máy tính qua cổng RS232.. 
  MICROSOFT WORD
 
Tóm tắt: 
Vấn giao tiếp giữa PC và vi điều khiển rất quan trong trong các ứng dụng điều khiển, đo lường,.. 
trong thực tế.  
Do đó tôi xin giới thiệu cho các bạn viết chương trình trên PC dùng MSComm. Tôi xin đưa ra một 
số vấn đề như sau:  
‐ Giới thiệu chuẩn giao tiếp  RS232  và  điều khiển Active X Microsoft Communication 6.0( 
MSComm): cách tính chất và cách thiết lập tham số tối ưu cho điều khiển. 
‐ Lập trình ứng dụng giao tiếp trên cơ sở sử dụng phần mềm Visual C++ trong bộ công cụ Visual ‐ 
Studio 6.0 của Microsft: 
+ Thiết kế giao diện chương trình. 
+ Viết mã cho chương trình. 
 

1. Điều khiển MSComm 
1.1. Chuẩn giao tiếp RS232 
RS232 là một chuẩn giao tiếp nối tiếp dùng định dạng không đồng bộ, kết nối nhiều 
nhất là với 2 thiết bị, chiều dài kết nối lớn nhất cho phép để đảm bảo dữ liệu là 50 – 100 feet 
( 12.7 đến 25.4 m), tốc độ 20kBít/s đôi khi là tốc độ 115 k Bít/s với một số thiết bị đặc biệt.  
Để biết được các tham số của chuẩn giao tiếp RS232 trong hệ điều hành của bạn như thế 
nảo thì bạn kích phải chuột vào biểu tượng My Computer , chọn Properties, chọn Tab 
HardWare chọn Device Manager sẽ có một tree hiện ra. Bạn chọn Port( Com & LPT), kích 
chuột phải vào Communication Port( COM1). Chuyển sang tab Port Setting sẽ thấy được 
các tham số mà chúng ta cần thiết lập bao gồm tần số bus, Data Bits, Parity Bits, Stop Bits, 
Handshaking,..  
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  2/78 

 
Hình 1.1: Chọn My Computer ‐> Properties 
 

 
Hình 1.2: Chọn Device Manager 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  3/78 

 
Hình 1.3: Chọn Properties của Communication Port( COM1) 
 

 
Hình 1.4: Chọn thẻ Port Setting để biết tham số  
Đó chính là lí do tại sao tôi lại chọn các tham số đưa vào trong các ComboBox như ở 
dưới chương trình này. 
 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  4/78 

 
1.2. Các thuộc tính của MSComm 
MSComm là một điều khiển ActiveX dùng trong truyền thông nối tiếp. Các tính chất 
của điều khiển này được dùng để thiết lập giao tiếp với các thiết bị ngoại vi qua cổng 
RS232. Do đó tôi xin giới thiệu với các bạn điều khiển này trong Visual Basic vì cách gọi 
thuộc tính đơn giản của VB. Từ đó sẽ lấy làm cơ sở để lập trình trên Visual C++. 
1.2.1. Điều khiển MSComm trong Visual Basic 
Tất cả các tính chất này bạn có thể tìm tại thư viện MSDN July 2001 theo đường dẫn 
như sau ở tab contents: 
MSDN Library ‐  July 2001 / Visual Tools and Languages/ Visual Studio 6.0 
Documentation / Visual Basic Documentation / Reference/  Control Reference / ActiveX 
Control/ MSComm Control 
Các tính chất của MSComm được sắp xếp theo chức năng:  
Thiết lập tham số cho cổng:  
+ CommID: trả lại handles đồng nhất tới thiết bị truyền thông, có kiểu Long. Tính chất 
này không có lúc thiết kế mà chỉ có khi thi hành, thuộc tính này là ReadOnly.  
+ CommPort: dạng object.CommPort = value. Value là chỉ số của cổng Com có giá trị từ 
1 ‐> 16 và mặc định có giá trị =1. Các bạn cần phải thiết lập thông số này trước khi mở cổng. 
Sẽ có lỗi error 68 (Device unavailable) nếu như không mở được cổng này. 
 + InBuferSize: thiết lập hoặc trả lại kích thước của bộ đệm nhận, tính = byte. Mặc định 
là 1024 byte. Các bạn không được nhầm lẫn với đặc tính InBufferCount là số byte đang 
chờ trong bộ đệm nhận. 
+ InputLen : object.InputLen [ = value ] thiết lập hoặc trả lại số  byte mỗi lần thuộc tính 
Input đọc trong bộ đệm nhận. Mặc định giá trị Value=0 tức là thuộc tính Input sẽ đọc hết 
nội dung của bộ đệm nhận khi thuộc tính này được gọi. Nếu số kí tự trong bộ đệm nhận 
không = InputLen thì thuộc tính Input sẽ trả lại kí tự rỗng “”. Ví thế bạn cần phải chọn 
cách kiểm tra InBufferCount để chắc chắn số kí tự yêu cầu đã có đủ trước khi dùng lệnh 
.Input. Tính chất này rất là có ích khi đọc dữ liệu một máy mà dữ liệu ra được định dạng 
bằng các khối có kích thước cố định. 
 + InputMode: object.InputMode [ = value ] .  
Value = 0 hay = comInputModeText dữ liệu nhận được dạng văn bản kiểu kí tự theo 
chuẩn ANSI. Dữ liệu nhận được sẽ là một sâu.  
      Value=1 hay = comInputModeBinary dùng nhận mọi kiểu dữ liệu như kí tự điều khiển 
nhúng, kí tự NULL,.. Giá trị nhận được từ Input sẽ là một mảng kiểu Byte. 
+ NullDiscard: object.NullDiscard [ = value ] tính chất này quyết định kí tự trống có 
được truyền từ cổng đến bộ đệm nhận hay không. Nếu value= True kí tự này không được 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  5/78 

 
truyền. value = false kí tự trống sẽ được truyền. Kí tự trống được định nghía theo chuẩn 
ASCII là kí tự 0 – chr$(0). 
+ OutBuferSize: giống như InBuferSize, mặc định là 512.  
+ ParityReplace: thiết lập và trả lại kí tự thay thế  kí tự không đúng trong lỗi giống 
nhau. 
+ PortOpen: thiết lập và trả lại tính trạng của cổng(đóng hoặc mở). 
 object.PortOpen [ = value ]. value = true cổng mở. value =false cổng đóng và xóa toàn 
bộ dữ liệu trong bộ đệm nhận và truyền. Cần phải thiết lập thuộc tính CommPort đúng với 
tên của cổng trước khi mở cổng giao tiếp. Thêm vào đó, cổng giao tiếp của thiết bị của bạn 
phải hỗ trợ giá trị trong thuộc tính Setting thì thiết bị của bạn mới hoạt động đúng, còn 
không thì nó sẽ hoạt động rất dở hơi nếu không nói là nó chạy không tốt. Đường DTR và 
RTS luôn giữ lại trạng thái của cổng.  
+ RthresHold: object.Rthreshold [ = value ] value kiểu số nguyên. Thiết lập số kí tự 
nhận được trước khi gây lên sự kiện comEvReceive. Mặc định = 0 tức là không có sự kiện 
OnComm khi nhận được dữ liệu. Thiết lập = 1 tức là sự kiện OnComm xảy ra khi bất kì kí 
tự nào được chuyển đến bộ đệm nhận. 
+ Settings: object.Settings [ = value ] thiết lập hoặc trả lại các thông số tần số baud, bít 
dữ liệu, bít chẵn lẻ, bít stop. Nếu Value không có giá trị khi mở sẽ gây ra lỗi 380 (Invalid 
property value).  
+ SThreshold: thiết lập và và trả lại số kí tự nhỏ nhất được cho phép trong bộ đệm gửi 
để xảy ra sự kiện OnComm = comEvSend . Theo mặc định giá trị này = 0 tức là khi truyền 
sẽ không gây ra sự kiện OnComm. Nếu thiết lập thông số này =1 thì sự kiện OnComm xảy 
ra khi bộ đệm truyền rỗng. Sự kiện OnComm = comEvSend chỉ xảy ra khi mà số kí tự 
trong bộ đệm truyền nhỏ hơn hoặc = Sthreshold. Nếu số kí tự trong bộ đệm này luôn lớn 
hơn Sthreshold thì sự kiện này không thể xảy ra. 
Truyền nhận dữ liệu:  
+ CommEvent: trả lại phần lớn sự kiện giao tiếp hoặc có lỗi. CommEvent xảy ra khi có 
lỗi hoặc khi xảy ra sự kiện nào đó. Sau đây là một số hằng số lỗi:  

Sự kiện  Giá trị  Miêu tả sự kiện 

comEventBreak  1001  Xảy ra khi nhận được một tín hiệu Break. 

comEventFrame  1004  Lỗi hệ thống. Phần cứng phát hiện ra một lỗi hệ thống 

comEventOverrun  1006  Xảy ra khi cổng tự tràn( Overrun). Một kí tự không được 


đọc từ phần cứng trước khi kí tự tiếp theo tới và do đó kí tự 
này bị mất. 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  6/78 

 
comEventRxOver  1008  Xảy ra khi bộ đệm nhận bị tràn. Không có đủ chỗ cho dữ 
liệu trong bộ đệm nhận. 

comEventRxParity  1009  Lỗi Parity. Phần cứng phát hiện ra một lỗi Parity. 

comEventTxFull  1010  xảy ra khi bộ đệm truyền bị đầy. Bộ đệm truyền bị đầy 


trong khi ghi dữ liệu lớn vào bộ đệm 

comEventDCB  1011  Một lỗi không mong muốn khi đang khôi phục lại khỗi 


điều khiển thiết bị( DCB – Device Control Block)  cho cổng 

                            
Một số sự kiện :  
 

Sự kiện  Giá trị  Miêu tả sự kiện 

comEvSend  1  Xảy ra khi số kí tự trong bộ đệm truyền nhỏ hơn giá trị 
SthresHold. 

comEvReceive  2  Xảy ra khi bộ đệm nhận được số kí tự bằng giá trị 
RthresHold. Sự kiện này được tạo ra liên tục cho tới khi bạn 
dùng thuộc tính Input để  lấy hết dữ liệu từ trong bộ đệm 
nhận. 

RcomEvCTS  3  Xảy ra khi có  thay đổi trong đường CTS( Clear To Send) 

comEvDSR  4  Xảy ra khi  thay đổi trong đường DSR( Data Set Ready). Sự 
kiện này chỉ xảy ra khi đường DSR thay đổi từ 1 ‐> 0. 

comEvCD  5  Xảy ra khi có thay đổi trong đường CD( Carrier Detect) 

comEvRing  6  Phát hiện chuông (Ring).Một số UART không hỗ trợ sự 
kiện này. 

comEvEOF  7  Xảy ra khi nhận được kí tự kết thúc file ( kí tự 26 trong 
bảng mã ASCII)  
 

+ EOFEnable : object.EOFEnable [ = value ] quyết định các hành động nếu MSComm 
tìm thấy kí tự kết thúc file. Nếu value=true khi tìm thấy kí tự kết thúc file thì sẽ gây lên sự 
kiện comEvEOF trong OnCommEvent. Nếu value= false thì sẽ không gây lên sự kiện này. 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  7/78 

 
+ InBufferCout: trả lại số kí tự đang có trong bộ đệm nhận Bạn có thể xoá bộ đệm nhận 
bằng cách đặt thuộc tính này =0 . Không nhầm với thuộc tính InBufferSize là tổng kích 
thước của bộ đệm nhận. 
+ Input: nhận và xoá dữ liệu trong bộ đệm nhận. 
Nếu InputMode là comInputModeText  thì giá trị trả về sẽ là một xâu tức có kiểu 
String , dữ liệu dạng text trong một biến kiểu Variant. Nếu InputMode = 
comInputModeBinary thì thuộc tính này sẽ trả lại dữ liệu dạng nhị phân dưới dạng một 
mảng kiểu byte trong một biến Variant. 
+ OutBufferCount: trả lại số kí tự trong bộ đệm truyền. 
+ Output: ghi dữ liệu vào bộ đệm truyền. có thể truyền kiểu text hoặc kiểu nhị phân. 
Nếu truyền bằng kiểu text thì cho một biến Variant = kiểu String, nếu truyền kiểu nhị phân 
thì cho cho Output= variant = một mảng kiểu Byte. 
Bắt tay( handshaking):  
+ Break : thiết lập hoặc xoá tín hiệu. object.Break [ = value] value = true hoặc false. Khi 
set value= true thì thông số Break này sẽ gửi một tín hiệu break. Tín hiệu break trì hoàn 
việc truyền dữ liệu và đưa đường truyền vào trạng thái break tới khi mà value = false. 
+ CDHolding: quết định xem sự truyền này đến đâu bằng cách truy vấn đường CD( 
Carrier Detect). Carrier Detect là tín hiệu gửi từ modem tới máy tính kết nối với nó thống 
báo rằng nó đang online. Nếu giá trị = true thì nó đường CD đang ở mức cao, nếu = false 
thì đường dây này đang ở mức thấp. Tính chất này không có trong lúc thiết kế chỉ có trong 
khi chạy chương trình.Carrier Detect được biết như là Receive Line Signal Detect (RLSD). 
+ CTSHolding: quết định khi nào bạn gửi dữ liệu bằng cách truy vấn trạng thái đường 
Clear To Send (CTS). Thông thường tín hiệu CTS được gửi từ modem tới máy tính kết nối 
với nó để báo rằng đang quá trình truyền dữ liệu. Thuộc tính Readonly chỉ xuất hiện khi 
chạy chương trình. Đường Clear To Send dùng trong RTS/CTS (Request To Send/Clear To 
Send) bắt tay phần cứng. CTSHolding cho bạn một cách để tự tay dò đường Clear To Send 
nếu bạn cần biết trạng thái của nó.  
+ DSRHolding: biết trạng thái của đường Data Set Ready (DSR). Tín hiệu Data Set 
Ready truyền từ modem tới máy tính nối với nó để thông báo rằng modem đã sẵn sàng 
hoạt động. Tính chất này dùng khi viết Data Set Ready/Data Terminal Ready handshaking 
routine cho máy Data Terminal Equipment (DTE)‐ máy trang bị đầu cuối dữ liệu. 
+ DTREnable: tính chất này quyết định khi nào cho phép đường Data Terminal Ready 
(DTR) trong truyền thông. Tín hiệu DTR gửi từ máy tính tới modem đẻ báo rằng máy tính 
sẵn sàng là nơi nhận dữ liệu. Khi DTREnable = true thì đường Data Terminal Ready set lên 
cao khi cổng mở, và thấp khi cổng đóng. Nếu DTREnable = false thì đường đó luôn mức 
thấp. Trong phần lớn trường hợp set đường Data Terminal Ready thành thấp để hang up 
telephone.  
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  8/78 

 
+ Handshaking: thiết lập và trả lại giao thức bắt tay phần cứng. object.Handshaking [ = 
value ]. 
Các giá trị của value:  
 

comNone     0  (Mặc định) Không bắt tay 

comXOnXOff  1  Bắt tay XON/XOFF 

comRTS     2  Bắt tay RTS/CTS (Request To Send/Clear To Send)  

comRTSXOnXOff  3  Dùng cả bắt tay Request To Send and XON/XOFF 

 
   Handshaking chỉ là giao thức truyền thông nội tại quyết định bởi dữ liệu nào được 
truyền từ cổng phần cứng tới bộ đệm nhận. Khi kí tự của dữ liệu tới cổng nối tiếp, thiết bị 
truyền thông sẽ chuyển nó vào trong bộ đệm nhận và chương trình của bạn có thể đọc 
chúng. Nếu không có bộ đệm dữ liệu hoặc chương trình của bạn cần đọc kí tự trực tiếp từ 
phần cứng , bạn có thể mất dữ liệu bởi vì kí tự từ phần cứng đến rất nhanh. Giao thức 
Handshaking đảm bảo dữ liệu không bị mất, khi dữ liệu đến cổng quá nhanh thì thiết bị 
truyền thông sẽ chuyển dữ liệu vào trong bộ đệm nhận.  
+ RTSEnable: quết định khi nào cho phép đường Request To Send (RTS), Tín hiệu RTS 
từ máy tính tới modem để yêu cầu được tryền dữ liệu. Khi RTSEnable = true thì đường 
RTS mức cao khi cổng mở, tích mức thấp khi cổng đóng. Và hiển nhiên khi RTSEnable thì 
đường RTS luôn mức thấp.RTS dùng trong RTS/CTS hardware handshaking. RTSEnable 
cho phép bạn dò đường RTS khi cần biết tình trạng của đường này.  
       Các tính chất trên không có lúc thiết kế giao diện mà chỉ có lúc chạy chương trình ( 
dùng trong viết code). 
1.1.2. Điều khiển MSComm trong Visual C++ 
       Trên đây là các tham số của điều khiển MSComm trong VB.  
Trong Visual C++ , mỗi một điều khiển được định nghĩa trong một lớp riêng. Và 
MSComm cũng không phải là ngoại lệ.  
Với các tham số ở trên các bạn hoàn toàn có thể áp dụng rất là tốt cho lập trình với 
VC++ bởi lẽ các tham số này bạn có thể lấy giá trị hoặc thiết lập tham số cho chúng tương 
ứng bằng các hàm thành viên cửa lớp như Get_thuộctính hoặc Set_thuộctính. 
Ví dụ, bạn muốn thiết lập dùng cổng COM1 chẳng hạn thì dùng thuộc tính CommPort 
ở trên và chỉ thêm tiền tố Set_ nếu muốn thiết lập và Get_  nếu muốn lấy giá trị này. 
Sau đây là lớp MSComm là một lớp kế thừa từ lớp cở sở CWnd, các bạn có thể tham 
khảo. Các bạn chú ý về các kiều dữ liệu cửa các tham số và giá trị trả về của các hàm. Việc 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  9/78 

 
chuyển đổi giữa các kiểu dữ liệu này các bạn có thể tham khảo tại  thư viện MSDN 
Microsoft July 2001 bằng cách Search 
Key Word: chính là các từ khoá chỉnh là các kiểu dữ liệu đó.( như CString,…) 
 
class CMSComm : public CWnd 

protected: 
  DECLARE_DYNCREATE(CMSComm) 
public: 
  CLSID const& GetClsid() 
  { 
    static CLSID const clsid 
    = { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } }; 
    return clsid; 
  } 
  virtual BOOL Create(LPCTSTR lpszClassName, 
    LPCTSTR lpszWindowName, DWORD dwStyle, 
    const RECT& rect, 
    CWnd* pParentWnd, UINT nID, 
    CCreateContext* pContext = NULL) 
  { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); 

 
    BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, 
    const RECT& rect, CWnd* pParentWnd, UINT nID, 
    CFile* pPersist = NULL, BOOL bStorage = FALSE, 
    BSTR bstrLicKey = NULL) 
  { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, 
    pPersist, bStorage, bstrLicKey); } 
 
// Attributes 
public: 
 
// Các phép toán 
public: 
  void SetCDHolding(BOOL bNewValue); 
  BOOL GetCDHolding(); 
  void SetCommID(long nNewValue); 
  long GetCommID(); 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  10/78 

 
  void SetCommPort(short nNewValue); 
  short GetCommPort(); 
  void SetCTSHolding(BOOL bNewValue); 
  BOOL GetCTSHolding(); 
  void SetDSRHolding(BOOL bNewValue); 
  BOOL GetDSRHolding(); 
  void SetDTREnable(BOOL bNewValue); 
  BOOL GetDTREnable(); 
  void SetHandshaking(long nNewValue); 
  long GetHandshaking(); 
  void SetInBufferSize(short nNewValue); 
  short GetInBufferSize(); 
  void SetInBufferCount(short nNewValue); 
  short GetInBufferCount(); 
  void SetBreak(BOOL bNewValue); 
  BOOL GetBreak(); 
  void SetInputLen(short nNewValue); 
  short GetInputLen(); 
  void SetNullDiscard(BOOL bNewValue); 
  BOOL GetNullDiscard(); 
  void SetOutBufferSize(short nNewValue); 
  short GetOutBufferSize(); 
  void SetOutBufferCount(short nNewValue); 
  short GetOutBufferCount(); 
  void SetParityReplace(LPCTSTR lpszNewValue); 
  CString GetParityReplace(); 
  void SetPortOpen(BOOL bNewValue); 
  BOOL GetPortOpen(); 
  void SetRThreshold(short nNewValue); 
  short GetRThreshold(); 
  void SetRTSEnable(BOOL bNewValue); 
  BOOL GetRTSEnable(); 
  void SetSettings(LPCTSTR lpszNewValue); 
  CString GetSettings(); 
  void SetSThreshold(short nNewValue); 
  short GetSThreshold(); 
  void SetOutput(const VARIANT& newValue); 
  VARIANT GetOutput(); 
  void SetInput(const VARIANT& newValue); 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  11/78 

 
  VARIANT GetInput(); 
  void SetCommEvent(short nNewValue); 
  short GetCommEvent(); 
  void SetEOFEnable(BOOL bNewValue); 
  BOOL GetEOFEnable(); 
  void SetInputMode(long nNewValue); 
  long GetInputMode(); 
}; 
Các bạn xem kĩ các hàm, các phép toán trên có thể  thấy là kiểu dữ liệu dùng làm tham 
số cho hàm hay giá trị trả về của các hàm hầu hết là các kiểu dữ liệu cơ bản như BOOL, 
short,.. Chỉ đặc biết là có kiểu dữ liệu VARIANT. 
VARIANT là một cấu trúc mà dữ liệu nó chứa là một kiểu union được định nghĩa như 
sau: 
   
typedef struct FARSTRUCT tagVARIANT VARIANT;
typedef struct FARSTRUCT tagVARIANT VARIANTARG;

typedef struct tagVARIANT {


VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
Byte bVal;
Short iVal;
long lVal;
float fltVal;
double dblVal;
VARIANT_BOOL boolVal;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
DECIMAL FAR* pdecVal
IUnknown FAR* punkVal;
IDispatch FAR* pdispVal;
SAFEARRAY FAR* parray;
Byte FAR* pbVal;
short FAR* piVal;
long FAR* plVal;
float FAR* pfltVal;
double FAR* pdblVal;
VARIANT_BOOL FAR* pboolVal;
SCODE FAR* pscode;
CY FAR* pcyVal;
DATE FAR* pdate;
BSTR FAR* pbstrVal;
IUnknown FAR* FAR* ppunkVal;
IDispatch FAR* FAR* ppdispVal;
SAFEARRAY FAR* FAR* pparray;
VARIANT FAR* pvarVal;
void FAR* byref;
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  12/78 

 
char cVal;
unsigned short uiVal;
unsigned long ulVal;
int intVal;
unsigned int uintVal;
char FAR * pcVal;
unsigned short FAR * puiVal;
unsigned long FAR * pulVal; // VT_BYREF|VT_UI4.
int FAR * pintVal;
unsigned int FAR * puintVal;
};
};
  
 
Các bạn để  ý thấy rằng kiểu VARIANT dùng làm tham số cho hàm SetInput và là kiểu 
trả về của hàm GetOutput. Mà với kiểu truyền kiểu dạng Text chúng ta truyền dữ liệu ra 
cổng là dạng xâu kí tự thì chúng ta chuyển đối giữ kiểu VARIANT sang kiểu kí tự CString 
như thế nào? 
‐ Chuyển từ kiểu CString ‐> VARIANT: tôi dùng lớp ColeVariant ( các bạn có thể tra 
trong MSDN dùng tab Index) là dạng đóng gói của kiểu cấu trúc VARIANT, lớp này có 
hàm khởi tạo COleVariant( CString& strSrc );  và do đó nó có thể làm tham số cho hàm 
SetInput của MSComm. Vì vậy chúng ta chỉ cần khai báo một biến ColeVariant là xong. 
 
CString data_tosend = “Example”; 
CodeVariant temp(data_tosend); 
m_mscomm1.SetInput(temp); 
 
‐ Chuyển từ kiểu VARIANT sang kiểu CString. Các bạn xem lại định nghĩa cấu trúc 
VARIANT ở trên xem có biến nào có kiểu trả về kiểu tương thích với kiểu CString( tức có 
thể ép kiểu để trở thành kiểu CString). 
Tôi thấy có thành phần 
                                      BSTR                    bstrVal;     
 
Do đó ta chỉ việc ép kiểu là xong. 
 
VARIANT data; 
CString m_strData = (CString) data.bstrVal; 
 
 
 
 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  13/78 

 
1.3. Cách thiết lập tối ưu cho ứng dụng 
Để  cho ứng dụng có thể đọc ngay dữ liệu khi bắt đầu có trong bộ đệm nhận thì các bạn 
nên đặt thuộc tính RthresHold = 1. 
Ngoài ra các bạn cần quan tâm đến các tham số: CommPort, Settings, Rthreshold, 
SthresHold,PortOpen, InputLen, InputBuffer, OutputBuffer, InBufferSize, InputMode, 
OutBufferSize. 
 
2. Lập trình 
2.1. Mục đích yêu cầu 
Chương trình này rất là đơn giản. Chúng ta sẽ tạo ra một chương trình có giao diện như 
sau: 

 
Hình 2.1: Giao diện chương trình 
   Chương trình có chức năng sau: 
‐ Nhập kí tự hoặc xâu kí tự vào EditBox Transfer, điều chỉnh tham số giao tiếp trên 
các ComboBox. Nhấn nút Send để gửi dữ liệu ra cổng COM.  
‐ Đồng thời với nó nếu có dữ liệu truyền vê cổng Com thì dữ liệu sẽ được hiển thị 
lên EditBox Receive. Khi bạn nhấn vào Clear thì sẽ xoá dữ liệu hiển thị trên EditBox này. 
Chú ý: 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  14/78 

 
Để có thể test luôn chương trình các bạn nối tắt chân 2 và chân 3 của RS232 lại với nhau 
chính là nối chân RxD và TxD để chúng ta truyền dữ liệu ra RS232 sau đó nhận dữ liệu 
luôn. Đây là ví dụ test đơn giản không có bắt tay phần cứng. 

Hình 2.2: Sơ đồ đấu chân của RS232 

2.2. Thiết kế giao diện cho chương trình  

2.2.1. Tạo dự án “RS232TUT” 

Khởi động Visual C++, chọn New từ menu File 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  15/78 

Hình 2.3: Chọn New từ menu file 

Hình 2.4: Chọn MFC Application(exe), tên dự án, nơi chứa dự án 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  16/78 

Hình 2.5: Chọn Dialog based 

Hình 2.6: Nhấn Next tiếp tục 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  17/78 

Hình 2.7: chọn như mặc định, nhấn Next luôn 

Hình 2.8: Kích finish để kết thúc việc tạo dự án 

Giao diện của ứng dụng ban đầu như sau:  
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  18/78 

Hình 2.9: Giao diện ban đầu 

2.2.2. Thêm điều khiển ActiveX  Microsoft Communication 6.0 

Đầu tiên bạn dùng nút Delete xoá 2  nút OK,Cancel và dòng văn bản tĩnh TODO 

Từ menu Project chọn Add to Project. Menu con hiện ra bạn chọn Components 
and Controls: 

Hình 2.10: Chọn Components Controls 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  19/78 

 
Hộp thoại Components and Control Gallery xuất hiện bạn chọn Regestered 
ActiveX Controls(đây là thư mục chứa các điều khiển ActiveX): 

Hình 2.11: Chọn thư mục đầu tiên 

Trong thư mục Registered ActiveX Controls bạn chọn điều khiển mà mình cần 
Microsoft Communications Control, version 6.0. Kích OK 

Hình 2.12: Chọn Microsoft Communication Control, version 6.0 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  20/78 

 
Hộp thoại yêu cầu bạn xác nhận có thêm điều khiển này vào không, chọn OK 

Hình 2.13: Chọn OK để thêm điều khiển  

Khi đó chúng ta sẽ có được một lớp mới CMSComm là lớp dẫn xuất của lớp cơ 
sở CWnd. Lớp này được khai báo trong file MSComm.h và định nghĩa trong file 
MSComm.cpp 

Hình 2.14: Chọn tên lớp, tên header file, file thực thi như mặc định 

Nhấn Close để đóng hộp thoại 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  21/78 

Hình 2.15: Đóng cửa sổ Components and Controls Gallery 

Bạn thêm điều khiển MSComm vào hộp giao diện bằng cách gắp thả như với các 
điều khiển thông thường khác 

Hình 2.16: Thêm điều khiển MSComm 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  22/78 

 
Thế là các bạn đã cho được ứng dụng MSComm vào trong Dialog 

2.2.3. Thêm các điều khiển khác 

2.2.3.1. Thêm các Group Box 

Hình 2.17: Thêm GroupBox1 

Hình 2.18: Thêm GroupBox2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  23/78 

Hình 2.19: Thêm GroupBox3 

Hình 2.20: Thêm GroupBox4 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  24/78 

Hình 2.21: Thêm GroupBox5 

Hình 2.22: Thêm GroupBox6 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  25/78 

Hình 2.23: Thêm GroupBox7 

Hình 2.24: Thêm GroupBox8 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  26/78 

Hình 2.25: Thêm GroupBox9 

Thay đổi thuộc tính cho GroupBox1: 

 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  27/78 

 
Hình 2.26: Kích chuột vào GroupBox1 chọn Properties 

Hình 2.27: Thiết lập thuộc tính Caption: Settings 

Các bạn làm tương tự với các GroupBox khác, theo hình vẽ dưới đây: 

Hình 2.28: Thiết lập thuộc tính cho GroupBox2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  28/78 

Hình 2.30: Thiết lập thuộc tính cho GroupBox3 

Hình 2.31: Thiết lập thuộc tính cho GroupBox4 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  29/78 

Hình 2.32: Thiết lập thuộc tính cho GroupBox5 

Hình 2.33: Thiết lập thuộc tính cho GroupBox6 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  30/78 

Hình 2.34: Thiết lập thuộc tính cho GroupBox7 

Hình 2.34: Thiết lập thuộc tính cho GroupBox8 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  31/78 

Hình 2.35: Thiết lập thuộc tính cho GroupBox9 

Tiếp theo các bạn làm cho các GroupBox 4‐>9 có kích thước bằng nhau và căn lề đẹp hơn 

Hình 2.36: Làm cho các GroupBox có cùng kích thước 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  32/78 

Hình 2.37 Làm cho các GroupBox 7‐>9 có khoảng cách bằng nhau 

Hình 2.38: Làm cho các GroupBox này thẳng hàng với nhau 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  33/78 

Hình 2.39: Kết quả sau khi làm cho cùng kích thước 

2.2.3.2. Thêm các EditBox 

Hình 2.40: Thêm EditBox1 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  34/78 

Hình 2.41: kích chuột phải, chọn Properties  

Hình 2.42: Thiết lập ID cho EditBox1 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  35/78 

Hình 2.43: Thiết lập thuộc tính ReadOnly và MultiLine 

Hình 2.44: Thêm EditBox2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  36/78 

Hình 2.45: Chọn Properties 

Hình 2.46: Thuộc tính của EditBox 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  37/78 

 
2.2.3.3. Thêm các Button 

Hình 2.47: Thêm Button1 

Hình 2.48: Thêm Button2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  38/78 

Hình 2.49: Thêm Button3 

Hình 2.50: Tạo 3 Button có cùng kích thước 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  39/78 

Hình 2.51: Chọn Properties 

Hình 2.52: Thuộc tính của Button1 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  40/78 

Hình 2.53: Thuộc tính của Button2 

Hình 2.54: Thuộc tính của Button3 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  41/78 

 
2.2.3.4. Thêm các ComboBox 

Hình 2.55: Thêm ComboBox1 

Hình 2.56: Thêm ComboBox2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  42/78 

Hình 2.57: Thêm ComboBox3 

Hình 2.58: Thêm ComboBox4 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  43/78 

Hình 2.59: Thêm ComboBox5 

Hình 2.60: Thêm ComboBox6 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  44/78 

Hình 2.61: Tạo cho các comboBox có cùng chiều rộng 

Chú ý:  Riêng với ComboBox thì các bạn phải kéo sao cho chiều cao của điều 
khiển phải đủ lớn để chứa các dữ liệu nằm trong nó sau này nếu không thì bạn sẽ 
chẳng thấy nó hiển thị gì hoặc là sẽ thấy có thanh cuộn. Tốt nhất là kéo dài thoải mái 
đi.  

Để điều chỉnh chiều cao của các ComboBox như sau:  

Di chuột đến ComboBox để con trỏ chuột nằm trên nút xổ xuống của điều khiển 
sau đó kích chuột trái 1 lần. Khi đó bạn sẽ có thể co dãn chiều cao của ComboBox 
thoải mái 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  45/78 

Hình 2.62: Co dãn chiều dài của ComboBox 

Tiếp theo, thiết lập các tham số cho các ComboBox 

Hình 2.63: Chọn thuộc tính Properties của ComboBox1 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  46/78 

Hình 2.64: Thuộc tính ID của Combo1 

Hình 2.65: Thuộc tính ID của Combo3 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  47/78 

Hình 2.66: Thuộc tính ID của Combo5 

Hình 2.67: Thuộc tính ID của Combo2 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  48/78 

Hình 2.68: Thuộc tính ID của ComboBox 4 

Hình 2.69: Thuộc tính ID của ComboBox6 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  49/78 

Hình 2.70: Thuộc tính Type: DropList của các ComboBox chung 

Các bạn sau kiểm tra các thuộc tính của các điều khiển bằng bảng sau: 

STT  Đối tượng  Thuộc tính  Thiết lập 


1  MSComm  ID  IDC_MSCOMM1 

2  ComboBox  ID  IDC_COMBO_COMPORT 


Style  Droplist 
3      IDC_COMBO_BITRATE 
Droplist 
4      IDC_COMBO_DATABIT 
Droplist 
5      IDC_COMBO_PARITYBIT 
Droplist 
6      IDC_COMBO_STOPBIT 
Droplist 
7      IDC_COMBO_HANDSHAKING 
Droplist 
8  Button  ID  IDC_BUTTON_CLEAR 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  50/78 

 
Caption  &Clear 
9      IDC_BUTTON_SEND 
&Send 
10      IDC_BUTTON_EXIT 
&Exit 
11  EditBox  ID  IDC_EDIT_RECEIVE 
Style  Read Only( check) 
12      IDC_EDIT_TRANSFER 
13  Group Box  ID  IDC_STATIC 
Settings 
14      IDC_STATIC 
Receive 
15      IDC_STATIC 
Trasfer 
2.3. Viết mã cho chương trình 

2.3.1. Thêm các biến, các hàm thành viên 

Để viết mã cho chương trình thì các bạn cần phải thêm các biến cho các điều 
khiển. Từ menu View chọn Class Wizard. Chọn tab MemberVariables. Chọn lớp 
CRS232TUTDlg 

Hình 2.71: Chọn MFCClassWizard tab Member Variables, chọn AddVariable.. 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  51/78 

 
Xin lấy ví dụ thêm biến m_cboBitRate cho điều khiển có ID là 
IDC_COMBO_BITRATE 

Hình 2.72: Thêm biến điều khiển cho ComboBox BitRate 

Các bạn thêm các biến cho các điều khiển tương tự như trên. Sau đây là hình minh hoạ 
việc thêm các biến này: 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  52/78 

Hình 2.73: Thêm biến điều khiển cho ComboBox ComPort 

Hình 2.74: Thêm biến điều khiển cho ComboBox Data Bit 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  53/78 

Hình 2.75: Thêm biến điều khiển cho Combo Handshaking 

Hình 2.76: Thêm biến điều khiển cho Combo Parity Bit 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  54/78 

Hình 2.77: Thêm biến điều khiển cho Combo Stop Bit 

Hình 2.78: Thêm biến giá trị cho Edit Box Receive 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  55/78 

Hình 2.79: Thêm biến giá trị cho EditBox Transfer 

Hình 2.80: Thêm biến điều khiển cho MSComm 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  56/78 

Hình 2.81: Kết quả cuối cùng trong của sổ MFC..  

Thêm các hàm thành viên:  

Đã xong phần thêm các biến. Bây giờ các bạn sẽ thêm một số hàm như sau:  

void InitComboBox(void)   dùng khởi tạo cho các ComboBox 

void Setting(void)     thiết lập tham số cho MSComm 

CString getCurStrInCombobox(const CComboBox &a)  

: hàm này dùng để lấy xâu đang được lựa chọn trong các ComboBox 

Để làm được điều đó thì các bạn làm như sau: Chọn tab Class.. Kích chuột phải 
vào lớp CRS232TUTDlg chọn Add Member Function:   
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  57/78 

Hình 2.82: Chọn tab Class trong cửa sổ Workspace 

 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  58/78 

Hình 2.83: Kích chuột phải chọn Add Member Function 

Hình 2.84: Thêm hàm getCurStrInCombobox , chọn OK 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  59/78 

Hình 2.85: Làm tương tự, thêm hàm InitComboBox 

Hình 2.86: Thêm hàm Settings() 

2.3.2. Viết mã cho từng hàm 

Chúng ta sẽ viết mã lệnh cho một số hàm 

2.3.2.1. Hàm getCurStrInCombobox: hàm có tác dụng lấy giá trị được chọn 
của các ComboBox 

Các bạn kích vào cửa sổ bên trái chọn tab Class, kích đúp chuột vào tên hàm, bên 
phải sẽ hiện ra nơi định nghĩa hàm, các bạn thêm mã vào. 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  60/78 

 
 
Hình 2.87: Kích đúp vào tên hàm getCurStrInCombobox  bên trái để định nghĩa hàm 
 
Thêm mã chương trình: 
 
CString CRS232TUTDlg::getCurStrInCombobox(const CComboBox &a) 

    CString str; 
    a.GetLBText(a.GetCurSel(),str); 
    return str; 

2.3.2.2. Hàm InitComboBox: dùng khởi tạo các giá trị cho ComboBox 

Kích đúp chuột vào hàm InitComboBox( hàm này dùng khởi tạo các giá trị cho 
ComboBox) trong của sổ bên trái tương tự như với hàm trên.  
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  61/78 

Hình 2.88: Kích đúp vào tên hàm InitComboBox 

Các bạn thêm đoạn mã này vào hàm: 

void CRS232TUTDlg::InitComboBox() 

    // ComboBox ComPort 
    m_cboComPort.ResetContent(); 
    m_cboComPort.AddString(ʺCOM1ʺ); 
    m_cboComPort.AddString(ʺCOM2ʺ); 
    m_cboComPort.SetCurSel(0); 
    // ComboBox BitRate 
    m_cboBitRate.ResetContent(); 
    m_cboBitRate.InsertString(0,ʺ600ʺ); 
    m_cboBitRate.InsertString(1,ʺ1200ʺ); 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  62/78 

 
    m_cboBitRate.InsertString(2,ʺ2400ʺ); 
    m_cboBitRate.InsertString(3,ʺ4800ʺ); 
    m_cboBitRate.InsertString(4,ʺ9600ʺ); 
    m_cboBitRate.InsertString(5,ʺ14400ʺ); 
    m_cboBitRate.InsertString(6,ʺ19200ʺ); 
    m_cboBitRate.InsertString(7,ʺ28800ʺ); 
    m_cboBitRate.InsertString(8,ʺ38400ʺ); 
    m_cboBitRate.InsertString(9,ʺ56000ʺ); 
    m_cboBitRate.InsertString(10,ʺ57600ʺ); 
    m_cboBitRate.InsertString(11,ʺ115200ʺ); 
    m_cboBitRate.InsertString(12,ʺ128000ʺ); 
    m_cboBitRate.InsertString(13,ʺ256000ʺ); 
    m_cboBitRate.SetCurSel(4); 
    // ComboBox Data Bit 
    m_cboDataBit.ResetContent(); 
    m_cboDataBit.AddString(ʺ5ʺ); 
    m_cboDataBit.AddString(ʺ6ʺ); 
    m_cboDataBit.AddString(ʺ7ʺ); 
    m_cboDataBit.AddString(ʺ8ʺ); 
    m_cboDataBit.SetCurSel(3); 
    // ComboBox Stop Bit 
    m_cboStopBit.ResetContent(); 
    m_cboStopBit.AddString(ʺ1ʺ); 
    m_cboStopBit.AddString(ʺ1.5ʺ); 
    m_cboStopBit.AddString(ʺ2ʺ); 
    m_cboStopBit.SetCurSel(0); 
    // ComboBox Parity Bit 
    m_cboParityBit.ResetContent(); 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  63/78 

 
    m_cboParityBit.InsertString(0,ʺNoneʺ); 
    m_cboParityBit.InsertString(1,ʺOldʺ); 
    m_cboParityBit.InsertString(2,ʺEvenʺ); 
    m_cboParityBit.InsertString(3,ʺMarkʺ); 
    m_cboParityBit.InsertString(4,ʺSpaceʺ); 
    m_cboParityBit.SetCurSel(0);  // mặc định chọn None 
    // ComboBox Handshaking 
    m_cboHandshaking.ResetContent(); 
    m_cboHandshaking.InsertString(0,ʺNoneʺ); 
    m_cboHandshaking.InsertString(1,ʺXON/XOFFʺ); 
    m_cboHandshaking.InsertString(2,ʺRTSʺ); 
    m_cboHandshaking.InsertString(3,ʺRTS/CTS + XON/XOFFʺ); 
    m_cboHandshaking.SetCurSel(0); 

Các bạn hoàn toàn có thể thêm dữ liệu ban đầu bằng cách kh ác kích chuột phải 
lên ComboBox chọn Properties ‐ > chọn tab Data, sau đó thì nhập giá trị vào , sau 
mỗi dòng ấn tổ hợp phím Ctr + Enter để xuống dòng nhập tiếp theo. 

Hình 2.89: Thêm dữ liệu bằng tay 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  64/78 

 
2.3.2.3. Hàm Settings: dùng thiết lập các tham số cho MSComm 

Bạn kích đúp vào hàm Settings ( hàm này dùng thiết lập các tham số cho 
MSComm) 

Hình 2.90: Kích đúp chuột vào tên hàm Settings bên trái  

Thêm đoạn mã vào hàm 

void CRS232TUTDlg::Settings() 
{     
    // nếu cổng đã mở thì đóng cổng để thiết lập tham số 
    if( m_mscomm.GetPortOpen())  
        m_mscomm.SetPortOpen(false); 
    // Thiết lập tên cổng  
    m_mscomm.SetCommPort(m_cboComPort.GetCurSel()+ 1);   
    // Thiết lập bắt tay 
    m_mscomm.SetHandshaking(m_cboHandshaking.GetCurSel());  
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  65/78 

 
    // Thiết lập tần số, bit dữ liệu, bít stop 
    CString strBitRate = getCurStrInCombobox(m_cboBitRate); 
    CString strParity =  getCurStrInCombobox(m_cboParityBit); 
    CString strDataBit =  getCurStrInCombobox(m_cboDataBit); 
    CString strStopBit =   getCurStrInCombobox(m_cboStopBit); 
    CString strSetting; 
  strSetting.Format(ʺ%s,%c,%s,%sʺ,strBitRate,strParity[1],strDataBit,strStopBit); 
    m_mscomm.SetSettings(strSetting); 
                      // Thiết lập khác 
    m_mscomm.SetRThreshold(1);   
    m_mscomm.SetInputLen(1); // mỗi lần đọc một kí tự 
    m_mscomm.SetInBufferSize(1024); 
    m_mscomm.SetInputMode(0); // 0 – Text Mode , 1‐ Binary Mode 
    m_mscomm.SetOutBufferSize(1024); 
    m_mscomm.SetPortOpen(true);  // mở cổng 

2.3.2.4. Hàm khởi tạo cho hộp thoại 

Hàm OnInitDialog() hàm này nằm trong lớp CRS232TUTDialog, ứng dụng sẽ 
load các thiết lập của bạn trong hàm này ngay khi chạy. 

Đầu tiên bạn phải thêm hàm này vào bằng cách mở MFC ClassWizard(ấn tổ hợp 
phím Ctr + W), chọn tab Message Maps: 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  66/78 

Hình 2.91: Thêm hàm InitDialog 

Tiếp theo, bạn kích vào Edit Code , khung bên phải của VC++ sẽ hiện ra hàm 
OnInitDialog()để bạn thêm code vào: 

Hình 2.92: Chọn EditCode để viết thêm vào hàm 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  67/78 

 
Thêm đoạn mã này vào: 

BOOL CRS232TUTDlg::OnInitDialog(){ 

……………………………. 

  // TODO: Add extra initialization here 

  InitComboBox();  

  return TRUE;  // return TRUE  unless you set the focus to a control 

2.3.2.5. Các hàm cho các nút Button đáp ứng sự kiện Click: 

Các bước làm cũng hoàn toàn tương tự như trên: thêm hàm, viết mã lệnh cho 
hàm  

  Hàm OnButtonExit() 

Hình 2.93: Thêm hàm cho nút Exit 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  68/78 

Hình 2.94: Đồng ý với tên hàm là OnButtonExit 

Hình 2.95: Nhấn EditCode để viết mã cho hàm 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  69/78 

Hình 2.96: Cửa sổ code hiện ra để thêm code 

   

void CRS232TUTDlg::OnButtonExit()  

  // TODO: Add your control notification handler code here 

           // Nếu cổng còn mở thì đóng lại 

  if  ( m_mscomm.GetPortOpen() ) 

      m_mscomm.SetPortOpen(false); 

  OnOK(); 

 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  70/78 

 
Hàm OnButtonSend:  

Hình 2.97: Thêm hàm cho nút Send 

Hình 2.98: Đồng ý với tên hàm là OnButtonSend 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  71/78 

Hình 2.99: Nhấn EditCode để viết hàm 

Hình 2.100: Cửa sổ thêm code 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  72/78 

 
void CRS232TUTDlg::OnButtonSend()  

  // TODO: Add your control notification handler code here 
  UpdateData(); 
  Settings(); 
  // send data 
  m_mscomm.SetOutput((COleVariant)m_strTransfer); 
  UpdateData(false); 

Hàm OnButtonClear:  

Hình 2.101: Thêm hàm cho nút Clear 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  73/78 

Hình 2.102: Đồng ý với tên hàm là OnButtonClear 

Hình 2.103: Cửa sổ thêm code 

void CRS232TUTDlg::OnButtonClear()  

  // TODO: Add your control notification handler code here 
  UpdateData(); 
  m_strReceive = ʺʺ; 
  UpdateData(false); 

Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  74/78 

 
Hàm OnOnCommMscomm1: ở đây tôi chỉ dùng một ngắt là ngắt nhận, các bạn 
có thể dùng các ngắt khác tuỳ ý của mình. 

Do tôi thiết lập InputLen = 1, nên mỗi lần chỉ nhận một kí tự, các bạn có thể dùng 
điều này để kiểm tra thông tin nhận từ vi điều khiển, ví dụ một kí tự báo hiệu chẳng 
hạn 

Hình 2.104: Thêm hàm cho MSComm1 

Hình 2.105: Đồng ý với tên hàm là OnOnCommMscomm1 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  75/78 

Hình 2.106: Cửa số thêm mã 

void CRS232TUTDlg::OnOnCommMscomm1()  

  // TODO: Add your control notification handler code here 
  UpdateData(); 
  switch( m_mscomm.GetCommEvent()){ 
  case 1: // comEvSend 
    break; 
  case 2://  comEvReceive 
    VARIANT  data = m_mscomm.GetInput(); 
    m_strReceive += (CString)data.bstrVal; 
    break; 
  case 3:// comEvCTS 
    break; 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  76/78 

 
  case 4://comEvDSR 
    break; 
  case 5: //comEvCD 
    break; 
  case 6://comEvRing 
    break; 
  case 7: //comEvEOF 
    break; 
  }; 
  UpdateData(false); 

Thế là xong. Bây giờ các bạn dịch( nếu có lỗi thì sửa lại cho đúng) và chạy 
chương trình để xem kết quả mình thế nào. 

Hình 2.107: Dịch chương trình 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  77/78 

Hình 2.108: Kiểm tra sửa lỗi chương trình đến khi không có lỗi 

Hình 2.109: Chạy chương trình 
Người báo cáo:  Ngô Hải Bắc  Tài liệu:  TUT01.03 
Ngày:  10/01/06  Trang:  78/78 

Hình 2.110: Ứng dụng khi chạy 

Bạn đánh một vài kí tự vào trong ô Transfer thiết lập tham số và truyền thử để 
kiểm tra chương trình. 

3. Tài liệu tham khảo 

‐ Phạm Công Ngô ‐ Phạm Ngọc Nam ‐ Phạm Tuấn Lương ‐ Tự học lập trình 
Visual C++ 6.0 từ cơ bản đến nâng cao 

‐ Microsoft Corporation ‐ MSDN July – 2001  

‐ Jan Axelson – Serial Por Complete Programming and Circuits for RS‐232 and RS 
– 485 Links and Networks 

‐ http://codeproject.com 

‐ http://microsoft.com/MSDN 

You might also like