嵌入式爱好者

嵌入式爱好者 门户 知识库 查看内容

485测试应用

2023-8-31 22:36| 发布者: Espoir| 查看: 159| 评论: 0

类目:  >  知识库     文档编号: 1119

485测试应用

1. 背景

  • 485是差分信号,需要两串口对测;

  • 教育市场板子需要测试,且板子上正好有两个485;

  • 我们现有的应用不适合用于自动测试,自动测试需要能够给出测试结果;

2. 应用层调用串口的流程

1. 打开设备节点

对于linux来说,操作串口就是操作/dev下的tty节点,应用层需要调用open/close函数来得到该节点的设备描述符,之后使用write/read函数进行读写。

2. 初始化串口

设置串口波特率、数据位、停止位等参数。

3. 读写串口

调用write/read函数进行读写。

4. 关闭设备节点

调用close函数关闭设备节点。

3. 应用常用的几种处理

1. 传参校验

使用argc和argv进行传参校验,如果传入的参数数量不对,则打印Usage提示输入正确的参数。

int main(int argc, char **argv)
{
  if (argc != 4 ) {
printf("Usage:%s dev1_name dev2_name [self_loop_test_string]\n", argv[0]);
exit(1);
}
}

2. open/close函数

对于linux来说,操作串口就是操作/dev下的tty节点,应用层需要调用open/close函数来得到该节点的设备描述符,之后使用write/read函数进行读写。

一般情况下,操作正常执行会返回0或者正数,当返回负数表示函数没有正常执行,所以一般会调用open/close等函数时,会通过判断该函数的返回值,确定函数是否正常执行。例如:

dev1 = argv[1];
fd1 = open(dev1, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == fd1) {
printf("Cannot open %s:%s\n", dev1, strerror(errno));
exit(1);
}

4. 串口对测的处理方法

两串口测试时,需要一个发,一个收,然后通过对比发出去的内容和收到的内容,来确定串口通信是否正常。

流程如下:

写串口1 >> 清理缓存区 >> 将串口2的数据读入缓存区 >> 对比判断 >> 输出结果

源码如下:

/* 写串口 */
do {
nwrite = write(fd1, test_string, strlen(test_string));
} while(nwrite <= 0);
printf("send %d bytes data.\n", nwrite);

/* 清空buffer */
memset(buffer, 0, BUF_SIZE);
p_buffer = buffer;
nread = 0;

/* 读串口 */
do {
ret = read(fd2, p_buffer, 64);
if (ret > 0) {
printf("read %d bytes data:%s\n", ret, p_buffer);
p_buffer += ret;
nread += ret;
}
} while(nread < nwrite && i--);

printf("all read %d bytes data:%s\n", nread, buffer);
printf("------%s >> %s test %s------\n", dev1, dev2, (0 == strcmp(buffer, test_string)) ? "ok!" : "failed!");

5. 源码

源码如下:

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

/*
* % 0x25
* ; 0x3B
* + 0x2B
* ? 0x3F
*/

#define DEF_BAUD 115200
#define SPEED_CNT 5
#define BUF_SIZE 100

/*用来接收轨道数据*/
char buffer[BUF_SIZE];

int speed_arr[SPEED_CNT] = {
B9600, B19200, B38400,
B57600, B115200
};

int name_arr[SPEED_CNT] = {
9600, 19200, 38400,
57600, 115200
};

/**
*@brief 设置串口通信速率
*@param fd     类型 int 打开串口的文件句柄
*@param speed 类型 int 串口速度
*@return 0 success or -1 err
*/
int set_speed(int fd, int speed)
{
int i;
int status;
struct termios opt;

tcgetattr(fd, &opt);

for (i= 0; i<SPEED_CNT; 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 set_speed");
return -1;
}

return 0;
    }
/*清空所有正在发生的IO数据*/
tcflush(fd, TCIOFLUSH);
  }
 
printf("Cannot find suitable speed\n");
return -1;
}

/**
*@brief   设置串口数据位,停止位和效验位
*@param fd     类型 int 打开的串口文件句柄*
*@param databits 类型 int 数据位   取值 为 7 或者8*
*@param stopbits 类型 int 停止位   取值为 1 或者2*
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*@return 0 success or -1 err
*/
int set_parity(int fd, int databits, int stopbits, int parity)
{

struct termios options;
if (tcgetattr(fd, &options) != 0)
{
perror("tcgetattr");
return -1;
}

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 -1;
}

switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB;   /* Clear parity enable */
options.c_iflag &= ~INPCK;     /* Enable parity checking */
options.c_iflag &= ~(ICRNL|IGNCR);
options.c_lflag &= ~(ICANON );
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 -1;
}

/* 设置停止位*/  
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return -1;
}

/* Set input parity option */
if ((parity != 'n') || (parity != 'N'))
options.c_iflag |= INPCK;

/* 若以O_NONBLOCK 方式open,这两个设置没有作用,等同于都为0 */
/* 若非O_NONBLOCK 方式open,具体作用可参考其他博客,关键词linux VTIME */
  options.c_cc[VTIME] = 10; // 1s
  options.c_cc[VMIN] = 0;

/* 清空正读的数据,且不会读出 */
tcflush(fd,TCIFLUSH);

/*采用原始模式通讯*/
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;

/*解决发送0x0A的问题*/
// options.c_iflag &= ~(INLCR | ICRNL | IGNCR);
// options.c_oflag &= ~(ONLCR | OCRNL | ONOCR | ONLRET);

/* Update the options and do it NOW */
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
perror("SetupSerial 3");
return -1;
}

return 0;
}

/**

*@breif main()

*/
int main(int argc, char **argv)
{
int fd1, fd2;
int ret = -1;
const char *dev1 = NULL;
const char *dev2 = NULL;
const char *test_string = NULL;
char *p_buffer = NULL;
int nread = 0;
int nwrite = 0;

/* 1、检测传参 */
if (argc != 4 ) {
printf("Usage:%s dev1_name dev2_name [self_loop_test_string]\n", argv[0]);
exit(1);
}
dev1 = argv[1];
dev2 = argv[2];
if (NULL != argv[3]) {
if (strlen(argv[3]) <= BUF_SIZE) {
test_string = argv[3];
} else {
printf("self_loop_test_string must be smaller than %d.\n", BUF_SIZE);
return 0;
}
}
else{
printf("please input a string!\n");
return 0;
}

/* 2、打开串口 */
fd1 = open(dev1, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == fd1) {
printf("Cannot open %s:%s\n", dev1, strerror(errno));
exit(1);
}
printf("------open %s success------\n", dev1);

fd2 = open(dev2, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == fd2) {
printf("Cannot open %s:%s\n", dev2, strerror(errno));
exit(1);
}
printf("------open %s success------\n", dev2);

#if 1
/* 3、初始化设备 */
if (-1 == set_speed(fd1, DEF_BAUD)) {
printf("Cannot set baudrate to 115200\n");
close(fd1);
exit(1);
}

if (-1 == set_speed(fd2, DEF_BAUD)) {
printf("Cannot set baudrate to 115200\n");
close(fd2);
exit(1);
}

if (-1 == set_parity(fd1, 8, 1, 'N')) {
  printf("Set Parity Error\n");
close(fd1);
  exit(1);
}
if (-1 == set_parity(fd2, 8, 1, 'N')) {
  printf("Set Parity Error\n");
close(fd2);
  exit(1);
}
#endif
int i = 30000;

if (NULL != test_string) {
/*开始自发自收测试*/
/* 写串口 */
do {
nwrite = write(fd1, test_string, strlen(test_string));
} while(nwrite <= 0);
printf("send %d bytes data.\n", nwrite);

/* 清空buffer */
memset(buffer, 0, BUF_SIZE);
p_buffer = buffer;
nread = 0;

/* 读串口 */
do {
ret = read(fd2, p_buffer, 64);
if (ret > 0) {
printf("read %d bytes data:%s\n", ret, p_buffer);
p_buffer += ret;
nread += ret;
}
} while(nread < nwrite && i--);
printf("all read %d bytes data:%s\n", nread, buffer);
printf("------%s >> %s test %s------\n", dev1, dev2, (0 == strcmp(buffer, test_string)) ? "ok!" : "failed!");

close(fd1);
close(fd2);
return 0;
}
}


已解决

未解决

只是看看

最新评论

QQ|小黑屋| 飞凌嵌入式 ( 冀ICP备12004394号-1 )

GMT+8, 2025-3-26 09:20

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

返回顶部