
串口多线程 卫星导航实例.doc
5页单片机编程专家VC++】在 VC++编程 息和事件;工作者线程主要用来处理应用程序的后台任务应用程序可以通过调用 AfxBejinThread()函数自动创建一个 CwinThread 对象,从而开始一个线程线程的终止条件有如下 4 种:线程函数返回;线程调用 ExitThtead()退出;异常情况下用现成的句柄调用 TerminateThread()退出;线程所属的进程被终止3、多线程在 RS-322 应用3.1 串口通信对线程同步 因为同一进程的所有线程共享进程的虚拟地址空间,而在 WINDOWS 中线程是汇编级中断,所以才有可能实现多个线程同时访问同一个对象这些对象可以是全局变量、MFC 的对象、MFC 的 API 等而串口通信对每个串口对象只提供一个缓冲区,发送接收都要用到这一个缓冲区,所以要求必须建立同步线程执行,使得一个时刻只能进行一种线程操作,以免通信出错串口通信处理的多个线程需要协调运行,一个线程必须等待另一线程结束才能开始,在处理一个线程的同时必须把其余待处理的线程挂起等待,以减少其余待处理线程对 CPU 的资源占用,正处理的线程一旦处理结束则通过线程间的通信发出信号来击活被挂起的线程中的一个线程进入处理。
VC++提供了以下 4 个同步对象来协调实现多线程的并行:Csemaphore 信号灯对象,允许一定数量的现成访问某个资源,用来控制访问共享资源的线程数量Cmutex 互斥量对象,一个时刻至多只允许一个线程访问某个资源,未被占用时处于有信号状态,可实现对共享线程的互斥访问Cevent 事件对象,用于使一个线程统治其余现成某个事件正发生,所以可以用来实现禁止对某个资源的访问,直至该线程结束释放资源使资源处于有信号状态,从而使被挂起的线程被通知得以执行CcriticalSection 临界区对象,将一段代码置入临界缓冲区,并只允许一个线程进入执行这段代码,该临界缓冲区仅在创建这个缓冲区的进程中有效3.2 等待 为了实现线程在资源对象被占用时把自己挂起而阻塞自己执行,等待资源空闲信号停止阻塞继续执行,从而减少对 CPU 的资源占用,WIN32 API 中提供了两个等待函数来实现这一功能:WaitForSingleObject() (只可监控单个同步对象) WaitForMUultipleObjects(可同时监控多个同步对象)在监控系统中,处理串口通信只是 CPU 的一部分事物,所以必须使用等待函数提高程序的执行效率。
3.3 的重叠 I/O 方式MFC 对于串口通信是作为文件设备来处理的,用 CreateFile()打开串口获得一个串口句柄打开后由 SetCommState()进行串口端口配置:缓冲区设置、超时设置、数据格式设置等等设置成功后就可以调用 ReadFile()和 WriteFile()进行数据的读与写,用WaitCommEvent()监控通信事件CloseHandle()用于关闭串口在 ReadFile()和WriteFile()进行串口读写时可以采取同步执行方式也可以采用重叠 I/O 方式由于采用同步执行方式,被调用的函数必须执行结束后才被返回,这必然要求除正被执行线程外其余线程被挂起等待,效率低;而采用重叠 I/O 方式,被调用的函数不必等执行结束后才被返回,而是可以立即返回,因为 I/O 操作在后台执行,这样其他线程就不必等待马上可以进行处理其他事物,实现了不同线程可以在同一串口句柄上基本上接近同时实现读写操作,实现重叠,是通信的实时性提高采用重叠 I/O 方式,线程必须创建 OVERLAPPED 结构攻读写函数使用,该结构最重要的成员是 hEvent 事件句柄它将作为线程的同步对象使用,读写函数完成时 hEvent 处于有信号状态,表示可以进行读写操作;读写函数未完成时 hEvent 被置于无信号状态。
4、多线程应 信程序中的实现应用程序需专门建立一个串口通信类,并在串口通信相关程序段中应用相关函数实现多线程的应用,下面给出实现多线程应用的的关键函数的核心代码1).专门针对 COM1 的初始化程序段(只写出涉及多线程应用的关键步骤)BOOL InitComm()//串口初始化{HANDLE m_hComm;COMMTIMEOUTS m_CommTimeouts;m_hComm = CreateFile(“COM1” , //这里只使用串口 1,如要对多个串口初始化需先在初始化前进入代码临界区,以保证在某时刻只对一个串口初始化GENERIC_READ | GENRIC_WRITE, //定义串口打开类型为可读写0, //以独占串口资源模式打开串口NULL, //对该串口不设置安全属性OPEN_EXISTING,FILE_FLAG_OVERLAPPED, //设置重叠 I/O 模式0;)if (m_hComm==INVALID_HANDLE_VALUE) //串口打开不成功{return FALSE;}m_CommTimeouts.ReadIntervalTimeout = 1000; //进行超时设置,具体量值根据实际需要调整m_CommTimeouts.ReadTotaloutMultiplier = 500; //进行超时设置m_CommTimeouts.ReadTotaloutConstant = 5000; //进行超时设置m_CommTimeouts.WriteTotaloutMultiplier = 500; //进行超时设置m_CommTimeouts.WriteTotaloutConstant = 5000; //进行超时设置if(! SetCommTimeouts(m_hComm,&m_CommTimeouts)){CloseHandle(m_hComm);return FALSE;}PurgeComm (m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT |PURGE_TXABORT); //清除串口缓冲区Reture TRUE;}在上述串口初始化成功后,监 控用的工作者线程从而实现对该串口通信多线程的并行管理,如果要对多个串口同时监控,可以分别对各个串口建立监控线程,各自实现对应串口的通信多线程的并行管理。
下面是建立串口监控用的工作者线程的关键程序段代码(只写出涉及多线程应用的关键步骤)UINT CommThread(LPVOID pParam) //用于监控串口用的工作者线程{BOOL bResult = FLASE;If(m_hComm) //查看前述串口初始化程序是否已打开串口PurgeComm (m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT |PURGE_TXABORT);for(;;) //只要所要监控的串口有线程在运行,就一直处于监视端口行为的无限循环{bResult = WaitCommEvent(m_hComm,&Event,&m_ov); // m_ov 是 OVERLAPPED 类型的成员变量if(! bResult){//进行相关的出错处理的具体函数调用过程这里与主题无关,略去不表述}else{Event = WaitForMultipleObjects(4, m_hEvent, FALSE, INFINITE);//无限等待设定的事件发生,其中 m_hEvent 根据需要设定了须响应的接收、发送、关闭串口事件以及 OVERLAPPED 类型的 hEvent 事件Switch(Event){//串口进行数据读写事件的响应处理过程。
这里与主题无关,略去不表述}return 0;}在编写远程监控串口通 关键程序段就可实现串口通讯程序的多线程应用,从而提高串口的事件响应能力,提高远端的数据交互实时性。
