PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Cơ bản về vi điều khiển và PIC (http://www.picvietnam.com/forum/forumdisplay.php?f=8)
-   -   giao tiếp cổng com đơn gian (http://www.picvietnam.com/forum/showthread.php?t=693)

111985 19-10-2006 12:03 PM

giao tiếp cổng com đơn gian
 
Giao tiếp cổng COM bằng VC++ nếu dùng ActiveX MSCOM thì sẽ rất phức tạp trong vấn đề truyền tham biến. Dưới đây là đoạn code ghi và đọc cổng COM đơn giản dùng hàm API CreateFile() để đọc hay đưa dữ liệu ra cổng COM của máy tính.

Header file comm.h


CODE

// Comm.h: interface for the CComm class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_COMM_H__06AC286E_CEFA_11D6_B591_00C04 F4C504A__INCLUDED_)
#define AFX_COMM_H__06AC286E_CEFA_11D6_B591_00C04F4C504A__ INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define READ_TIMEOUT 2500 // milliseconds
class CComm
{
private:
HANDLE m_hCom; // Device handle
BOOL fWaitingOnRead;
OVERLAPPED m_ov; // A structure that contains informations which are // used in asynchronous input and output operations
public:
CComm(VOID);
CComm (LPCSTR lpszPortNum);
~CComm(){ Close(); }
VOID Close(VOID);
BOOL Open (LPCSTR lpszPortNum = "com1");
DWORD WriteData (LPCVOID pdata, DWORD len);
DWORD ReadData (LPVOID pdest, DWORD len);
};

#endif // !defined(AFX_COMM_H__06AC286E_CEFA_11D6_B591_00C04 F4C504A__INCLUDED_)





Implimentation


CODE

// Comm.cpp: implementation of the CComm class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Comm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CComm::CComm(VOID)
{
fWaitingOnRead=FALSE;
m_hCom = 0;
ZeroMemory(&m_ov, sizeof(m_ov));
}
VOID CComm::Close (VOID)
{
}
CComm::CComm(LPCSTR lpszPortNum)
{
fWaitingOnRead=FALSE;
m_hCom = 0;
ZeroMemory(&m_ov, sizeof(m_ov));
Open(lpszPortNum);
}
BOOL CComm::Open (LPCSTR lpszPortNum )
{
DCB dcb;
BOOL bSuccess;

m_hCom = CreateFile(lpszPortNum, // pointer to name of the file
GENERIC_READ | GENERIC_WRITE, // access mode
0, // comm devices must be opened w/exclusive-access
NULL, // no security attrs
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL); // hTemplate must be NULL for comm devices

if ( m_hCom == INVALID_HANDLE_VALUE )
{
return FALSE;
}

//
// Omit the call to SetupComm to use the default queue sizes.
// Get the current configuration.
//

bSuccess = GetCommState(m_hCom, &dcb);

if ( ! bSuccess )
{
CComm::Close();
return FALSE;
}
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
bSuccess = SetCommState(m_hCom, &dcb);

if ( ! bSuccess )
{
CComm::Close();
return FALSE;
}
PurgeComm(this->m_hCom ,PURGE_RXCLEAR | PURGE_TXCLEAR);
return TRUE;
}
DWORD CComm::ReadData(LPVOID pdest,DWORD len)
{
DWORD dwRes;
DWORD dwRead;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL) return 0;
if (!fWaitingOnRead){
if (!ReadFile(m_hCom , pdest , len, &dwRead, &osReader)) {
if (GetLastError() != ERROR_IO_PENDING) {
return 0;
}
else{
fWaitingOnRead = TRUE;
}
}
else{
return dwRead;
}
}
if (fWaitingOnRead) {
dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);
switch(dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(m_hCom , &osReader, &dwRead, FALSE)){
return 0;
}
else{
fWaitingOnRead = FALSE;
return dwRead;
}
break;
case WAIT_TIMEOUT:
return 0;
break;
}
}
return 0;
}


DWORD CComm::WriteData(LPCVOID pdata,DWORD len)
{
DWORD write;
BOOL bSuccess;
if ( len < 1 )
return(0);

bSuccess = WriteFile(m_hCom, // handle to file to write to
pdata, // pointer to data to write to file
len, // number of bytes to write
&write, // pointer to number of bytes written
&m_ov); // pointer to structure needed for overlapped I/O
if ( ! bSuccess )
{
return(-1);
}
return write;
}







Cách sử dụng hàm:

1. CComm() hàm thiết lập mặc định
2. CComm(LPCSTR lpszPortNum) tạo đối tượng Comm với cổng xác định bởi lpszPortNum, 9600,n,1. VD "COM1","COM2"...
3. BOOL Open (LPCSTR lpszPortNum ) mở cổng COM x,9600,n,1
4. DWORD ReadData(LPVOID pdest,DWORD len) đọc dữ liệu từ cổng COM về pdest với số bytes cần đọc là len, trả về số byte đọc được
5. DWORD WriteData(LPCVOID pdata,DWORD len) đưa dữ liệu chứa trong pdata ra cổng COM với len bytes. Trả về số byte thành công.


VD:

CODE

#include "Comm.h"

CComm comm("COM1");
//CComm comm;
//comm.Open("COM1");

// đọc 10 byte dữ liệu

BYTE dest[10];

DWORD dwRes = comm.ReadData(dest,sizeof(dest));

TRACE("Đọc từ COM1 được %d bytes\n",dwRes);

// đưa 10 byte đọc được ra COM1

dwRes = comm.WriteData(dest,sizeof(dest));

TRACE("Viết COM1 với %d bytes thành công\n",dwRes);











: #6730


Show Smilies Pop Up Window | |

ngohaibac 19-10-2006 03:18 PM

Chào bạn. Thế bạn đã nghĩ đến việc làm thế nào để có thể nhận biết được sự kiện OnComm bằng cách này chưa :D. Nếu bạn viết như thế mà chưa có dữ liệu ở cổng Com thì nhận làm sao, và khi có thì nhận làm sao? nhận không kịp tràn bộ đệm thì sao?

Bạn trả lời được các câu hỏi đó thì chương trình bạn sẽ hoàn thiện ngay.

Mời bạn sang box về lập trình giao tiếp qua RS232 mình sẽ upload chương trình viết bằng VC++ mà không dùng MSCOMM, bạn xem và góp ý nhé .

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


Múi giờ GMT. Hiện tại là 04:08 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam