linux串口通信 读取信息

这两天需要做一个串口通信,用于接受外设传输来的信息,网上的好多程序较为复杂,写了一个简单易点的程序,主要流程:打开串口->初始化->循环读取。
代码如下:

#include <iostream>   
/*串口相关的头文件*/
#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 DEV_NAME  "/dev/ttyUSB0"
#define FALSE  -1
#define TRUE   0

     
int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)    
{    
       
    int   i;    
    int   status;    
    int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};    
    int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};    
             
    struct termios options;    
       
    /*  tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数还可以测试配置是否正确,
        该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.  */    
    if( tcgetattr( fd,&options)  !=  0)    
    {    
        perror("SetupSerial 1");        
        return(FALSE);     
    }    
      
    //设置串口输入波特率和输出波特率    
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)    
    {    
        if  (speed == name_arr[i])    
        {                 
            cfsetispeed(&options, speed_arr[i]);     
            cfsetospeed(&options, speed_arr[i]);      
        }    
    }         
       
    //修改控制模式,保证程序不会占用串口    
    options.c_cflag |= CLOCAL;    
    //修改控制模式,使得能够从串口中读取输入数据    
    options.c_cflag |= CREAD;    
      
    //设置数据流控制    
    switch(flow_ctrl)    
    {    
          
        case 0 ://不使用流控制    
              options.c_cflag &= ~CRTSCTS;    
              break;       
          
        case 1 ://使用硬件流控制    
              options.c_cflag |= CRTSCTS;    
              break;    
        case 2 ://使用软件流控制    
              options.c_cflag |= IXON | IXOFF | IXANY;    
              break;    
    }    
    //设置数据位    
    //屏蔽其他标志位    
    options.c_cflag &= ~CSIZE;    
    switch (databits)    
    {      
        case 5    :    
                     options.c_cflag |= CS5;    
                     break;    
        case 6    :    
                     options.c_cflag |= CS6;    
                     break;    
        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;     
                 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);    
    }    
       
    //修改输出模式,原始数据输出    
    options.c_oflag &= ~OPOST;    
      
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);    
    //options.c_lflag &= ~(ISIG | ICANON);    
       
    //设置等待时间和最小接收字符    
    options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */      
    options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */    
       
    //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读    
    tcflush(fd,TCIFLUSH);    
       
    //激活配置 (将修改后的termios数据设置到串口中)    
    if (tcsetattr(fd,TCSANOW,&options) != 0)      
    {    
        perror("com set error!\n");      
        return (FALSE);     
    }    
    return (TRUE);     
}    
/*******************************************************************  
*名称:                UART0_Init()  
*功能:                串口初始化  
*入口参数:            fd         文件描述符    
*                      speed      串口速度  
*                      flow_ctrl  数据流控制  
*                      databits   数据位   取值为 7 或者8  
*                      stopbits   停止位   取值为 1 或者2  
*                      parity     效验类型 取值为N,E,O,,S  
*                        
*出口参数:正确返回为1,错误返回为0  
*******************************************************************/    
  
int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity)    
{    
    int err;    
    //设置串口数据帧格式    
    if (UART0_Set(fd,115200,0,8,1,'N') == FALSE)    
    {                                                             
        return FALSE;    
    }    
    else    
    {    
        return  TRUE;    
    }    
}    

int decode_distance(unsigned char *rcv_buf){
  int distance;
  distance = (int) rcv_buf[2] + (int) rcv_buf[3]*256;
  return distance;
}

int decode_strength(unsigned char rcv_buf[8]){
  int strength;
  strength = (int) rcv_buf[4] + (int) rcv_buf[5]*256;
  return strength;
}

int decode_sigment(unsigned char rcv_buf[8]){
  int sigment;
  sigment = (int) rcv_buf[6];
  if(sigment == 7||sigment == 8)
  {
    return 1;
  }else{
    return 0;
  }
}

using namespace std;
     
int main(int argc, char **argv)
{
    int fd;                            //文件描述符
    int len;                        
    int i;
    int err;                           //返回调用函数的状态
    int distance;
    int strength;
    int sigment;
    unsigned char rcv_buf[1024];       
	
    fd = open( DEV_NAME, O_RDWR|O_NOCTTY|O_NDELAY);
    //O_RDONLY 只读打开。 O_WRONLY 只写打开。 O_RDWR 读、写打开。 O_APPEND 每次写时都加到文件的尾端。 O_CREAT 若此文件不存在则创建它。
    //std::cout<<fd<<std::endl;
	
    if(fd < 0) {
      std::cout<<"打开错误"<<std::endl;
      return -1;
    }

    do  
    {    
      err = UART0_Init(fd,115200,0,8,1,'N');    
      printf("Set Port Exactly!\n"); 
      sleep(1);   
    }while(FALSE == err || FALSE == fd);

    while (1) //循环读取数据
    {
      len = read(fd, rcv_buf , 9);
      cout << len << endl;
      sleep(2);
      if (len < 0) 
      {
        std::cout<<"读错误 "<<std::endl;
        return -1;
      }
      
      distance = decode_distance(rcv_buf);
      cout<<"distance: "<<distance<<endl;
      strength = decode_strength(rcv_buf);
      sigment = decode_sigment(rcv_buf);
      
      cout<<"信号强度为:"<< strength << endl;
      
      if(sigment==1){
	cout<<"数据可信"<< endl;
      }else{
	cout<<"数据不可信"<< endl;
      }
      
//       cout<<rcv_buf<<endl;
//       int a =(int)rcv_buf[0];
//       cout<<a<<endl;
//       int b = (int)rcv_buf[1];
//       cout<<b<<endl;
//       for(int i =0;i < 9; i++)
//       {
// 	rcv_buf[i] = 0;
//       }
//       
// 
//       a =(int)rcv_buf[2];
//       cout<<a<<endl;
//       b = (int)rcv_buf[3];
//       cout<<b<<endl;
    }
    
    return 0;
}

注意:
1.在打开串口时,需要使用超级权限才能实现,所以可以

sudo kdevelop

进入编译器进行操作或直接cmake、make后

chmod 777 ./new_port
sudo ./new_port

2.在使用过程中,当我的缓冲数组rcv_buf较小时实现的结果没有更新,出现了故障,所以建议一般rcv_buf取大一点的值。

3.对于数据解码,我是根据我所使用的外设的具体情况进行解码,大家也具体情况具体分析吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值