主题 : linux串口通信问题 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 54790
精华: 0
发帖: 25
金钱: 125 两
威望: 25 点
综合积分: 50 分
注册时间: 2011-09-06
最后登录: 2015-06-02
楼主  发表于: 2011-09-19 17:03

 linux串口通信问题

我在虚拟机上添加了串口,但是运行程序,串口收不到数据。
我使用tty0 的时候,会出现nread=0。使用tty1的时候,没有显示,只能显示到set done!fd=3
不知道是什么问题。
另外,编译下载到开发板上也不行。
以下是我的测试程序
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if  ( tcgetattr( fd,&oldtio)  !=  0)
        { //保存以前的串口参数
            perror("SetupSerial 1");
            return -1;
        }
    bzero( &newtio, sizeof( newtio ) );//把结构体里的内容全部设为0
    newtio.c_cflag  |=  CLOCAL | CREAD; //本地访问,可读取
    newtio.c_cflag &= ~CSIZE; //清空标记

    switch( nBits )//数据位
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch( nEvent ) //设置校验位
    {
    case 'O':
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':  
        newtio.c_cflag &= ~PARENB;
        break;
    }

switch( nSpeed )
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default: //默认方式
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )//是否设置停止位
        newtio.c_cflag &=  ~CSTOPB;
    else if ( nStop == 2 )
        newtio.c_cflag |=  CSTOPB;
    
    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 0;  //最小时间、等待时间
    
    tcflush(fd,TCIFLUSH);
    
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
        {
            perror("com set error");
            return -1;
        }
    printf("set done!\n");
    return 0;
}

int open_port(int fd,int comport)
{
    char *dev[]={"/dev/tty0","/dev/tty1","/dev/tty2"};
    long  vdisable;
    if (comport==1)
        {    
            fd = open( "/dev/tty0", O_RDWR|O_NOCTTY|O_NDELAY);
            if (-1 == fd)
                {
                    perror("Can't Open Serial Port");
                    return(-1);
                }
            else
                printf("open tty0 .....\n");
        }
    else if(comport==2)
        {    
            fd = open( "/dev/tty1", O_RDWR|O_NOCTTY|O_NDELAY);
            if (-1 == fd)
                {
                    perror("Can't Open Serial Port");
                    return(-1);
                }
            else
                printf("open tty1 .....\n");
        }
    else if (comport==3)
        {
            fd = open( "/dev/tty2", O_RDWR|O_NOCTTY|O_NDELAY);
            if (-1 == fd)
                {
                    perror("Can't Open Serial Port");
                    return(-1);
                }
            else
                printf("open tty2 .....\n");
        }
    if(fcntl(fd, F_SETFL, 0)<0) //正确的 返回值是0
        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;
}

int main(void)
{
    int fd;
    int nread,i;
    char buff[]="Hello\n";

    if((fd=open_port(fd,3))<0) //代表打开的设?福?晒Γ?祷豧d
        {
            perror("open_port error");
            return;
        }
    if((i=set_opt(fd,9600,8,'N',1))<0)
        {
            perror("set_opt error");
            return;
        }
    printf("fd=%d\n",fd);
    
    nread=read(fd,buff,8);
    printf("nread=%d,%s\n",nread,buff);
    close(fd);
    return;
}
好好赚钱,保护媳妇。。。
级别: 新手上路
UID: 49714
精华: 0
发帖: 43
金钱: 255 两
威望: 51 点
综合积分: 86 分
注册时间: 2011-06-14
最后登录: 2012-06-25
1楼  发表于: 2011-09-23 19:29
跟网上搜到的代码一样?   我最近也在搞串口   并且很巧我用的也是这两个函数   是可以在开发板上使用的

哥们:我首先做了一个波特率的显示  每次开机首先显示的总是 0    总不至于开发板默认值为 0  吧 !

我使用这个函数是可以成功更改的   比如波特率   更改之后我的显示程序(cfsetispeed())就可以显示更改后的数据了      

但是我实在不知道为什么每次开机波特率都是显示为  0    ???
嘿嘿。。
我把grub.conf文件中原来的路径修改啦,现在启动不来机器啦,停留在启动画面中(黑屏有字符,估 ..
级别: 新手上路
UID: 55202
精华: 0
发帖: 9
金钱: 45 两
威望: 9 点
综合积分: 18 分
注册时间: 2011-09-14
最后登录: 2012-05-24
2楼  发表于: 2012-05-16 21:40
朋友你好:        我是一名大四的学生,现在做毕业设计,我的 mini2440开发板在调试串口(uart1),每次总是在接收 { 使用函数:write(fd,buff,512) ;} 数据后又发送所接收到的数据,而且还在前后都加上了\r\n.
        例如:接收数据:\r\dOK\r\d。接着就发送数据:\r\d\r\dOK\r\d\r\d。
        读取数据时{使用函数:read(fd,buff,512);}接着使用printf(“%s”,buff,)打印,如果没有收到数据,打印函数不执行。如果给串口发送一个带回车换行的数据,就能显示,并且ARM回向串口发送数据就是上面提到的情况。
        我认为是缓存没有清空,但是在应用程序中我又不知道怎么去清除。希望大家能帮忙看看怎么设置,谢谢啦,我QQ:402828584
        我的应用函数如下:
#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>      /*错误号定义*/
#include     <string.h>
#define FALSE  -1#define TRUE    0/*#define UTRSTAT1  0x50004010#define UERSTAT1  0x50004014
#define TXD0READY  (1<<2)#define RXD0READY  (1)*///**全局变量出初始化**//char buff[512];char storbuff[512];
**************//////////////
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 < 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);   }}
           设置串口数据位,停止位和效验位  fd       类型  int  打开的串口文件句柄*  databits 类型  int 数据位   取值 为 7 或者8*  stopbits 类型  int 停止位   取值为 1 或者2*  parity   类型  int  效验类型 取值为N,E,O,,S
int 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,"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); }  return (TRUE); }

****打开串**********//////////////

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

//******函数*******////**调用函数声名//int JUDGE_OK(char date[]);int TXDATE_TO_BUFF(char date[]);int TBUFF_TO_STORBUFF(char date[]);
////**应用程序主函数实现功能******////////**应用程序主函数实现功能******////int main(int argc, char **argv){ int fd; int nread; char *dev ="/dev/s3c2410_serial1"; fd = OpenDev(dev); if (fd>0) set_speed(fd,19200); 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);           }
//**使用-标志位-初始化**//     int read_flag=0;//   char stor_buff[512];//**使用-发送数组-初始化//**   char AT[]="AT\n";   char *ATD="ATD15958492073;\n";   char ATE0[]="ATE0\n";
memset(buff,0,sizeof(buff)); write(fd,"AT\r\n",4); //write(fd,buff,(TXDATE_TO_BUFF(ATD))); memset(buff,0,sizeof(buff)); while(1)   {     if((nread = read(fd,buff,512))>0)          {          buff[nread+1]='\0';                                  printf("Get date is :%s",buff);          if(TBUFF_TO_STORBUFF(buff)==1)                                  {              memset(buff,0,sizeof(buff));              read_flag=1;                                    }                      }      if(read_flag==1)                     {           if(1==JUDGE_OK(storbuff)) printf("This is OK\n");           memset(buff,0,sizeof(storbuff));           printf("claean storbuff ok !\n");           read_flag=0;                     }              }                                  close(fd);  exit(0);}
////****收到数据判断函数定义******/////int JUDGE_OK(char date[])      {    int i,flag=0;    if((strlen(date))<5)                  {        for(i=0;i<2;)          switch(date[i++])                              {              case 'O' :flag=1; break;              case 'K' :if(flag==1)return 1;else {printf("judge ok is erro\n");return 0;}                              }                 }       }///****发送组合数组********///int TXDATE_TO_BUFF(char date[])      {     int datelen=0;     int count=0;     datelen=strlen(date);     for(count=0;count<datelen;)                     {          buff[count]=date[count];          count++;                      }     return datelen;          }///****接受到数组保留********///int TBUFF_TO_STORBUFF(char date[])      {     int datelen=0;     int count=0;     datelen=strlen(date);     for(count=0;count<datelen;)                     {          storbuff[count]=date[count];          count++;                      }     return datelen;       }
助人为乐~!相互学习~!
我最虚心
级别: 新手上路
UID: 44872
精华: 0
发帖: 20
金钱: 100 两
威望: 20 点
综合积分: 40 分
注册时间: 2011-04-29
最后登录: 2014-03-08
3楼  发表于: 2012-05-18 14:48
帮顶阿,顺便问一下LZ以及LS诸位,你们的串口程序在开发板上可以接受hex类型的数据吗