串口通讯的代码 。是别人写的 我加了些注释。

// Communication.h: interface for the CCommunication class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_COMMUNICATION_H__6CA00576_F088_11D1_89BB_8311A0F2733D__INCLUDED_)
#define AFX_COMMUNICATION_H__6CA00576_F088_11D1_89BB_8311A0F2733D__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/*
_MSC_VER 定义编译器的版本
MS VC++ 10.0 _MSC_VER = 1600
MS VC++ 9.0 _MSC_VER = 1500
MS VC++ 8.0 _MSC_VER = 1400
MS VC++ 7.1 _MSC_VER = 1310
MS VC++ 7.0 _MSC_VER = 1300
MS VC++ 6.0 _MSC_VER = 1200
MS VC++ 5.0 _MSC_VER = 1100
其中MS VC++ 10.0就是Visual C++ 2010,MS VC++ 9.0就是Visual C++ 2008,MS VC++ 8.0就是Visual C++ 2005。

在程序中加入_MSC_VER宏可以根据编译器版本让编译器选择性地编译一段程序。
例如一个版本编译器产生的lib文件可能不能被另一个版本的编译器调用,
那么在开发应用程序的时候,在该程序的lib调用库中放入多个版本编译器产生的lib文件。
在程序中加入_MSC_VER宏,编译器就能够在调用的时根据其版本自动选择可以链接的lib库版本,如下所示。
#if _MSC_VER >= 1400 // for vc8, or vc9
#ifdef _DEBUG
#pragma comment( lib, "SomeLib-vc8-d.lib" )
#else if
#pragma comment( lib, "SomeLib-vc8-r.lib" )
#endif
#else if _MSC_VER >= 1310 // for vc71
#ifdef _DEBUG
#pragma comment( lib, "SomeLib-vc71-d.lib" )
#else if
#pragma comment( lib, "SomeLib-vc71-r.lib" )
#endif
#else if _MSC_VER >=1200 // for vc6
#ifdef _DEBUG
#pragma comment( lib, "SomeLib-vc6-d.lib" )
#else if
#pragma comment( lib, "SomeLib-vc6-r.lib" )
#endif
#endif 

*/

#define WM_RECEIVEPACKET WM_USER+100

class CCommunication
{
public:
//	BOOL Connect;
	//发送数据函数
	int SendData(char *data,int len);

	//设定消息接收者
	void SetMessageReceiver(CWnd *pWnd);

	//初始化函数
	BOOL Initialize(char *device,DWORD BaudRate,int Bits,int DDV,int StopBit);

	//构造函数
	CCommunication();
	//析构函数
	virtual ~CCommunication();

	//关闭通讯接口
	BOOL CloseSerialPort();

	//CWnd是MFC窗口类的基类,提供了微软基础类库中所有窗口类的基本功能
	CWnd *msg_receiver;

	//OVERLAPPED是一个包含了用于异步输入输出的信息的结构体
	OVERLAPPED write_os;

	//定义一个句柄
	HANDLE hComPort;

private:

};

#endif // !defined(AFX_COMMUNICATION_H__6CA00576_F088_11D1_89BB_8311A0F2733D__INCLUDED_)
/*
第一种声明:

typedef struct _OVERLAPPED {
  DWORD Internal;
  DWORD InternalHigh;
  DWORD Offset;
  DWORD OffsetHigh;
  HANDLE hEvent;
  } OVERLAPPED
参数说明:

Internal: 预留给操作系统使用。
它指定一个独立于系统的状态,当GetOverlappedResult函数返回时没有设置扩展错误信息ERROR_IO_PENDING时有效。

InternalHigh: 预留给操作系统使用。它指定长度的数据转移,当GetOverlappedResult函数返回TRUE时有效。

Offset: 该文件的位置是从文件起始处的字节偏移量。调用进程设置这个成员之前调用ReadFile或WriteFile函数。
当读取或写入命名管道和通信设备时这个成员被忽略设为零。

OffsetHigh: 指定文件传送的字节偏移量的高位字。当读取或写入命名管道和通信设备时这个成员被忽略设为零。

hEvent: 在转移完成时处理一个事件设置为有信号状态。
调用进程集这个成员在调用ReadFile、 WriteFile、TransactNamedPipe、 ConnectNamedPipe函数之前。
*/

/*
第二种声明:

typedef struct _OVERLAPPED {
ULONG_PTR Internal; //操作系统保留,指出一个和系统相关的状态
ULONG_PTR InternalHigh; //指出发送或接收的数据长度
union {
struct {
DWORD Offset; //文件传送的字节偏移量的低位字
DWORD OffsetHigh; //文件传送的字节偏移量的高位字
};
PVOID Pointer; //指针,指向文件传送位置
};
HANDLE hEvent; //指定一个I/O操作完成后触发的事件
} OVERLAPPED, *LPOVERLAPPED;
*/

/*
I/O设备处理必然让主程序停下来干等I/O的完成,解决这个问题,可以使用OVERLAPPED。
OVERLAPPED I/O是WIN32的一项技术, 你可以要求操作系统为你传送数据,并且在传送完毕时通知你。
这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。
事实上,操作系统内部正是以线程来I/O完成OVERLAPPED I/O。
,而不需付出什么痛苦的代价。也就是说,OVERLAPPED主要是设置异步I/O操作,
异步I/O操作是指应用程序可以在后台读或者写数据,而在前台做其他事情。
*/

  

// Communication.cpp: implementation of the CCommunication class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Communication.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
BOOL CState;//定义一个全局的变量 CState。

//构造函数  用于给全局变量CState置ON
CCommunication::CCommunication()
{
	CState=TRUE;
}
//析构函数  用于给全局变量CState置OFF
CCommunication::~CCommunication()
{
   CState=FALSE;
}

//具体的函数定义  。这个CommWatchProc 这个函数 一个线程函数, 这个函数是为了处理 串口相关事件的处理。
//在后面的代码里面,有个AfxCreateThrend的函数 是用于创建线程的,其中第一个参数 就要填CommWatchProc
UINT CommWatchProc(LPVOID lpData)
{
//Add message WM_RECEIVEPACKET handler in class caller:
//(wParam=pointer to data block   lParam=length of data block

//Add message WM_SENDSUCCESS handler in class caller
	CCommunication* com=(CCommunication*)lpData;
   DWORD       dwEvtMask ;
   OVERLAPPED  os;
   COMSTAT comstat;
   DWORD dwErrorFlag;
   DWORD dwLength;
	//		AfxMessageBox("Receiving");

   memset( &os, 0, sizeof( OVERLAPPED ) ) ;

   // create I/O event used for overlapped read

   os.hEvent = CreateEvent( NULL,    // no security
                            TRUE,    // explicit reset req
                            FALSE,   // initial event reset
                            NULL ) ; // no name
   if (os.hEvent == NULL)
   {
      MessageBox( NULL, _T("Failed to create event for thread!"),
		          _T("Communication Error!"),
                  MB_ICONEXCLAMATION | MB_OK ) ;
      return ( FALSE ) ;
   }

   if (!SetCommMask(com->hComPort, EV_RXCHAR ))
      return ( FALSE ) ;
   DWORD dwRead;
   char *buf;
   buf=new char[MAX_PATH];
   memset(buf,0,MAX_PATH);
   while (CState)
   {
		dwEvtMask = 0 ;

		WaitCommEvent(com->hComPort, &dwEvtMask, 0 );//等待串口通讯的事件的发生。
		Sleep(100);
		//memset(buf,0,MAX_PATH);检测返回的dwEvtMask,知道发生了什么样的串口事件
		if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
		{//EV_RXCHAR代表缓冲区 有数据过来了
			//read code
			ClearCommError(com->hComPort,&dwErrorFlag,&comstat);//清除错误
			dwLength=comstat.cbInQue;//输入缓冲区有多少数据?
			if (dwLength)//如果大于0
			{

				if (ReadFile(com->hComPort,buf,dwLength,&dwRead,&os))//调用ReadFile函数读取缓冲区数据
				{
					com->msg_receiver->PostMessage(WM_RECEIVEPACKET,(WPARAM)buf,(LPARAM)dwRead);
					//想系统消息队列放入一个消息,通知程序的主线程,串口受到了数据。
				}
			}
		}
   }
   delete buf;
   // get rid of event handle
   CloseHandle( os.hEvent ) ;
   return( TRUE ) ;
} // end of CommWatchProc()

//初始化端口  定义端口的带宽 位数 奇偶校验 停止位之类的
BOOL CCommunication::Initialize(char * device,DWORD BaudRate,int Bits,int DDV,int StopBit)
{
//   srand( (unsigned)time( NULL ) );
   // open COMM device
	CState=TRUE;
	//将函数CreateFileA的的返回值赋值给hComPort,并且判定其等于(HANDLE) -1
   if (
	   (hComPort =
      CreateFileA( device,//设备名称  可以是COM2 COM3 之类的名字
					GENERIC_READ | GENERIC_WRITE,//允许读写
                  0,                    // exclusive access  必须是0
                  NULL,                 // no security attrs
                  OPEN_EXISTING,		//设置产生方式
                  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O  使用异步通讯
                  NULL )

				  ) == (HANDLE) -1
		)
      return ( FALSE ) ;
   // get any early notifications

   SetCommMask(hComPort, EV_RXCHAR ) ;//设置事件驱动类型

   // setup device buffers

   SetupComm(hComPort, 10240, 10240 ) ;//设置输入 输出缓冲区的大小

   // purge any information in the buffer

   PurgeComm(hComPort, PURGE_TXABORT | PURGE_RXABORT |
                                   PURGE_TXCLEAR | PURGE_RXCLEAR ) ;//清干净输入和输出缓冲区

   // set up for overlapped I/O
   COMMTIMEOUTS CommTimeOuts;	//定义超时结构, 并且给结构的中的值赋值
   CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
   CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
   CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;
   CommTimeOuts.WriteTotalTimeoutMultiplier = 0 ;
   CommTimeOuts.WriteTotalTimeoutConstant = 10000 ;
   SetCommTimeouts(hComPort, &CommTimeOuts ) ;

   DCB dcb;//定义数据控制块结构
   dcb.DCBlength=sizeof(DCB);
   dcb.BaudRate=BaudRate;//通讯波特率
   dcb.fBinary=1;
   dcb.fParity=1;
   dcb.fOutxCtsFlow=0;
   dcb.fOutxDsrFlow=0;
   dcb.fDtrControl=0;
   dcb.fDsrSensitivity=0;
   dcb.fTXContinueOnXoff=0;
   dcb.fOutX=0;
   dcb.fInX=0;
   dcb.fErrorChar=0;
   dcb.fNull=0;
   dcb.fRtsControl=0;
   dcb.fAbortOnError=0;
//   dcb.wReserved=0;
   dcb.XonLim=0;
   dcb.XoffLim=0;
   dcb.ByteSize=Bits;//数据位长度  Bits 就是八位的意思  也可以写数字8
   dcb.Parity=0;
   dcb.StopBits=ONESTOPBIT;//停止位 是几位  此处写的一位
   //dcb.StopBits=StopBit;

   if (!SetCommState(hComPort,&dcb))//数据配置完毕以后,就调用SetCommState函数 给端口配置
   return (FALSE);//如果配置不成功就返回 FALSE

   if (!AfxBeginThread(CommWatchProc,(LPVOID)this))//启动一个辅助线程,用于串口事件的处理
	   //此处需要对线程说明一下:
	   /*
	   Windows提供了两种线程,辅助线程和用户界面线程。区别在于:辅助线程
没有窗口,所以它没有自己的消息循环。但是辅助线程很容易编程,通常也
很有用。我们使用辅助线程。主要用它来监视串口状态,看有无数据到达、通
信有无错误;而主线程则可专心进行数据处理、提供友好的用户界面等重要
的工作。
辅助线程还有一个名字 就是工作线程。
	   */
   {
    CloseHandle(hComPort) ;//如果线程没有启动成功,就关闭句柄,并且返回FAlSE
    return (FALSE);
   }
   else
   {
    // assert DTR and RTS
    EscapeCommFunction(hComPort,SETDTR);
    EscapeCommFunction(hComPort,SETRTS);
   }
   memset( &write_os, 0, sizeof( OVERLAPPED )) ;
   write_os.hEvent = CreateEvent( NULL,    // no security
                                  TRUE,    // explicit reset req
                                  FALSE,   // initial event reset
                                  NULL ); // no name
   if (NULL == write_os.hEvent)
   {
      CloseHandle( write_os.hEvent ) ;
      return (FALSE) ;
   }
   return(TRUE);
}

//关闭串口的端口
BOOL CCommunication::CloseSerialPort()
{
	CState=FALSE;
	Sleep(10);
	if(!CloseHandle(hComPort)) return FALSE;
	else return TRUE;
}

void CCommunication::SetMessageReceiver(CWnd * pWnd)
{
	//Add a line in class caller:
	//??.SetMessageReceiver(this);
	msg_receiver=pWnd;
}

//函数: 用于发送数据 。需要提交的是发送数据的字符内容 和长度
int CCommunication::SendData(char * data, int len)
{
	CString b;
	int a=1,c=1;
	unsigned long sendlen;
    a=WriteFile(hComPort, data, len, &sendlen, &write_os);//其实其内部调用的是WriteFile这个函数。
	//从本质上  系统把通讯的东西看成一个文件的读写。
	CString strText;
	strText.Format(",,‘%s",data);
//	::Log(GetDirectory()+"\\Log\\Com.csv",strText.Left(31),TRUE,"Time,Receive,send");
	return sendlen;
}

/*
使用多线程技术,在工作线程(也就是所谓的辅助线程)里面监视串口,有数据到达时依靠事件驱动,
读取数据后向主线程汇报,注意发送数据的工作在主线程里面完成,因为通常来说发送数据的
内容(也就是所谓的下行数据)数量比较少,并且WaitCommEvent,ReadFile(),WriteFile()	都
使用非阻塞通信技术。依靠重叠(Overlappend)读写操作,让串口的读写工作在后台完成。
*/

/*
读写文件是每个Windows软件开发人员都需要做的工作。可见这项工作是非常重要的,
毕竟各种各样的数据都需要保存起来,以便作各种各样的分析,或者通过网络传送给别人。
像大家用BT下载的电影,在那个BT软件里,就需要不断从网络里接收到数据,
然后再把这些数据保存到文件里合适的位置,就可以生成跟发行者那里一样的文件,
这样才可以播放出来。又比如我在玩《征途》的游戏里,刚刚打开游戏时,
它就不断从服务器上下载更新的文件下来,然后保存到硬盘。WriteFile函数是用来写数据到文件,
ReadFile函数是从文件里读取数据出来。但这两个函数不但可以读取写磁盘的文件,
也可以接收和发送网络的数据,还有读写串口、USB、并口等设备的数据。在读写文件里,
首先就是先打开文件,然后判断打开是否成功。在写文件时,同时要注意磁盘的空间是否满等问题。
在读取文件时,往往需要读取不同位置的文件,比如要读取一个4G的视频文件,
就不可能完全把它读取到内存里,因此就需要对文件进行定位读取。
*/

/*
函数WriteFile和ReadFile声明如下:
WINBASEAPI
BOOL
WINAPI
WriteFile(
    __in        HANDLE hFile,//是文件句柄
    __in_bcount(nNumberOfBytesToWrite) LPCVOID lpBuffer,//是读写数据缓冲区
    __in        DWORD nNumberOfBytesToWrite,//是多少数据要写入
    __out_opt   LPDWORD lpNumberOfBytesWritten,//是已经写入多少数据
    __inout_opt LPOVERLAPPED lpOverlapped//是异步读写的结构
    );

WINBASEAPI
BOOL
WINAPI
ReadFile(
    __in        HANDLE hFile,//是文件句柄
    __out_bcount_part(nNumberOfBytesToRead, *lpNumberOfBytesRead) LPVOID lpBuffer,//是读写数据缓冲区
    __in        DWORD nNumberOfBytesToRead,//是多少数据要读取
    __out_opt   LPDWORD lpNumberOfBytesRead,//是已经读取多少数据
    __inout_opt LPOVERLAPPED lpOverlapped//是异步读写的结构
    );

hFile是文件句柄。
lpBuffer是读写数据缓冲区。
nNumberOfBytesToWrite是多少数据要写入。
lpNumberOfBytesWritten是已经写入多少数据。
nNumberOfBytesToRead是多少数据要读取。
nNumberOfBytesToRead是已经读取多少数据。
lpOverlapped是异步读写的结构。

调用函数的例子如下:
#001  //创建、写入、读取文件。
#002  //蔡军生 2007/10/21 QQ:9073204 深圳
#003  void CreateFileDemo(void)
#004  {
#005         //
#006         HANDLE hFile = ::CreateFile(_T("CreateFileDemo.txt"),     //创建文件的名称。
#007               GENERIC_WRITE|GENERIC_READ,          // 写和读文件。
#008               0,                      // 不共享读写。
#009               NULL,                   // 缺省安全属性。
#010               CREATE_ALWAYS,          // 如果文件存在,也创建。
#011               FILE_ATTRIBUTE_NORMAL, // 一般的文件。
#012               NULL);                 // 模板文件为空。
#013
#014         if (hFile == INVALID_HANDLE_VALUE)//根据返回文件句柄的值,判定创建是否成功。
#015         {
#016               //
#017               OutputDebugString(_T("CreateFile fail!/r/n"));
#018         }
#019 

#020         //往文件里写数据。
#021         const int BUFSIZE = 4096;//定义缓冲区的大小
#022         char chBuffer[BUFSIZE];    //定义一个缓冲区 其实就是一个字符数组
#023         memcpy(chBuffer,"Test",4);//由src指向地址为起始地址的连续n个字节的数据复制到
                                       //以destin指向地址为起始地址的空间内。
#024         DWORD dwWritenSize = 0;
#025        BOOL bRet = ::WriteFile(hFile,chBuffer,4,&dwWritenSize,NULL);//将字符数组里面
									   //的数据写入 文件句柄对应的那块内存区域里面。
#026         if (bRet)
#027         {
#028               //
#029               OutputDebugString(_T("WriteFile 写文件成功/r/n"));
#030         }
#031
#032         //先把写文件缓冲区的数据强制写入磁盘。
#033         FlushFileBuffers(hFile);
#034
#035         //
#036         //从文件里读取数据。
#037         LONG lDistance = 0;
#038         DWORD dwPtr = SetFilePointer(hFile, lDistance, NULL, FILE_BEGIN);
#039         if (dwPtr == INVALID_SET_FILE_POINTER)
#040         {
#041               //获取出错码。
#042               DWORD dwError = GetLastError() ;
#043               //处理出错。
#044         }
#045
#046         DWORD dwReadSize = 0;
#047        bRet = ::ReadFile(hFile,chBuffer,4,&dwReadSize,NULL);
#048         if (bRet)
#049         {
#050               //
#051               OutputDebugString(_T("ReadFile 读文件成功/r/n"));
#052         }
#053         else
#054         {
#055               //获取出错码。
#056               DWORD dwError = GetLastError();
#057               //处理出错。
#058               TCHAR chErrorBuf[1024];
#059               wsprintf(chErrorBuf,_T("GetLastError()=%d/r/n"),dwError);
#060               OutputDebugString(chErrorBuf);
#061         }
#062
#063  }
*/

/*
在软件的需求里,把有用的数据保存起来是非常重要的功能。
比如每天的股票行情数据需要保存起来,以便生成K线图。
比如游戏客户端的LOG需要保存起,以便客户端出错时可以把LOG发送回来分析它出错的原因。
比如银行每天进行交易时,也需要把所有交易的数据保存到文件备份起来,以便进行结算。
还有在数据采集领域更是需要保存更多的数据,比如从DV里读取视频和语音数据出来,
就会生成12G的巨型文件。比如读DVD光盘里,把光盘做成虚拟光驱也有9G大小。
因此,创建文件是非常普通的功能,这个肯定是掌握,并且非常会使用的。
当然这个CreateFile函数不但可以创建文件,还可以打串口、并口、网络、USB设备等功能。

函数CreateFile声明如下:
WINBASEAPI
__out
HANDLE
WINAPI
CreateFileA(
    __in     LPCSTR lpFileName,
    __in     DWORD dwDesiredAccess,
    __in     DWORD dwShareMode,
    __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    __in     DWORD dwCreationDisposition,//是创建属性
    __in     DWORD dwFlagsAndAttributes,
    __in_opt HANDLE hTemplateFile
    );

WINBASEAPI
__out
HANDLE
WINAPI
CreateFileW(
    __in     LPCWSTR lpFileName,//是文件或是设备的名称
    __in     DWORD dwDesiredAccess,//是访问属性
    __in     DWORD dwShareMode,//是共享模式
    __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,//是安全属性
    __in     DWORD dwCreationDisposition,//是创建属性
    __in     DWORD dwFlagsAndAttributes,//是文件标志和属性
    __in_opt HANDLE hTemplateFile//是文件模板
    );

#ifdef UNICODE
#define CreateFile CreateFileW
#else
#define CreateFile CreateFileA
#endif // !UNICODE
lpFileName是文件或设备的名称。
dwDesiredAccess是访问属性。
dwShareMode是共享属性。
lpSecurityAttributes是安全属性。
dwCreationDisposition是创建属性。
dwFlagsAndAttributes是文件标志和属性。
hTemplateFile是文件模板。

调用函数的例子如下:
#001  //创建文件。
#002  //蔡军生 2007/10/18 QQ:9073204 深圳
#003  void CreateFileDemo(void)
#004  {
#005         //
#006         HANDLE hFile = ::CreateFile(_T("CreateFileDemo.txt"),     //创建文件的名称。
#007              GENERIC_WRITE,          // 写文件。
#008              0,                      // 不共享读写。
#009              NULL,                   // 缺省安全属性。
#010              CREATE_ALWAYS,          // 如果文件存在,也创建。
#011              FILE_ATTRIBUTE_NORMAL, // 一般的文件。
#012              NULL);                 // 模板文件为空。
#013
#014         if (hFile == INVALID_HANDLE_VALUE)
#015         {
#016               //
#017               OutputDebugString(_T("CreateFile fail!/r/n"));
#018         }
#019  }
*/

  

时间: 2024-10-07 10:21:02

串口通讯的代码 。是别人写的 我加了些注释。的相关文章

简单的串口通讯程序

很早以前写过串口通讯的代码,今天又要用到,做了一个简单的类封装. 代码如下: rs485Test.h #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <termios.h> #include <fcntl.h> #include <errno

山大泰克条屏写串口的核心代码(海宏原创,转载请注明)

山大泰克条屏写串口的核心代码,海宏原创,转载请注明. using System; using System.Collections.Generic; using System.Text; // using System.Runtime.InteropServices; using System.IO.Ports; using System.Windows.Forms; using iPublic; namespace sdLed { /// <summary> /// 用来连接LED的API.

看别人写的优秀代码,是对自己的一种提高,看别人写的很恶心的代码,对自己也是一种提高:告诉自己不要这样写(转)

这两天,我做了两件事: 1.重构了系统某个模块的部分代码: 花了一天时间,一个6k多行的java文件,搞到4k行加若干个类文件,恕我能力有限,后面的实在重构不下去了,那是一种3个domain属性名几乎一样100多个字段但是却用同一个copy了三遍的方法来处理的欲哭无泪,那是一种使劲滚鼠标滚轮都滚不到一个方法尾部的绝望(100多个字段的几个类属性equals来,equals去,get来,set去的,这样类型的方法有那么五六个,你说能不多吗)...... 2.做了一个日志处理的小工具: 客户要求把日

Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块

一直想写一份技术文档,但因为自感能力有限而无从下笔,近期做了个关于Android平台下实现与C语言的通讯来操作蓝牙模块的项目,中间碰到了很多问题,也在网上查了很多资料,在完毕主要功能后.也有一些人在网上问我一些问题.这里写下这篇文档算是一个阶段性的总结. 假设反响好.兴许将会发上Android Stub与新版Android HAL的学习文档. 因为蓝牙模块是串口通讯机制.使用C语言来訪问,而Android的应用层採用Java.无法直接操作硬件.故使用JNI的技术实现主要功能.Android的JN

C#串口通讯

本文提供一个用C#实现串口通讯实例,亲自编写,亲测可用! 开发环境:VS2008+.net FrameWork3.5(实际上2.0应该也可以) 第一步 创建一个WinForm窗体,拉入一些界面元素 重点就是,图中用红框标出的,工具箱——组件——SerialPort,做.net串口通讯,这是必备控件 第二步 设置SerialPort控件属性 用C#向串口发送数据没什么特别的,就是调用SerialPort的Write方法往串口写数据就行 但是从串口那里接收数据的方式就比较特别了 首先,需要在代码里声

Linux串口通讯

一.串口简介 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接通常特指那些与RS-232标准兼容的硬件或者调制解调器的接口.虽然现在在很多个人计算机上,原来用以连接外部设备的串口已经广泛的被USB和Firewire替代:而原来用以连接网络的串口则被以太网替代,还有用以连接终端的串口设备则已经被MDA或者VGA取而代之.但是,一方面因为串口本身造价便宜技术成熟,另一方面因为

Java程序与RSR232串口通讯小练手(转载)

一直以来都是在学习J2EE方面的应用系统开发,从未想过用JAVA来编写硬件交互程序,不过自己就是喜欢尝试一些未曾接触的新东西.在网上搜索了些资源,了解到JAVA写串口通讯的还是蛮多的,那么便着手准备开发调试环境.软件程序开发环境搭建不成问题,可这硬件环境就有点犯难啦.更何况自己用的是笔记本哪来的串口呀,再说要是真拿这串口硬件来自己也不会弄,随即想到了虚拟机,觉得这东西应该也有虚拟的吧,果真跟自己的猜测一样还真有这东西,顺便也下载了个串口小助手做为调试之用.下面就先看看软件环境的搭建: 1.下载c

自定义串口通讯类的实现

前面写串口通讯是有界面的,后面的项目感觉串口通讯只是辅助的作用,应该专门写一个不可视的类来做,这样的好处是通讯模块是独立的,要用的时候直接引用就行了. using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.IO;using System.IO.Ports;using System.Threading;us

多机串口通讯

★使用器件 使用了3块80c51的单片机,其中U1为主机控制其他两个从机U2,U3.每个单片机上都有一个数码管用来显示数据.主机上有两个按键KEY_1,KEY_2,分别用来控制不同的从机. ★实现目标 主要实现的目标就是通过写多机通讯来了解他们其中的协议,以及简单协议的写法!本程序主要达到了一下效果,主机可以通过发送命令来控制从机:发送数据给从机.接收从机的数据.然后将从机或者主机显示的数据显示在数码管上. ★协议要求 1.地址:主机的地址设置为0x01,从机1(U3)的地址为0x03,从机2(