搜索
bottom↓
回复: 11

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

[复制链接]

出0入0汤圆

发表于 2009-11-15 22:25:05 | 显示全部楼层 |阅读模式
初学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[50];//定义接收数据缓存


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_Data  thread_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[k] = 0x00;
       
                }
        }
       
        return 0;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2009-11-15 22:59:33 | 显示全部楼层
好像没有用控件,厉害啊,没有玩过

出0入0汤圆

 楼主| 发表于 2009-11-16 19:19:39 | 显示全部楼层
串口应用程序一般有三种:使用微软的控件,使用第三方类,还有就是使用系统给的API,
使用系统给的API很灵活,也很方便,
用API函数写的基于控制台的代码,运行在后台,

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

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

出0入0汤圆

发表于 2009-11-17 10:50:03 | 显示全部楼层
既然是异常关闭,你就应该在异常处理中负责清理现场。

出0入0汤圆

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

出0入0汤圆

发表于 2010-3-29 20:18:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-9 09:03:35 | 显示全部楼层
楼主能否将源码发至小弟邮箱?bryant87061322@163.com  十分感谢!

出0入0汤圆

发表于 2010-4-23 08:51:45 | 显示全部楼层
关注.VC

出0入0汤圆

发表于 2010-4-23 17:27:44 | 显示全部楼层
楼主将邮件发到我的邮箱,另外再附上详细说明,十分感谢
cz_hust_ei@163.com
bryant87061322@163.com

出0入0汤圆

发表于 2011-4-26 22:30:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-2 11:11:27 | 显示全部楼层
mark

出10入12汤圆

发表于 2014-4-25 23:35:13 | 显示全部楼层
明天试一试
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 09:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表