| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 10734 人关注过本帖, 1 人收藏
标题:用C语言编程操作计算机串口,请大神们看看这个程序该怎样修改???
只看楼主 加入收藏
Andrew_Lee
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:185
专家分:626
注 册:2014-3-21
收藏
得分:0 
首先说明下我改动的我用/* modified by Andrew 2014/04/07 */注释了,楼主可以和自己的代码比较下,看看我改动了哪些,如果觉得我改动的有什么问题,我们可以再共同探讨;
第一个:CreateFile()函数的  文件的属性参数我改了。
第二个:SetupComm()和PurgeComm()我又使用了,后一个不用行不行你可以自己试验下,我没有实验
第三个:对nwrite进行了简单的循环,计算实际写入串口的字节数
第四个:将SetFilePointer()注释掉了,我调试过,基本0影响,如果要是不确定要读多少字节的话,不妨把接收的空间申请大一些
第五个:buffRead=(char *)malloc(1024);只要注意一点就可以了:实际申请的空间要比理论上至少多上3个字节的空间。这里1024是我自己写的,你可以自己设置。
第六个:ReadFile(hCom,buffRead,nwrite,&dwBytesRead,NULL)这里我将nread改成了nwrite就是将我写的数据都读出来(调试简单),你可以自己根据需要读取数据的大小自行填充
第七个:就是最后两个free内存释放函数,我估计你开始那个两三次以后出现的以外退出就是因为malloc和free操作不当引起的。
最后还有点就是:最好不要使用goto语句,据说会带来编程的混乱。你可以在一个while(1)循环里进行对串口的操作。
基本没打乱你的代码结构,最后主函数不要这么藏,可以讲这个拆成各个子函数,条理会清楚些
你在看看还有没有什么问题,我用VC6.0调试的没有什么问题,也没有意外退出:
程序代码:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <commdlg.h>
#include <windef.h>

#define BAUD_RATE 9600
#define p printf
#define size 1024

int nread,nwrite;
void main()
{
    int temp;
    HANDLE hCom;
    COMMTIMEOUTS timeouts;
    COMMCONFIG dcb;
    char *buffRead;
    char *buffWrite;
    DWORD dwBytesWritten,dwBytesRead;
  
    retry:
    /*  把串口作为文件打开  */
    hCom=CreateFile("COM4",                       //打开串口1
                GENERIC_READ|GENERIC_WRITE,       //允许读写
                0,                                //通讯设备必须以独占方式打开
                NULL,                             //安全属性
                OPEN_EXISTING,                    //通讯设备已存在
                /*FILE_FLAG_OVERLAPPED*/0,             //异步I/O        /* modified by Andrew 2014/04/07 */                                       

                NULL);  

    if(hCom==(HANDLE)-1)                          //打开串口失败返回
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            p("serial port does exist.\n");
        }
        p("some other error occured, Inform user.\n");
    }
    else
        p("port open successed!\n");

    /*  串口超时结构体设置  */
    SetCommTimeouts(hCom,&timeouts);
    //COMMTIMEOUTS timeouts={0};
 
    timeouts.ReadIntervalTimeout=1000;            //接收时两字符之间的最大时延
    timeouts.ReadTotalTimeoutMultiplier=500;      //指定以毫秒为单位的累积值,用于计算读操作时的超时总数
    timeouts.ReadTotalTimeoutConstant=5000;       //指定以毫秒为单位的常数,用于计算读操作时的超时总数
    timeouts.WriteTotalTimeoutMultiplier=500;     //计算写操作时的超时总数
    timeouts.WriteTotalTimeoutConstant=2000;       //计算写操作时的超时总数
    
    if(!SetCommTimeouts(hCom,&timeouts))          //与串口绑定失败返回
    {
        p("error setting port state.\n");
    }
  
    /* 设置串口各项参数  */
    if(!GetCommState(hCom,&dcb.dcb))
    {
    p("error setting serial port state.\n");  //串口绑定失败
    }
    dcb.dcb.BaudRate=BAUD_RATE;     //波特率为9600
    dcb.dcb.ByteSize=8;             //设置数据位
    dcb.dcb.Parity=EVENPARITY;      //偶校验
    dcb.dcb.StopBits=2;             //两个停止位
    dcb.dcb.fBinary=TRUE;
    dcb.dcb.fParity=TRUE;

    if(!SetCommState(hCom,&dcb.dcb))                  //DCB绑定失败返回
    {
        p("串口设置出错!");
    }

   /*  设置串口输入输出缓冲区  */
    if(!SetupComm(hCom,1024,1024))                //设置串口的输入/输出缓冲区大小
    {
    p("设置串口读写缓冲区失败");
    }
    PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);  //终止所有的后台读写操作并清空缓冲区 

    /*  将数据写入缓冲区操作  */
    buffWrite=(char *)malloc(size);             //输入缓冲区分配
        p("please input yourdata:");
    scanf("%s",buffWrite);
    //nwrite=255; 

    /*modified by Andrew 2014/04/07*/
    nwrite = 0;

    for(temp = 0;buffWrite[temp]!='\0';temp++)
    {
        nwrite++;
    }
    /* Anrew modified over*/

    if(!WriteFile(hCom,buffWrite,nwrite,&dwBytesWritten,NULL))
    {
        p("error writting to output buffer.\n");
    }
    else
        p("written data:%s\n",buffWrite);
        system("pause");                       //调用系统命令pause,输出类似于“press any key to exit”的字

    /*  从输出缓冲区读取数据操作  */
    // buffRead=0;

    /* delete by Andrew 2014/04/07*/
       //buffRead=(char *)malloc(size);

    /*  在缓冲区设置当前的读写位置  */
    /*     SetFilePointer(hCom,                 //问价句柄
             0,                               //偏移量(低位)
             0,                               //偏移量(高位)
             FILE_BEGIN);                     //基准位置
     nread=GetFileSize(hCom,NULL);
    */

    /*  Andrew delete over */
     buffRead=(char *)malloc(1024);
     memset(buffRead,0,1024);                 //将缓冲区的前1024个字节用0代替,相当于初始化

     if(!ReadFile(hCom,buffRead,nwrite,&dwBytesRead,NULL))                 /*modified by Andrew 2014/04/07*/
     {
     p("error reading from input buffer.\n");
     }
     else
     {
         p("Data read from read buffer is:%s\n",buffRead);
     }

    /*  关闭串口  */
  CloseHandle(hCom);       //关闭设备句柄
       
/*modified by Andrew 2014/04/07 */
         free(buffWrite);
         free(buffRead);
/* Andrew modified over */ 

         Sleep(2000);
         goto retry;
  }



[ 本帖最后由 Andrew_Lee 于 2014-4-7 20:29 编辑 ]
2014-04-07 20:20
一叶扁舟2014
Rank: 1
等 级:新手上路
帖 子:8
专家分:0
注 册:2014-4-1
收藏
得分:0 
回复 11 楼 Andrew_Lee
/*  串口初始化程序  cominit.c   */  

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BAUD_RATE 9600
#define pr printf
        
void  serialinit(int hcom)
{
   
    COMMTIMEOUTS timeouts;            //超时函数设置
    COMMCONFIG dcb;                   //dcb的参数配置

    /*  把串口作为文件打开  */
    hcom=CreateFile("COM1",               //打开串口1,hcom为串口句柄
        GENERIC_READ|GENERIC_WRITE,       //允许读写
        0,                                //通讯设备必须以独占方式打开
        NULL,                             //安全属性
        OPEN_EXISTING,                    //通讯设备已存在
        0,                                //异步I/O  /*FILE_FLAG_OVERLAPPED*/                  
        NULL);  
   
    if(hcom==(HANDLE)-1)                  //打开串口失败返回
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            pr("serial port does exist.\n");
        }
        pr("some other error occured, Inform user.\n");
    }
    else
        pr("port open successed!\n");
   
    /*  串口超时结构体设置  */
    SetCommTimeouts(hcom,&timeouts);
    //COMMTIMEOUTS timeouts={0};
   
    timeouts.ReadIntervalTimeout=1000;            //接收时两字符之间的最大时延
    timeouts.ReadTotalTimeoutMultiplier=500;      //指定以毫秒为单位的累积值,用于计算读操作时的超时总数
    timeouts.ReadTotalTimeoutConstant=5000;       //指定以毫秒为单位的常数,用于计算读操作时的超时总数
    timeouts.WriteTotalTimeoutMultiplier=500;     //计算写操作时的超时总数
    timeouts.WriteTotalTimeoutConstant=2000;       //计算写操作时的超时总数
   
    if(!SetCommTimeouts(hcom,&timeouts))          //与串口绑定失败返回
    {
        pr("error setting port state.\n");
    }
   
    /* 设置串口各项参数  */
    if(!GetCommState(hcom,&dcb.dcb))
    {
        pr("error setting serial port state.\n");  //串口绑定失败
    }
    dcb.dcb.BaudRate=BAUD_RATE;     //波特率为9600
    dcb.dcb.ByteSize=8;             //设置数据位
    dcb.dcb.Parity=EVENPARITY;      //偶校验
    dcb.dcb.StopBits=1;             //一个停止位
    dcb.dcb.fBinary=TRUE;
    dcb.dcb.fParity=TRUE;
   
    if(!SetCommState(hcom,&dcb.dcb))                  //DCB绑定失败返回
    {
        pr("串口设置出错!\n");
    }
}

   
/*=======================================*/
/*          depthrecv.c                  */
/*   数据接收程序,调用串口初始化程序    */
/*          hcom6对应串口描述符          */
/*=======================================*/

#include <string.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "cominit.c"


  #define size6 30
  #define pr printf
  char com[7];                          //串口接收的数据帧
// char depth_str1={"00000000"};        //截取后的数据帧,初始值为零

  //float depth1;                         //浮点型深度数据

  extern void serialinit(int hcom);
  
  void main()
  {  int hcom6;
     int nwrite;
     int inum=0,temp=0;
     int depthstate=1;
     char *readbuff6;                   //数据接收缓冲区
     char *writebuff6;                  //数据写入缓冲区
     int pos=0;
     DWORD dwBytesWritten,dwBytesRead;
     serialinit(hcom6);
      
     /* 设置串口输入输出缓冲区  */  
     if(!SetupComm(hcom6,1024,1024))
     {
         pr("设置串口读写缓冲区失败!\n");
     }
     PurgeComm(hcom6,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

    /*  将数据写入缓冲区操作  */
    writebuff6=(char *)malloc(size6);
    pr("please input your data:");
     scanf("%s",writebuff6);
    nwrite=0;
   for(temp = 0;writebuff6[temp]!='\0';temp++)
    {
        nwrite++;
    }
    if(!WriteFile(hcom6,writebuff6,nwrite,&dwBytesWritten,NULL))
     { pr("error writting to output buffer.\n");}
     else
       pr("written data:%s\n",writebuff6);
       system("pause");
   
    /* 从输出缓冲区读数据 */
    readbuff6=(char *)malloc(size6);  
    memset(readbuff6,0,size6);            //将缓冲区的前size6个字节用0代替,相当于初始化
    if(!ReadFile(hcom6,readbuff6,size6,&dwBytesRead,NULL))
    {   pr("error reading from input buffer\n");
    }
    else  
        pr("Data read from buffer is:%s\n",readbuff6);
    /*  关闭串口  */
    CloseHandle(hcom6);  //关闭设备句柄
    free(readbuff6);
    free(writebuff6);
 }
2014-04-19 19:49
Andrew_Lee
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:185
专家分:626
注 册:2014-3-21
收藏
得分:0 
回复 12 楼 一叶扁舟 2014
程序代码:
/*  串口初始化程序  cominit.c   */ 

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BAUD_RATE 9600
#define pr printf  
                                                            /*******Andrew:这个初始化函数中,所有用到hcom的地方,都改用*hcom指针操作*/
void  serialinit(HANDLE* hcom)                              /*******Andrew modified 1*/
{
    COMMTIMEOUTS timeouts;            //超时函数设置
    COMMCONFIG dcb;                   //dcb的参数配置
 
     /*  把串口作为文件打开  */
    *hcom=CreateFile("COM5",               //打开串口1,hcom为串口句柄
        GENERIC_READ|GENERIC_WRITE,       //允许读写
        0,                                //通讯设备必须以独占方式打开
        NULL,                             //安全属性
        OPEN_EXISTING,                    //通讯设备已存在
        0,                                //异步I/O  /*FILE_FLAG_OVERLAPPED*/                
        NULL);

    if(*hcom==(HANDLE)-1)                  //打开串口失败返回
    {
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
        {
            pr("serial port does exist.\n");
        }
        pr("some other error occured, Inform user.\n");
    }
    else
        pr("port open successed!\n");

    /*  串口超时结构体设置  */
    GetCommTimeouts(*hcom,&timeouts);                                             /* Andrew modified */
    //COMMTIMEOUTS timeouts={0};
 
    timeouts.ReadIntervalTimeout=1000;            //接收时两字符之间的最大时延
    timeouts.ReadTotalTimeoutMultiplier=500;      //指定以毫秒为单位的累积值,用于计算读操作时的超时总数
    timeouts.ReadTotalTimeoutConstant=5000;       //指定以毫秒为单位的常数,用于计算读操作时的超时总数
    timeouts.WriteTotalTimeoutMultiplier=500;     //计算写操作时的超时总数
    timeouts.WriteTotalTimeoutConstant=2000;       //计算写操作时的超时总数
 
    if(!SetCommTimeouts(*hcom,&timeouts))          //与串口绑定失败返回
    {
        pr("error setting port state.\n");
    }

    /* 设置串口各项参数  */
    if(!GetCommState(*hcom,&dcb.dcb))
    {
        pr("error setting serial port state.\n");  //串口绑定失败
    }
    dcb.dcb.BaudRate=BAUD_RATE;     //波特率为9600
    dcb.dcb.ByteSize=8;             //设置数据位
    dcb.dcb.Parity=EVENPARITY;      //偶校验
    dcb.dcb.StopBits=1;             //一个停止位                               /*Andrew modified 1,我的电脑需要2位停止位*/
    dcb.dcb.fBinary=TRUE;
    dcb.dcb.fParity=TRUE;

 
    if(!SetCommState(*hcom,&dcb.dcb))                  //DCB绑定失败返回
    {
        pr("串口设置出错!\n");
    }
}


/*=======================================*/
/*          depthrecv.c                  */
/*   数据接收程序,调用串口初始化程序    */
/*          hcom6对应串口描述符          */
/*=======================================*/

#include <string.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//#include "cominit.c"                                                   /*Andrew modified 1*/


 #define size6 30

 #define pr printf

 char com[7];                          //串口接收的数据帧
//char depth_str1={"00000000"};        //截取后的数据帧,初始值为零


 //float depth1;                         //浮点型深度数据


 extern void serialinit(HANDLE* hcom);                                  /*Andrew modified 2*/


 void main()

 {  HANDLE hcom6;                                                       /*Andrew modified 3*/
    int nwrite;
    int inum=0,temp=0;
    int depthstate=1;
    char *readbuff6;                   //数据接收缓冲区
    char *writebuff6;                  //数据写入缓冲区
    int pos=0;
    DWORD dwBytesWritten,dwBytesRead;
    serialinit(&hcom6);                                                /*Andrew modified 4*/

    /* 设置串口输入输出缓冲区  */ 

    if(!SetupComm(hcom6,1024,1024))
    {
        pr("设置串口读写缓冲区失败!\n");
    }
    PurgeComm(hcom6,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

   /*  将数据写入缓冲区操作  */
   writebuff6=(char *)malloc(size6);
   pr("please input your data:");
   scanf("%s",writebuff6);
   nwrite=0;
   for(temp = 0;writebuff6[temp]!='\0';temp++)
   {
       nwrite++;
   }
   if(!WriteFile(hcom6,writebuff6,nwrite,&dwBytesWritten,NULL))
    { pr("error writting to output buffer.\n");}
    else
      pr("written data:%s\n",writebuff6);
      system("pause");

 
   /* 从输出缓冲区读数据 */
   readbuff6=(char *)malloc(size6); 

   memset(readbuff6,0,size6);            //将缓冲区的前size6个字节用0代替,相当于初始化
   if(!ReadFile(hcom6,readbuff6,size6,&dwBytesRead,NULL))
   {   pr("error reading from input buffer\n");
   }
   else 

       pr("Data read from buffer is:%s\n",readbuff6);
   /*  关闭串口  */
   CloseHandle(hcom6);  //关闭设备句柄
   free(readbuff6);
   free(writebuff6);
} 
2014-04-20 09:45
qq67651306
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2014-4-22
收藏
得分:0 
来看看的~~~~~~~~~
2014-04-22 08:56
快速回复:用C语言编程操作计算机串口,请大神们看看这个程序该怎样修改???
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.022797 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved