kong 发表于 2009-11-15 22:25:05

初学上位机串口编程,基于API的控制台串口代码,VC6.0编译通过

初学PC机串口编程,基于多线程,异步操作,事件驱动的控制台程序,
在VC6.0下编译通过,使用时不占用cpu时间,当有数据到达接收缓冲区时,读取数据,
如要发送数据,直接在主函数里面调用API的发送数据函数即可,
将代码贴上,希望高手不吝指点,以便提高我的编程能力!!!
// bn.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>


void init_com(void);//定义串口初始化函数
DWORD WINAPI Thread1Proc(LPVOID lParam);//定义子线程函数
CRITICAL_SECTION com_cs;//定义临界变量对象


struct Thread_Data//定义一个结构类型,用于传参数给子线程
{
                HANDLE hcom;
                OVERLAPPED vcc;               
};
unsigned char receive_data;//定义接收数据缓存


int main(int argc, char* argv[])
{
        InitializeCriticalSection(&com_cs);//初始化临界变量

        init_com();        //初始化串口
        while(1)
        {
                Sleep(200);//使主线程挂起
        }
        return 0;
}

void init_com()
{
        EnterCriticalSection(&com_cs);//进入临界段
        //1.////////////////////////////////////////////////////////        打开串口
        HANDLE m_hCom = NULL;//定义一个句柄,用于打开串口
        HANDLE hThread1 = NULL;//子线程句柄;
        COMMTIMEOUTS TimeOuts;//定义超时结构
        DCB dcb;                        //定义串口设备控制结构
        OVERLAPPED wrOverlapped;//定义异步结构
        static struct Thread_Datathread_data;//定义一个结构对象,用于给子线程传递参数
               
        m_hCom = CreateFile("com1",GENERIC_READ | GENERIC_WRITE, 0, NULL,

                                                OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

        if (m_hCom == INVALID_HANDLE_VALUE)
        {
                printf("CreateFile fail\n");
        }
        else
        {
                printf("CreateFile ok\n");
        }

//2.////////////////////////////////////////////////////////设置读写缓冲区
        if(SetupComm(m_hCom,2048,2048))
        {
                printf("buffer ok\n");
        }
        else
        {
                printf("buffer fail\n");
        }
//3.///////////////////////////////////////////////设置串口操作超时

        //memset(&TimeOuts,0,sizeof(TimeOuts));
        TimeOuts.ReadIntervalTimeout = 1000;
        TimeOuts.ReadTotalTimeoutConstant = 1000;
        TimeOuts.ReadTotalTimeoutMultiplier = 1000;
        TimeOuts.WriteTotalTimeoutConstant = 1000;
        TimeOuts.WriteTotalTimeoutMultiplier = 1000;
        if(SetCommTimeouts(m_hCom,&TimeOuts))
        {
                printf("comm time_out ok!\n");}
       
//4./////////////////////////////////////////////////////////设置串口参数
       
        if (GetCommState(m_hCom,&dcb))
        {
                printf("getcommstate ok\n");
        }
        else
        {
                printf("getcommstate fail\n");
        }

        ////////////
        dcb.DCBlength = sizeof(dcb);
        if (BuildCommDCB("9600,n,8,1",&dcb))//填充DCB的数据传输率、奇偶校验类型、数据位、停止位
        {
                printf("buildcommdcb ok\n");
        }
        else
        {
                printf("buildcommdcb fail\n");
        }
        ////////////
        if(SetCommState(m_hCom,&dcb))
        {
                printf("setcommstate ok\n");
        }
        else
        {
                printf("setcommstate fail\n");
        }
//5.///////////////////////////////////////////////////////////////////初始化异步结构
        ZeroMemory(&wrOverlapped,sizeof(wrOverlapped));
        wrOverlapped.Offset = 0;
        wrOverlapped.OffsetHigh = 0;

        if (wrOverlapped.hEvent != NULL)
        {
                ResetEvent(wrOverlapped.hEvent);
        }
        wrOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//创建手工复位事件
        ///////////////////////////创建一个线程//////////////////////////////////////////

        thread_data.vcc = wrOverlapped;
        thread_data.hcom = m_hCom;///////////////////////////////////////
        hThread1=CreateThread(NULL,0,Thread1Proc,(LPVOID)&thread_data,0,NULL); //『注意』创建线程

        LeaveCriticalSection(&com_cs);//推出临界段

}

DWORD WINAPI Thread1Proc(LPVOID lParam) //线程的执行函数
{
       
        Thread_Data* pThread_Data = (Thread_Data*)lParam;///将线程函数参数给新定义的结构指针

        HANDLE com= pThread_Data->hcom;////通过新定义的结构指针使用原结构的成员

        OVERLAPPED wrOverlapped1 = pThread_Data->vcc;/////通过新定义的结构指针使用原结构的成员
       
        COMSTAT ComStat ;///定义一个串口状态结构对象,给结构有10个参数,第九个参数
                          /////DWORD cbInQue;表示出入缓冲区有多少字节的数据到达,
       
        DWORD word_count;//////存放实际读到的数据字节数存放
        DWORD Event = 0;
        DWORD CommEvtMask=0 ;
        DWORD result;
        DWORD error;
        unsigned int k;

        SetCommMask(com,EV_RXCHAR);//设置串口等待事件
       
        while(1)
        {       
               
                result = WaitCommEvent(com,&CommEvtMask,&wrOverlapped1);//等待事件函数
                if(!result)
                {
                        switch(error = GetLastError())
                        {
                                case ERROR_IO_PENDING :
                                        {
                                                break;
                                        }
                                case 87:
                                        {
                                                break;
                                        }
                                default:
                                        {
                                                break;
                                        }
                        }

                }
                else
                {
                        result = ClearCommError(com,&error,&ComStat);
                        if(ComStat.cbInQue == 0)
                        {
                                continue;
                        }
                }

                Event = WaitForSingleObject(wrOverlapped1.hEvent,INFINITE);//异步结果等待函数

                EnterCriticalSection(&com_cs);
                result = ClearCommError(com,&error,&ComStat);
                if(ComStat.cbInQue == 0)
                {
                        continue;
                }
                ReadFile(com,receive_data,ComStat.cbInQue,&word_count,&wrOverlapped1);//从系统接收缓冲区读出接收到得所有数据
                LeaveCriticalSection(&com_cs);//推出临界段

                printf("%s\n",receive_data);
                for(k=0;k<50;k++)
                {
                        receive_data = 0x00;
       
                }
        }
       
        return 0;
}

wychao 发表于 2009-11-15 22:59:33

好像没有用控件,厉害啊,没有玩过

kong 发表于 2009-11-16 19:19:39

串口应用程序一般有三种:使用微软的控件,使用第三方类,还有就是使用系统给的API,
使用系统给的API很灵活,也很方便,
用API函数写的基于控制台的代码,运行在后台,

遇到一个问题:在串口程序异常关闭后,没有机会去关掉打开的串口句柄,当再次打开串口时,发现
串口已经被占用,路过的前辈指点下:

如何通过串口名或者其他的东西找到一个已经打开但是丢失句柄的串口??

alexmayer 发表于 2009-11-17 10:50:03

既然是异常关闭,你就应该在异常处理中负责清理现场。

cz_hust_ei 发表于 2010-1-7 11:23:03

回复【楼主位】kong 雷神
-----------------------------------------------------------------------
小弟现在也正要用API进行串口编程,你给的程序直接编译很多问题啊!能否将源代码发至我邮箱cz_hust_ei@163.com,十分感激!

rainbowu 发表于 2010-3-29 20:18:30

mark

hgnuist 发表于 2010-4-9 09:03:35

楼主能否将源码发至小弟邮箱?bryant87061322@163.com十分感谢!

lizhoubob 发表于 2010-4-23 08:51:45

关注.VC

hz100 发表于 2010-4-23 17:27:44

楼主将邮件发到我的邮箱,另外再附上详细说明,十分感谢
cz_hust_ei@163.com
bryant87061322@163.com

gloryzkl 发表于 2011-4-26 22:30:20

mark

hao234hao234 发表于 2011-6-2 11:11:27

mark

442502587 发表于 2014-4-25 23:35:13

明天试一试
页: [1]
查看完整版本: 初学上位机串口编程,基于API的控制台串口代码,VC6.0编译通过