例程有兩種基本用法
一、短接tx rx,自發自收
短接開發闆待測序列槽的tx和rx,運作如下例程,
二、用電腦的序列槽助手進行收發測試
1、将開發闆待測序列槽和電腦連接配接起來(用USB轉序列槽連接配接闆)
2、開發闆運作例程(循環讀取序列槽内容并回傳)
$ ./uart_test /dev/ttyS1
3、電腦序列槽助手打開對應的序列槽,發送任意資料,檢視傳回結果。
使用全志的A64開發闆實測,write發送位元組個數幾乎沒有限制,一次就完成。read一次最多讀32個位元組。
例程源碼如下
/*
* 序列槽測試例程
* 需要傳參序列槽的裝置檔案,如/dev/ttyS2
* 若打開序列槽成功,會循環讀取序列槽讀到的内容,然後回傳
*/
#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 fd;
int ret = -1;
const char *dev = NULL;
const char *test_string = NULL;
char *p_buffer = NULL;
int nread = 0;
int nwrite = 0;
/* 1、檢測傳參 */
if (argc < 2 || argc > 3 ) {
printf("Usage:%s dev_name [self_loop_test_string]\n", argv[0]);
exit(1);
}
dev = argv[1];
if (NULL != argv[2]) {
if (strlen(argv[2]) <= BUF_SIZE) {
test_string = argv[2];
} else {
printf("self_loop_test_string must be smaller than %d.\n", BUF_SIZE);
return 0;
}
}
/* 2、打開序列槽 */
fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (-1 == fd) {
printf("Cannot open %s:%s\n", dev, strerror(errno));
exit(1);
}
printf("==== open %s success ====\n", dev);
#if 1
/* 3、初始化裝置 */
if (-1 == set_speed(fd, DEF_BAUD)) {
printf("Cannot set baudrate to 115200\n");
close(fd);
exit(1);
}
if (-1 == set_parity(fd, 8, 1, 'N')) {
printf("Set Parity Error\n");
close(fd);
exit(1);
}
#endif
if (NULL != test_string) {
/*開始自發自收測試*/
/* 寫序列槽 */
do {
nwrite = write(fd, 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(fd, p_buffer, 64);
if (ret > 0) {
printf("read %d bytes data:%s\n", ret, p_buffer);
p_buffer += ret;
nread += ret;
}
} while(nread < nwrite);
printf("all read %d bytes data:%s\n", nread, buffer);
printf("==== test %s ====\n", (0 == strcmp(buffer, test_string)) ? "success." : "error!!!");
close(fd);
return 0;
}
/*開始測試*/
/*循環讀取并回寫序列槽内容*/
printf("start read and pass back\n");
while(1) {
/* 清空buffer */
memset(buffer, 0, BUF_SIZE);
/* 讀序列槽 */
nread = read(fd, buffer, 64);
if(nread > 0) {
printf("read %d bytes.\n", nread);
do {
ret = write(fd, buffer, nread);
} while(ret <= 0);
printf("write %d bytes.\n", ret);
}
//printf("block test.\n");
}
close(fd);
return 0;
}