Chinaunix首页 | 论坛 | 博客
  • 博客访问: 231938
  • 博文数量: 56
  • 博客积分: 2480
  • 博客等级: 大尉
  • 技术积分: 475
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-28 10:57
文章分类

全部博文(56)

文章存档

2012年(36)

2011年(4)

2010年(2)

2009年(14)

我的朋友

分类: LINUX

2009-11-03 12:00:22



#include           /*标准输入输出定义*/
#include          /*标准函数库定义*/
#include  
#include          /*Unix标准函数定义*/
#include       /**/
#include        /**/
#include           /*文件控制定义*/
#include         /*PPSIX终端控制定义*/
#include           /*错误号定义*/

#include   

int fd;

/***@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void*/

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
38400,  19200,  9600, 4800, 2400, 1200,  300, };
void set_speed(int fd, int speed)
{
    int   i;
    int   status;
    struct termios   Opt;
    tcgetattr(fd, &Opt);
    for ( i= 0;  i <(int ) ( sizeof(speed_arr) / sizeof(int) );  i++)
    {
        if  (speed == name_arr[i])
        {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            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
*/
bool set_Parity(int fd,int databits,int stopbits,int parity)
{
    struct termios oldtio, options;
    //if  ( tcgetattr( fd,&options)  !=  0)
    if  ( tcgetattr( fd,&oldtio)  !=  0)
    {
        perror("SetupSerial 1");
        return(false);
    }
    //bzero(&options,sizeof(struct termios));
    bzero( &options, sizeof( termios ) );//这里需要注意 。
    options.c_cflag |= CLOCAL | CREAD;
    options.c_cflag &= ~CSIZE;
    switch (databits) /*设置数据位数*/
    {
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        fprintf(stderr,"Unsupported data size\n");
        return (false);
    }
    switch (parity)
    {
    case 'n':
    case 'N':   /*无校验位*/
        options.c_cflag &= ~PARENB;   /* Clear parity enable */
        options.c_iflag &= ~INPCK;     /* Enable parity checking */
        break;
    case 'o':
    case 'O': /*奇校验*/
        options.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/
        options.c_iflag |= INPCK;             /* Disnable parity checking */
        break;
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;     /* Enable parity */
        options.c_cflag &= ~PARODD;   /* 转换为偶效验*/
        options.c_iflag |= INPCK;       /* Disnable parity checking */
        break;
    case 'S':
    case 's':  /*as no parity*/
        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);
    }
    /* Set input parity option */
    if (parity != 'n')
        options.c_iflag |= INPCK;
    options.c_cc[VTIME] = 150; // 15 seconds
    options.c_cc[VMIN] = 0;

    tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
    if (tcsetattr(fd,TCSANOW,&options) != 0)
    {
        perror("SetupSerial 3");
        return (false);
    }
    else
    {
        printf(" set serial success! ");
    }

    return ( true);
}
/**
*@breif 打开串口
*/
int OpenDev(char *Dev)
{
    //int    fd = open( Dev, O_RDWR );         //| O_NOCTTY | O_NDELAY

    int    fd = open( Dev,O_RDWR | O_NOCTTY | O_NONBLOCK);         //| O_NOCTTY | O_NDELAY
    if (  -1 == fd  )
    { /*设置数据位数*/
        perror("Can't Open Serial Port");
        return -1;
    }

    if(  fcntl(fd, F_SETFL, 0)<0  )/*改变文件的状态:F-SETFL:设置文件状态标志!参考C函数实例手册P8*/
        printf("fcntl failed!\n");
    else
        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));

    if(  isatty(STDIN_FILENO)==0 )/*检查设备类型*/
        printf("standard input is not a terminal device\n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;

}

/******************************************************
* send data
* fd:串口描述符,data:待发送的数据,datalen:数据长度
* 返回实际发送长度
******************************************************/
int data_send(int fd,char *data,int datalen)
{
    int len = 0;
    len = write(fd,data,datalen);
    if (len == datalen)
    {
        return(len);
    }
    else
    {
        tcflush(fd,TCOFLUSH);
        return -1;
    }
}
/****************************************************
* receive data
* 返回实际读入的字节数
*****************************************************/
int data_Recv(int fd,char *data,int datalen )
{
    int recvlen,fd_sel;
    fd_set fs_read;
    struct timeval tv_timeout;

    FD_ZERO(&fs_read);
    FD_SET(fd,&fs_read);
    tv_timeout.tv_sec = 5;
    tv_timeout.tv_usec = 0;


    fd_sel = select(fd +1,&fs_read,NULL,NULL,&tv_timeout);
    if (fd_sel)
    {
        recvlen = read(fd,data,datalen);
        return(recvlen);
    }
    else
    {
        return -1;
    }
    return recvlen;
}


void *get_thread(void *parg);
void *put_thread(void *parg);

void *get_thread(void *parg)
{
    char k_buf[] = "abcdef";
    int writelen=0;
    while(true)
    {

        int len = data_send(fd, k_buf , 6);//write(fd, k_buf , 6 );
        if( len >0 )
        {
            writelen+=len;
            printf("write len =%d   sum write %d \n ", len,writelen );
        }

        sleep( 1);  //这里 需要 等待 。second

    }
    return NULL;
}

void *put_thread(void *parg)
{
    int readlen =1;
    char buff[512];
    while(true)
    {
        //while((nread = read(fd,buff,512))>0)
            bzero( buff, 50 );//这里需要注意 。
        int nread = data_Recv(fd,buff,512) ;
        if( nread > 0 )
        {
            buff[nread]='\0';
            readlen+= nread;
            printf("readlen = %d  readSum =%d context= %s  \n ", readlen ,nread , buff );
        }
        printf("read =%d \n",nread);
    }
    return NULL;                                       
}                                                            
/**
*@breif     main()
*/
int main(int argc, char **argv)
{
    char dev[] ="/dev/ttyS0";  // com口1

    fd = OpenDev(dev);
    if (fd>0)
    {
        printf(" Open Serial Port succes !\n");
        set_speed(fd,9600);
    }
    else
    {
        printf("Can't Open Serial Port!\n");
        exit(0);
    }
    if (set_Parity(fd,8,1,'N')== false)
    {
        printf("Set Parity Error\n");
        exit(1);
    }
    printf("set paity success ! \n");


    pthread_t pget,pput;                                 
    pthread_create( &pget,NULL,get_thread,NULL);         
    pthread_create( &pput, NULL, put_thread,NULL);
    sleep(10);
    printf("now close fd ! \n");
    sleep(2);
    close(fd);

    pthread_join( pget,NULL );                           
    pthread_join( pput,NULL );  


    close(fd);

    return 0;
    //exit(0);
}




总结:  1,linux 下 Select 的使用 ,用在 com口 read 上, 将 com口关闭,发现 ,不在阻塞线程。


阅读(1411) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~