多线程串口类
Delphi 串口多线程处理 急急急急解决马上给分

最好是自己做个类似链表的数据结构做缓冲区,暂命名为LinkList,Delphi中好像没这样的数据结构
我现在是每接到一个数据包就开辟一个线程来处理和分析,结果发现CPU占用的太厉害了,基本上为100%,鼠标的操作基本上响应不了.
敬请各位给个好的解决方法,即能够不断的处理每个数据包,而不影响人机交互的操作.分数不够可以再加
1 楼 postren 发表于:2011-08-24 14:53:33 是不是线程中没有用sleep啊,适当的添加sleep缓冲cpu的使用率 2 楼 postren 发表于:2011-08-24 15:10:13 处理方式呢,这样比较好:
接收线程收到数据后就把数据放到LinkList的尾部,除此之外该线程不做其他任何事,也要适当添加sleep
处理线程负责查看LinkList中有没有元素,如果有则进行处理,否则sleep
其中的处理包括保存数据库、分析数据、向串口发送指令等
解决CPU占用率..可以使用windows的性能监视器..然后找出问题所在.. 13 楼 postren 发表于:2011-08-24 18:13:33 给搂住发邮件了,一个简单的例子 14 楼 mymousecat 发表于:2011-08-24 18:30:13 你的这个问题,我在刚做完的项目里就碰到了,为什么你每收一个数据包就要开一条线程呢,这样才不划算了!我有两条线程解决了问题,一条专收数据包,把收到的数据写入自定的Buffer里,而另一条是专门从Buffer里取数并插库呢,项目运行两个多了,很键状,有什么事可以直接找我,QQ:459834034 15 楼 lnndy 发表于:2011-08-24 18:46:53 说得太不具体了,我刚刚做了你一个类似的问题,用两个串口分别读取的数据,读取数据以后的处理也是很复杂,用了四个线程,CPU的占用率才2%左右,你说得不够详细,详细的说来听听?
SPCP多线程串口通信软件设计

本设计总体设计思路归根到底是以上的设计方 法, 限于篇幅具体函数的使用方法不再赘述。
收稿 日期 :2 1 —0 0 0 1 5— 9
l Wi 2A I串 口编 程 n P 3
De in o u tt r a e e i lc m m u ia in s fwa e wih S sg fm lih e d d s ra o n c to o t r t PCP T N hn -un X h-n A G Z egq a . U Z iig j
(nomainE gneigC H g ,h nh i r i iesy,h n a 0 15 C ia Ifr t n ier o ee S a g a ime vri S a g i 0 3 , hn ) o n Ma t Un t h 2
函数 。 ( ) 立 辅 助 线 程 : 到 函 数 较 多 , 要 有 4 建 用 主
Wa C m E e t i o m vn,WatoMu il bet, l ro — t i r lpe jcs Ce C m F t 0 a
通过调用计算机操作系统提供的一系列底层例程来 实现的。目前采用 M Cm S o m实现 串 口通信 的实例
2 1 年第 1 01 1期
中 图分 类号 :P 1 T 31 文 献 标 识码 : A 文 章编 号 :0 9— 52 2 1 ) 1 0 1 0 10 2 5 (0 1 1 — 0 3— 3
SC P P多线程 串 口通 信 软 件设 计
唐政权 ,徐志京
( 上海海事大学信息工程学院 , 海 203 ) 上 01 5
基于数据库和串口技术的数据监控系统

基于数据库和串口技术的数据监控系统摘要:ADO和串口通信技术常用于数据采集监控等场合。
通过ADO 对象可以建立与数据库的连接,并读写数据库中的数据;利用串口通信程序可在上位机和下位机间进行数据传输。
介绍了ADO对象及其导入编程环境的方法,根据具体事例详细描述了利用ADO对象操作数据库,介绍了串口通信程序。
结果证明ADO和串口通信技术相结合可以更方便快捷地访问数据库。
关键词:VC++;ADO;数据库;串口;监控系统0 引言数据采集作为远程监控的重要组成部分,通常是创建一个普通数据文件如文本文件保存数据。
但当数据量很大时,频繁地读写将会消耗很多的系统资源,造成上位机负担加重,实时性恶化,利用数据库管理系统则能较好地解决这一问题。
串行通信因其简单方便、成本低廉、适合大规模长距离传输等优点,广泛地应用于远程监控系统中。
本文介绍了一种利用ADO技术访问数据库,实现串口数据采集存取的方法。
1 ADO数据库接口技术1.1 ADO技术简介ADO(ActiveX Data Object)是微软提出的一种应用程序接口,和DAO、RDO一样,均可以访问数据库中的数据。
它是一种功能强大的面向对象的数据访问编程模式,是对当前微软所支持的数据库进行操作的最有效和最简单直接的方法。
由于微软开发的Visual C++语言支持COM库,所以可在VC编译环境下利用ADO对象访问数据库。
1.2 ADO数据库初始化使用ADO访问数据库之前有两个准备步骤:①导入ADO类型库;②初始化COM库。
一般在stdafx.h头文件中,使用#import指令导入ADO类型库,程序语句如下:#import“C:Program FilesCommon FilesSystemadomsado15.dll”no_namespacerename(“EOF”,“adoEOF”)rename(“BOF ”,“adoBOF”)在调用ADO对象之前,必须先初始化库环境,调用结束后再释放资源。
Qt下实现多线程的串口通信

Qt下实现多线程的串⼝通信简述Qt下⽆论是RS232、RS422、RS485的串⼝通信都可以使⽤统⼀的编码实现。
本⽂把每路串⼝的通信各放在⼀个线程中,使⽤movetoThread的⽅式实现。
代码之路⽤SerialPort类实现串⼝功能,Widget类调⽤串⼝。
serialport.h如下#include <QObject>#include <QSerialPort>#include <QString>#include <QByteArray>#include <QObject>#include <QDebug>#include <QObject>#include <QThread>class SerialPort : public QObject{Q_OBJECTpublic:explicit SerialPort(QObject *parent = NULL);~SerialPort();void init_port(); //初始化串⼝public slots:void handle_data(); //处理接收到的数据void write_data(); //发送数据signals://接收数据void receive_data(QByteArray tmp);private:QThread *my_thread;QSerialPort *port;};serailport.cpp如下#include "serialport.h"SerialPort::SerialPort(QObject *parent) : QObject(parent){my_thread = new QThread();port = new QSerialPort();init_port();this->moveToThread(my_thread);port->moveToThread(my_thread);my_thread->start(); //启动线程}SerialPort::~SerialPort(){port->close();port->deleteLater();my_thread->quit();my_thread->wait();my_thread->deleteLater();}void SerialPort::init_port(){port->setPortName("/dev/ttyS1"); //串⼝名 windows下写作COM1port->setBaudRate(38400); //波特率port->setDataBits(QSerialPort::Data8); //数据位port->setStopBits(QSerialPort::OneStop); //停⽌位port->setParity(QSerialPort::NoParity); //奇偶校验port->setFlowControl(QSerialPort::NoFlowControl); //流控制if (port->open(QIODevice::ReadWrite)){qDebug() << "Port have been opened";}else{qDebug() << "open it failed";}connect(port, SIGNAL(readyRead()), this, SLOT(handle_data()), Qt::QueuedConnection); //Qt::DirectConnection }void SerialPort::handle_data(){QByteArray data = port->readAll();qDebug() << QStringLiteral("data received(收到的数据):") << data;qDebug() << "handing thread is:" << QThread::currentThreadId();emit receive_data(data);}void SerialPort::write_data(){qDebug() << "write_id is:" << QThread::currentThreadId();port->write("data", 4); //发送“data”字符}widget.h的调⽤代码#include "serialport.h"public slots:void on_receive(QByteArray tmpdata);private:SerialPort *local_serial;widget.cpp调⽤代码//构造函数中local_serial = new SerialPort();connect(ui->pushButton, SIGNAL(clicked()), local_serial, SLOT(write_data()),Qt::QueuedConnection);connect(local_serial, SIGNAL(receive_data(QByteArray)), this, SLOT(on_receive(QByteArray)), Qt::QueuedConnection);//on_receive槽函数void Widget::on_receive(QByteArray tmpdata){ui->textEdit->append(tmpdata);}写在最后本⽂例⼦实现的串⼝号是 /dev/ttyS1(对应windows系统是COM1⼝),波特率38400,数据位8,停⽌位1,⽆校验位的串⼝通信。
stm32多任务多数据串口接收及处理方法

stm32多任务多数据串口接收及处理方法STM32多任务多数据串口接收及处理方法通常涉及到使用中断服务程序(ISR)或轮询方法来接收串口数据,并在多个任务之间分配和同步处理这些数据。
以下是一个基本的步骤和策略,用于实现这一功能:1. 初始化串口:首先,你需要初始化串口以进行通信。
这包括设置波特率、数据位、停止位、奇偶校验等。
2. 配置中断:STM32的串口通常具有一个接收中断。
你可以配置这个中断,以便每当一个新的字节被接收时,它就会触发一个中断。
3. 中断服务程序(ISR):在中断服务程序中,你可以读取接收缓冲区中的数据,并将其放入一个全局变量或数据结构中,以便其他任务或函数可以访问它。
4. 多任务处理:你可以使用一个任务或一组任务来处理这些串口数据。
这可能涉及到解析数据、执行某些操作或将数据发送到其他设备。
5. 数据同步:在多任务环境中,你需要确保数据的同步。
这意味着,当一个任务正在处理数据时,其他任务不能同时访问或修改这些数据。
这通常通过使用互斥锁、条件变量或其他同步机制来实现。
6. 轮询:除了使用中断,你还可以使用轮询方法来检查串口是否有数据可供读取。
这种方法可能在某些应用中更简单,但可能不如中断方法效率高。
7. 错误处理:不要忘记在代码中包含错误处理逻辑。
这可能包括检查读取的数据是否完整、是否有任何传输错误等。
8. 优化:对于高性能应用,你可能还需要考虑其他优化策略,如非阻塞读取、缓冲区管理、流量控制等。
以上只是一个基本的框架,具体的实现细节将取决于你的具体需求和STM32的具体型号。
建议查阅STM32的参考手册和相关文档以获取更详细的信息和示例代码。
CSerialPort类解析

assert(portnr > 0 && portnr < 5);assert(pPortOwner != NULL);// if the thread is alive: Killif (m_bThreadAlive){do{SetEvent(m_hShutdownEvent);}while (m_bThreadAlive);TRACE("Thread ended\n");}// create eventsif (m_ov.hEvent != NULL)ResetEvent(m_ov.hEvent);m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (m_hWriteEvent != NULL)ResetEvent(m_hWriteEvent);m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);if (m_hShutdownEvent != NULL)ResetEvent(m_hShutdownEvent);m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);// initialize the event objectsm_hEventArray[0] = m_hShutdownEvent; // highest prioritym_hEventArray[1] = m_ov.hEvent;m_hEventArray[2] = m_hWriteEvent;// initialize critical sectionInitializeCriticalSection(&m_csCommunicationSync);// set buffersize for writing and save the ownerm_pOwner = pPortOwner;if (m_szWriteBuffer != NULL)delete [] m_szWriteBuffer;m_szWriteBuffer = new char[writebuffersize];m_nPortNr = portnr;m_nWriteBufferSize = writebuffersize;m_dwCommEvents = dwCommEvents;BOOL bResult = FALSE;char *szPort = new char[50];char *szBaud = new char[50];// now it critical!EnterCriticalSection(&m_csCommunicationSync);// if the port is already opened: close itif (m_hComm != NULL){CloseHandle(m_hComm);m_hComm = NULL;}// prepare port stringssprintf(szPort, "COM%d", portnr);sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);// get a handle to the portm_hComm = CreateFile(szPort, // communication port string (COMX)GENERIC_READ | GENERIC_WRITE, // read/write types0, // comm devices must be opened with exclusive access NULL, // no security attributesOPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O0); // template must be 0 for comm devicesif (m_hComm == INVALID_HANDLE_VALUE){// port not founddelete [] szPort;delete [] szBaud;return FALSE;}// set the timeout valuesm_CommTimeouts.ReadIntervalTimeout = 1000;m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;m_CommTimeouts.ReadTotalTimeoutConstant = 1000;m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;m_CommTimeouts.WriteTotalTimeoutConstant = 1000;// configureif (SetCommTimeouts(m_hComm, &m_CommTimeouts)){if (SetCommMask(m_hComm, dwCommEvents)){if (GetCommState(m_hComm, &m_dcb)){m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!if (BuildCommDCB(szBaud, &m_dcb)){if (SetCommState(m_hComm, &m_dcb)); // normal operation... continueelseProcessErrorMessage("SetCommState()");}elseProcessErrorMessage("BuildCommDCB()");}elseProcessErrorMessage("GetCommState()");}elseProcessErrorMessage("SetCommMask()");}elseProcessErrorMessage("SetCommTimeouts()");delete [] szPort;delete [] szBaud;// flush the portPurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | P URGE_TXABORT);// release critical sectionLeaveCriticalSection(&m_csCommunicationSync);TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communica te.\n", portnr);return TRUE;}这个函数是用来初始化串口的,即设置串口的通信参数:需要打开的串口号、波特率、奇偶校验方式、数据位、停止位,这里还可以用来进行事件的设定。
CSerial类与MSComm控件

一、CSerialPort类支持多线程链接(非MODEM)的串口编程操作,其步骤如下:第一步:在**Dlg.h文件添加#include "SerialPort.h"(需先加入类头文件与源文件)第二步:添加成员变量 CSerialPort serialPort;第三步:在初始化对话框函数中调用serialPort.InitPort,serialPort.StartMonitoring 第四步:发送,serialPort.WriteToPort(buf);第五步:接收,在类的定义中,声明消息函数afx_msg LONG OnCommunication(UINT, LONG);在.cpp文件中添加映射ON_MESSAGE(WM_COMM_RXCHAR, OnCommunication)并实现LONG **Dlg::OnCommunication(WPARAM ch, LPARAM port)基于单文档的应用程序,则初始化在新增加的OnInitialUpdate()中添加代码。
说明:由于OnCommunication(WPARAM ch,LPARAM port)带参,所以其接收代码比MSComm 控件的接收代码简单很多,不要涉及接收函数及其数据类型的转换。
二、但对于MODEM控制,需要对类进行改写,采用MSComm控件比较理想。
使用MSComm控件进行编程的基本步骤:1)在建立的工程中加入MSComm控件;2)添加MSComm控件的ID关联变量(或者对象);3)对串口进行初始化,设置MSComm控件的属性(一般在OnInitDialog中);4)添加串口事件的消息处理函数OnComm(),在函数中根据应用需要,编写数据处理代码;(一般用于接收缓冲区里面的数据)5)编写串口发送等其他代码;(一般在按钮处理函数中实现)6)关闭串口。
以上采用MSComm控件的是事件驱动方式,即通过函数OnComm()处理。
多线程实现串口通讯

程序一般不需要直接创建CWinThread对象,通过调用AfxBeginThread()函数就会自动创建一个CWinThread对象,从而开始一个进程。创建上述的两种线程都利用这个函数。
线程的终止取决于下列事件之一:线程函数返回;线程调用ExitThread()退出;异常情况下用线程的句柄调用TerminateThread()退出;线程所属的进程被终止。
在ReadFile()和WriteFile()读写串口时,可以采取同步执行方式,也可以采取重叠I/O方式。同步执行时,函数直到执行完毕才返回,因而同步执行的其他线程会被阻塞,效率下降;而在重叠方式下,调用的读写函数会立即返回,I/O操作在后台进行,这样线程就可以处理其他事务。这样,线程可以在同一串口句柄上实现读写操作,实现"重叠"。
常用的等待函数是WaitForSingleObject()和WaitForMultipleObjects(),前者可监测单个同步对象,后者可同时监测多个同步对象。
3.3 串口通信的重叠I/O方式
MFC对于串口作为文件设备处理,用CreateFile()打开串口,获得一个串口句柄。打开后SetCommState()进行端口配置,包括缓冲区设置,超时设置和数据格式等。成功后就可以调用函数ReadFile()和WriteFile()进行数据的读写,用WaitCommEvent()监视通信事件。CloseHandle()用于关闭串口。
CEvent:事件对象,用于使一个线程通知其他线程某一事件的发生,所以也可以用来封锁对某一资源的访问,直到线程释放资源使其成为有信号状态。适用于某一线程等待某事件发生才能执行的场合。
CCriticalSection:临界区对象,将一段代码置入临界区,只允许最多一个线程进入执行这段代码。一个临界区仅在创建它的进程中有效。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.多线程串口类
使用多线程串口通信更方便的途径是编写一个多线程的串口类,例如Remon Spekreijse编写了一个CSerialPort串口类。
仔细分析这个类的源代码,将十分有助于我们对先前所学多线程及同步知识的理解。
3.1类的定义
3.2类的实现
3.2.1构造函数与析构函数
进行相关变量的赋初值及内存恢复:
3.2.2核心函数:初始化串口
在初始化串口函数中,将打开串口,设置相关参数,并创建串口相关的用户控制事件,初始化临界区(Critical Section),以成队的EnterCriticalSection()、LeaveCriticalSection()函数进行资源的排它性访问:
3.3.3核心函数:串口线程控制函数
串口线程处理函数是整个类中最核心的部分,它主要完成两类工作:
(1)利用WaitCommEvent函数对串口上发生的事件进行获取并根据事件的不同类型进行相应的处理;
(2)利用WaitForMultipleObjects函数对串口相关的用户控制事件进行等待并做相应处理。
下列三个函数用于对串口线程进行启动、挂起和恢复:
3.3.4读写串口
下面一组函数是用户对串口进行读写操作的接口:
3.3.5控制接口
应用程序员使用下列一组public函数可以获取串口的DCB及串口上发生的事件:
3.3.6错误处理
仔细分析Remon Spekreijse的CSerialPort类对我们理解多线程及其同步机制是大有益处的,从/network/serialport.shtml我们可以获取CSerialPort类的介绍与工程实例。
另外,电子工业出版社《Visual C++/Turbo C串口通信编程实践》一书的作者龚建伟也编写了一个使用CSerialPort
类的例子,可以从/scomm/sc2serialportclass.htm获得详情。