C - open (& RS232開發)



開啟方式


int open(const char *pathname, int flags);

pathname:開啟路徑
flags:開啟方式
    O_RDWR:可讀可寫
    O_APPEND:以附加方式開啟
    O_CREAT:不存在就建立
    O_NDELAY:非阻塞式,讀不到值回傳0,就算讀完了也回傳0
    O_NONBLOCK:和 O_NDELAY 一樣,差在讀完了會回傳-1,並設置 errno 為 EAGAIN
    O_SYNC:以同步IO方式打開文件
    O_NOCTTY:這個程式不控制TTY介面。
        如果不設定這個旗標,有些輸入(例如鍵盤的abort)信號可能影響程式
回傳:檔案代號 (-1: 讀取失敗)

開啟後也可再次設定 flags

int flag = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, (flag | O_NONBLOCK | O_SYNC));



讀取


ssize_t read(int fd, void *buf, size_t count);

fd:用 open 得到的值
buf:讀取後要存放的位置
count:讀取長度
回傳:讀取長度 (-1: 讀取失敗)


寫入


ssize_t write(int fd, const void *buf, size_t count);

fd:用 open 得到的值
buf:要寫入的資料
count:寫入長度
回傳:寫入長度 (-1: 寫入失敗)


關閉


int close(int fd);

fd:用 open 得到的值
回傳:0:成功, -1:失敗



使用 select


int select(int fd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);


用法範例

struct timeval tv;
fd_set readfds;

FD_ZERO(&readfds);
FD_SET(fd, &readfds);
tv.tv_sec = 30;
tv.tv_usec = 0;
if (select(fd + 1, &readfds, NULL, NULL, &tv) > 0) {
len = read(fd, buf, sizeof(buf));
}

等待到fd有資料可讀時再讀取,  最長等30秒


pipe 取得標準輸出入


int fds[2];
pipe(fds);
fds[0] // 取得標準輸入() fd
fds[1] // 取得標準輸出() fd





Device open 範例


#define FALSE -1
#define TRUE 1

int speed_arr[] = {
B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300,
};
int name_arr[] = {
115200, 38400, 19200, 9600, 4800, 2400, 1200, 300,
};

int openDev(char *dev) {
int fd = open(dev, O_RDWR | O_NOCTTY);
if (fd < 0) {
perror("open dev failed !!");
return (FALSE);
}
return fd;
}

/**
*@brief 設置串口資料位元,停止位元和效驗位
*@param fd 類型 int 打開的串口文件控制碼*
*@param databits 類型 int 資料位元 取值 為 7 或者8*
*@param stopbits 類型 int 停止位 取值為 1 或者2*
*@param parity 類型 int 效驗類型 取值為N,E,O,S
*/
int setParity(int fd, int databits, int stopbits, int parity) {
struct termios options;
if (tcgetattr(fd, &options) != 0) {
perror("SetupSerial 1");
return (FALSE);
}

options.c_cflag = 0;
options.c_iflag = 0;
options.c_oflag = 0;
options.c_lflag = 0;

options.c_cflag = CREAD | CLOCAL; // +++++
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] = 0; // 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);
}

void setSpeed(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[i]) {
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
}
tcflush(fd, TCIOFLUSH);
}
}


使用方式

#define BAUDRATE 9600
#define DATABITS 8
#define STOPBITS 1
#define PARITY 0x4E // 'N'
static char sendBuf_Cmd[] = { 0x02, 0x30, 0x03 };
char buf[32];
int buf_size = sizeof(buf);
int fd, len = 0, ret_len = 0, n, data_len = 0;
memset(buf, '\0', sizeof(buf));

if((fd = openDev(dev)) > 0) {
setSpeed(fd, BAUDRATE);
if (setParity(fd, DATABITS, STOPBITS, PARITY) == FALSE) {
printf("Set Parity Error\n");
exit(1);
}

while(1) {
ret_len = read(fd, &buf[len], buf_size - len);
if(ret_len < 0) {
usleep(100000);
continue;
}
len += ret_len;

if(len > 0) {
while(len > 0) {
if(buf[0] == 0x6) { // ACK
write(fd, sendBuf_Cmd, sizeof(sendBuf_Cmd)); // 送命令
data_len = 1;
} else if(buf[0] == 0xXX) { // ...
// ...
data_len = xx;
} else // unknown
data_len = len;
len -= data_len;
if(len > 0)
memcpy(buf, &buf[data_len], len);
}
}
}

close(fd);
}

也可讀寫改用 pthread 的方式




沒有留言:

張貼留言