LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 827|回复: 6

求助:串口通信源代码分析

[复制链接]
发表于 2004-5-9 11:14:23 | 显示全部楼层 |阅读模式
[php]
/*----------------------------------------

                                            ==========================================        
                                                  Linux操作系统下串口编程
                                                                ===========================================                   
                                                                --------------------------------------------*/



#include     <stdio.h>                                        /*标准输入输出定义*/
#include     <stdlib.h>                                        /*标准函数库定义*/
#include     <unistd.h>                                        /*Unix 标准函数定义*/
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>                                        /*文件控制定义*/
#include     <termios.h>                                /*PPSIX 终端控制定义*/
#include     <errno.h>                                        /*错误号定义*/



#define                COM1        1                                        //"/dev/ttyS0"                //串口一
#define                COM2        2                          //"/dev/ttyS1"                //串口二



#define         TURE    0
#define         FALSE   -1  




class        Ctermios
{
public:         Ctermios();                //构造函数
                ~Ctermios();                                //析构函数
                void OpenSerialPort(int);           //打开串口
                void CloseSerialPort();                                //关闭串口
                void ReadSerialPort();                                //从串口中读取数据
                void WriteSerialPort();                        //向串口写入数据
                void SetSerialPort();
               
private:
          struct termios opt;
          int                 fd;
          char         buffR[512];
          char    buffW[512];  
          int               LenR;
          int           LenW;
       
        
          int OpenDev(char *Dev);
          void set_speed(int fd,int speed);
          int set_Parity(int fd,int databits,int stopbits,int parity);


}

/*--------------------------------------------------
                    构造函数
---------------------------------------------------*/   
Ctermios::Ctermios()
{
        struct termios opt
        LenR = 512;
          LenW = 512;
}



/*--------------------------------------------------
                    析构函数
----------------------------------------------------*/
/*Ctermios::~Ctermios()
{
        tcflush(fd,TCIOFLUSH);   //清数据机线并启动序列阜的设定
        if(close(fd)==0)
                exit(0);
}
*/



/*==================================================================
                      私有函数   初始化串口
===================================================================*/


int        Ctermios::OpenDev(char *Dev)
{
        int        fd = open( Dev, O_RDWR );
        //| O_NOCTTY | O_NDELAY       
        if (fd == -1)       
        {                        
                perror("Can't Open Serial Port");        //打开串口文件时发生错误
                return -1;               
        }       
        else       
                return fd;                                                        //返回文件ID
}




/*=========================================================================
                    设置串口通信速率

  fd     类型 int  打开串口的文件句柄
  speed  类型 int  串口速度
                    return  void
==========================================================================*/
void Ctermios::set_speed(int fd,int speed)
{
  int i;
  int status;
  int     name_arr[]={38400,19200,9600,4800,2400,1200,300, 38400,19200,9600,4800,2400,1200,300 ,};
  int     speed_arr[]={B38400,B19200,B9600,B4800,B2400,B1200,B300, B38400,B19200,B9600,B4800,B2400,B1200,B300 ,};
  struct termios Opt;
  tcgetattr(fd,&Opt);
  for(i=0;i<sizeof(speed_arr)/sizeof(int);i++)
  {
    if (speed==name_arr)
   {
    tcflush(fd,TCIOFLUSH);
    cfsetispeed(&Opt,speed_arr);
    cfsetospeed(&Opt,speed_arr);
    status=tcsetattr(fd,TCSANOW,&Opt);
    if (status!=0)
       perror("tcsetattr fd1");
       return;
    }
tcflush(fd,TCIOFLUSH);
  }
}
/*=========================================================================*/



/*==================================================================

                   私有函数   设置校验位


*@brief   设置串口数据位,停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄
*@param  databits 类型  int 数据位   取值 为 7 或者8
*@param  stopbits 类型  int 停止位   取值为 1 或者2
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
=====================================================================*/
int Ctermios::set_Parity(int fd,int databits,int stopbits,int parity)
{
  struct termios options;
  if (tcgetattr(fd,&options)!=0)
  {
    perror("SetupSerial 1");
    return(FALSE);
  }
  options.c_cflag&=~CSIZE;
  switch(databits)
  {
    case 7:
         options.c_cflag|=CS7;
         break;
    case 8:
         options.c_cflag|=CS8;
         break;
    default:
         fprintf(stderr,"Unsuipported data size\n");
         return(FALSE);
  }
  switch(parity)
  {
    case'n':
    case'N':
         options.c_cflag&=~PARENB;

         options.c_iflag&=~INPCK;
         break;
    case'o':
    case'O':   
         options.c_cflag|=(PARODD|PARENB);
         options.c_iflag|=INPCK;
         break;
    case'e':
    case'E':
         options.c_cflag|=PARENB;
         options.c_cflag&=~PARODD;
         options.c_iflag|=INPCK;
         break;
    case's':
    case'S':
         options.c_cflag&=~PARENB;
         options.c_cflag&=~CSTOPB;
         break;
    default:
         fprintf(stderr,"Unsupported parity\n");
         return(FALSE);        
  }
  switch(stopbits)
  {
     case 1:
          options.c_cflag&=~CSTOPB;
          break;
     case 2:
          options.c_cflag|=CSTOPB;
          break;
     default:
          fprintf(stderr,"Unsupported stop bits\n");
          return(FALSE);
  }
  if (parity!='n')
          options.c_iflag|=INPCK;
     options.c_cc[VTIME]=150;
     options.c_cc[VMIN]=0;
     
     tcflush(fd,TCIFLUSH);
     if(tcsetattr(fd,TCSANOW,&options)!=0)
       {
          perror("SetupSerial 3");
          return(FALSE);
       }  
     return(TURE);
}

/*=========================================================================*/




/*---------------------------------------------------------
           公有函数  打开串口         
-------------------------------------------------------*/
void Ctermios::OpenSerialPort(int com)
{
        char *dev ;
        switch(com)
        {
        case        COM1:
                dev  = "/dev/ttyS0"; break;
        case        COM2:
                dev  = "/dev/ttyS1"; break;
        default:
                exit(-1);
        }
        fd=OpenDev(dev);
        set_speed(fd,B9600);
        if(set_Parity(fd,8,1,'N') == 0)
        {
                printf("Set Parity Error\n");
                exit(-1);
        }
       

}



/*---------------------------------------------------------
==========================================================
           公有函数  设置串口属性         
===========================================================
-------------------------------------------------------*/
void Ctermios::SetSerialPort()
{
        int sp;
    printf("please input baute rate\n");
        printf("default rate please input 9600");
        scanf("%d",&sp);
        set_speed(fd,sp);
        int dt,st;
        printf("please input databits stopbits \n");
    printf("default rate please input 8 1 ");
    scanf("%d %d",&dt,&st);
        if(set_Parity(fd,dt,st,'N')==FALSE)
        {
                printf("Set Parity Error\n");
                exit(0);
         }

}



/*---------------------------------------------------------
==========================================================
           公有函数  读取串口信息         
===========================================================
-------------------------------------------------------*/
void Ctermios::ReadSerialPort()
{
        int nread;
        while(nread!=0)
        {
                while((nread=read(fd,buffR,511)>0))
                {
                        printf("\nLen %d\n",nread);
                        buffR[nread+1]='\0';
                        printf("\n%s",buffR);
                 }
                if (nread==-1)
                {
                        printf("read error!\n");
                        exit(-1);
                 }
         }


}



/*---------------------------------------------------------
==========================================================
           公有函数  发送串口信息         
===========================================================
-------------------------------------------------------*/
void Ctermios::WriteSerialPort()
{
        int nwrite;
        char bb;
        int i;
        while(nwrite!=-1)
        {
                for(i=0;i<512;i++)
                {
            bb=getchar();
                        buffW=bb;
                 }
                nwrite=write(fd,buffW,512);
         }
}



/*---------------------------------------------------------
==========================================================
           公有函数  关闭串口         
===========================================================
-------------------------------------------------------*/

void Ctermios::CloseSerialPort()
{  
    close(fd);
}



/*---------------------------------------------------------
==========================================================
           main函数  联调测试用         
===========================================================
-------------------------------------------------------*/


main ()
{
   Ctermios T;
   printf("please input which serial port you want to use! \n");
   printf("1 or 2 ?");
   int a,b;
   scanf("%d",&a);
   T.OpenSerialPort(a);
   printf("you want to reserve or send\n");
   printf("reserve pease  press 1 and send for 2\n");
   scanf("%d",&b);
   switch(b)
  {
     case 1:
          T.ReadSerialPort();
          break;
     case 2:
          T.WriteSerialPort();
          break;
     default:
          printf("wrong input!");
   }
   T.CloseSerialPort();
}
[/php]
59行有错误   g++编译后有错误   显示为iso c++ forbids defining types within return type return type specification for constructor invalid  
本人接触linux时间太短,想不出来怎么解决了  
请大家给些宝贵意见   
这厢先谢过了
 楼主| 发表于 2004-5-9 11:19:33 | 显示全部楼层

说明

问题出在构建函数里面  
我搞不懂怎么才能把结构体termios封装在类Ctermios中呢  
是不是可以在Ctermios中定义一个内部变量是termios呢?
发表于 2004-5-9 16:31:22 | 显示全部楼层
程序可以编译通过,关键是程序中少了两个逗号,一个在class Ctermios定义的大括号后面,另一个在构造函数Ctermios中struct termios opt的后面。加上这两个逗号后,再加上解构函数的定义,就可以编译通过。
但我觉得在构造函数中声明struct termios opt似乎没有必要,opt已经是类的私有成员了,这样声明也不能正确的初始化。
btw:自己敲代码是个好习惯,但要细心一些。
发表于 2004-5-9 16:34:00 | 显示全部楼层
这是我调试通过的程序,你看看。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主| 发表于 2004-5-9 21:15:40 | 显示全部楼层
多谢斑竹,辛苦了。我在红帽9用g++编译下构造函数有问题。你有时间的话可以对我的程序提些意见么
发表于 2004-5-10 19:13:29 | 显示全部楼层

回复: 说明

最初由 无人喝彩 发表
问题出在构建函数里面  
我搞不懂怎么才能把结构体termios封装在类Ctermios中呢  
是不是可以在Ctermios中定义一个内部变量是termios呢?

结构在c++中是被当作一种特殊的类来处理的,可以参考封装类的方法。看看zhcon的源代码或许会有帮助。
 楼主| 发表于 2004-5-11 20:53:27 | 显示全部楼层
此代码已经调通,又作了一些修改。
不过通信两方收发不同步
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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