com串口通信测试代码

简介: com串口通信测试代码

串口助手可以从这里下载:https://docs.ai-thinker.com/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B72

内容摘自网络:

要实现AT指令的发送与接收,第一步先实现相关的串口通信接口:

/******************************
实现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>      /*错误号定义*/    
#include<string.h>    
#include "linux_interface.h"
int serial_port_open(char *dev)
{
  //const char * dev = "/dev/ttyUSB1";
  int fd;
  //O_RDWR读写模式
  //O_NOCTTY如果路径名指向终端设备,不要把这个设备用作控制终端。
  //O_NONBLOCK如果路径名指向FIFO/块文件/字符文件,则把文件的打开和后继I/O
  fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
  if(fd == -1)
  {
    printf("open AT com error. \n");
    return -1;
  }
  //如果非阻塞,如果文件为空,不会阻塞,直接返回结果,非阻塞针对设备,网络文件
  //设置fd为阻塞状态,设备文件,网络文件时用
  if(fcntl(fd, F_SETFL, 0) < 0)
  {
    printf("fcntl error. \n");
  }else
  {
    printf("fcntl=%d\n",fcntl(fd, F_SETFL, 0));
  }
  //STDIN_FILENO 标准输入
  if(isatty(STDIN_FILENO)==0) 
    printf("standard input is not a terminal device\n");
  else 
    printf("isatty success!\n"); 
  return fd;
}
void serial_port_close(int fd)
{
  close(fd);
}
/*****************************************************
入口参数:
  fd      打开设备的fd
  speed     串口速率
  flow_ctrl 数据流控制,一般不控制 0
  databits    数据位,取值7或者8
  stopbits    停止位   取值为 1 或者2  
  parity      效验类型 取值为N,E,O,,S  
*****************************************************/
int serial_port_config(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
  int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};    
    int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};    
    struct termios options; //获取到fd中对应的参数
    bzero( &options, sizeof(options)); 
    if(tcgetattr(fd, &options) != 0)
    {
      printf("get serial port config error.\n");
      return -1;
    }
    //根据speed 设置输入波特率和输出波特率
    for(int i=0; i<sizeof(speed_arr)/sizeof(int); i++)
    {
      if(name_arr[i] == speed)
      {
        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;
    }
    //设置字符长度掩码,取值为 CS5, CS6, CS7, 或 CS8。
    //屏蔽其他标志位    
    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:
        printf("unsupported data size \n");
        return -1;
    }
    //设置停止位
    switch(stopbits)
    {
      case 1: options.c_cflag &= ~CSTOPB; break;
      case 2: options.c_cflag |= CSTOPB; break;
      default:
        printf("unsupported stop bit. \n");
        return -1;
    }
    //设置校验位 
    switch(parity) //int类型和char类型的默认互转
    {
      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:
        printf("unsupported parity.\n");
        return -1;
    }
    //设置输出模式 原始数据输出
    options.c_oflag &= ~OPOST;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    //设置等待时间和最小接收字符 ==》这里应该为0吧
    options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */
    options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */
    //如果发生数据溢出,接收数据,且不再读取 刷新收到的数据但是不读
    //清空终端未完成的输入/输出请求及数据
    tcflush(fd,TCIFLUSH);
    if (tcsetattr(fd,TCSANOW,&options) != 0)
    {    
        printf("com set error!\n");
        return -1;
    }
    return 0;
}
//发送的接口 调用write接口
int linux_serial_port_send(int fd, char* send_buf, int data_len)
{
  int len = 0; 
  data_len = (strlen(send_buf) > data_len)? data_len:strlen(send_buf);
  len = write(fd, send_buf, data_len);
  if(len == data_len)
  {
    printf("send buff [%s] success. \n", send_buf);
    return len;
  }else
  {
    tcflush(fd,TCOFLUSH);
        return -1;
  }
}
int linux_serial_port_read(int fd, char* recv_buf, int data_len)
{
  return read(fd, recv_buf, data_len);
}
//接收的接口
int linux_serial_port_recv(int fd, char* recv_buf, int data_len)
{
  //把fd添加到select的集合中
  fd_set fs_read,fd_temp;
  FD_ZERO(&fs_read);
  FD_SET(fd, &fs_read);
  //设置fd,然后设置select参数
  struct timeval time;
  time.tv_sec = 10;
  time.tv_usec = 0;
  //使用select实现多路复用
  int result;
  while(1)
  {
    fd_temp = fs_read;
    result = select(fd +1, &fd_temp, (fd_set *)0, (fd_set *)0, &time);/*(struct timeval *) 0);*/
    int len;
    for(int i=0; i<fd+1; i++)
    {
      if(FD_ISSET(i, &fd_temp))
      {
        //开始接收数据并进行打印
        len = read(fd, recv_buf, data_len);
        if(len > 0)
        {
          recv_buf[len] = '\0';
          printf("recv buff: %s \n", recv_buf);
        }else
        {
          printf("not recv some buff, wait... \n");
        }
      }
    }
    sleep(1);
  }
  return 0;
}
//按照一定的设置打开 COM口,这里的com口请传参传入,传入是发送还是接收的标志
int linux_serial_port_init(char * dev_port, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
  //打开端口
  int fd;
  if((fd = serial_port_open(dev_port)) == -1)
  {
    return -1;
  }
  //设置端口
  int err;
  do{
    // err = serial_port_config(fd, 115200, 0, 8, 1, 'N');
    err = serial_port_config(fd, speed, flow_ctrl, databits, stopbits, parity);
    // printf("set Port Exactly! \n");
    if(err != 0)
    {
      printf(" set Port config error. \n");
    }else
    {
      printf(" set Port config success. \n");
      break;
    }
    sleep(1);
  }while(err == -1);
  if(err == -1)
  {
    close(fd);
  }
  return fd;
  //关闭端口
}
//根据入参,实现发送和接收不同逻辑的处理
int linux_serial_execute_send_or_recv(char * dev_port, int flag)
{
  int fd;
  fd = linux_serial_port_init(dev_port, 115200, 0, 8, 1, 'N');
  if(fd == -1)
  {
    printf("open serial port error. \n");
    return -1;
  }
  int len;
  char send_buf[256];
  char recv_buf[256];
  //flag 为0,则发送, 为1,则接收
  if(flag == 0)
  {
    //输入内容,最大不超过160字节,fgets能吸收回车符,这样pc收到的数据就能自动换行
    fgets(send_buf,256,stdin);
    for(int i=0; i<3; i++)
    {
      //从send_buf中发送
      len = linux_serial_port_send(fd, send_buf, 160);
      if(len > 0)
      {
        printf(" %d time send %d data successful\n",i,len); 
      }else
      {
        printf("send data error!\n"); 
      }
      sleep(1);
    }
    serial_port_close(fd);
    return 0;
  }
  //循环一直从串口中读数据
  if(flag == 1)
  {
    //接收放在接口里  这里后两个参数不用了
    linux_serial_port_recv(fd, recv_buf, sizeof(recv_buf));
    serial_port_close(fd);
    return 0;
  }
}
// int main(int argc, char *argv[])
// {
//  if(argc != 3)
//  {
//    printf("Usage: %s /dev/ttySn 0      #(send data)\n",argv[0]);
//         printf("Usage: %s /dev/ttySn 1      #1(receive data)\n",argv[0]);
//         printf("open failure : %s\n", strerror(errno));
//         return -1; 
//  }
//  if(0 == strcmp(argv[2],"0"))
//  {
//    linux_serial_execute_send_or_recv(argv[1], 0);
//  }
//  if(1 == strcmp(argv[2],"1"))
//  {
//    linux_serial_execute_send_or_recv(argv[1], 1);
//  }
//  printf("Usage: %s /dev/ttySn 0/1      #1(receive data)\n",argv[0]);
//  return 0;
// }
目录
相关文章
|
3月前
|
数据采集 机器学习/深度学习 大数据
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
这篇文章详细介绍了C3D架构在行为检测领域的应用,包括训练和测试步骤,使用UCF101数据集进行演示。
88 1
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
|
3月前
|
机器学习/深度学习 人工智能 监控
提升软件质量的关键路径:高效测试策略与实践在软件开发的宇宙中,每一行代码都如同星辰般璀璨,而将这些星辰编织成星系的过程,则依赖于严谨而高效的测试策略。本文将引领读者探索软件测试的奥秘,揭示如何通过精心设计的测试方案,不仅提升软件的性能与稳定性,还能加速产品上市的步伐,最终实现质量与效率的双重飞跃。
在软件工程的浩瀚星海中,测试不仅是发现缺陷的放大镜,更是保障软件质量的坚固防线。本文旨在探讨一种高效且创新的软件测试策略框架,它融合了传统方法的精髓与现代技术的突破,旨在为软件开发团队提供一套系统化、可执行性强的测试指引。我们将从测试规划的起点出发,沿着测试设计、执行、反馈再到持续优化的轨迹,逐步展开论述。每一步都强调实用性与前瞻性相结合,确保测试活动能够紧跟软件开发的步伐,及时适应变化,有效应对各种挑战。
|
9天前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
40 13
|
4月前
|
Web App开发 JavaScript 前端开发
添加浮动按钮点击滚动到网页底部的纯JavaScript演示代码 IE9、11,Maxthon 1.6.7,Firefox30、31,360极速浏览器7.5.3.308下测试正常
添加浮动按钮点击滚动到网页底部的纯JavaScript演示代码 IE9、11,Maxthon 1.6.7,Firefox30、31,360极速浏览器7.5.3.308下测试正常
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
65 1
|
4月前
|
SQL JavaScript 前端开发
基于Python访问Hive的pytest测试代码实现
根据《用Java、Python来开发Hive应用》一文,建立了使用Python、来开发Hive应用的方法,产生的代码如下
85 6
基于Python访问Hive的pytest测试代码实现
|
4月前
|
Java C++
代码文件间重复性测试
本文介绍了如何使用代码相似性检测工具simian来找出代码文件中的重复行,并通过示例指令展示了如何将检测结果输出到指定的文本文件中。
|
4月前
|
测试技术 UED
软件测试的艺术:从代码到品质的探索之旅
在数字时代的浪潮中,软件已成为我们生活和工作不可或缺的一部分。然而,高质量的软件背后隐藏着一门鲜为人知的艺术——软件测试。本文将带你走进这门艺术的世界,从基础理论到实践应用,一起探索如何通过软件测试保障产品质量,提升用户体验,并最终实现从代码到品质的华丽转变。
|
4月前
|
敏捷开发 安全 测试技术
软件测试的艺术:从代码到用户体验的全方位解析
本文将深入探讨软件测试的重要性和实施策略,通过分析不同类型的测试方法和工具,展示如何有效地提升软件质量和用户满意度。我们将从单元测试、集成测试到性能测试等多个角度出发,详细解释每种测试方法的实施步骤和最佳实践。此外,文章还将讨论如何通过持续集成和自动化测试来优化测试流程,以及如何建立有效的测试团队来应对快速变化的市场需求。通过实际案例的分析,本文旨在为读者提供一套系统而实用的软件测试策略,帮助读者在软件开发过程中做出更明智的决策。
|
4月前
|
SQL JavaScript 前端开发
基于Java访问Hive的JUnit5测试代码实现
根据《用Java、Python来开发Hive应用》一文,建立了使用Java、来开发Hive应用的方法,产生的代码如下
83 6