📄 c_serial.c
字号:
/* ******************************************************************** */
/* UNIX串行口操作接口 */
/* ******************************************************************** */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifndef M_UNIX
#include <sys/time.h>
#endif
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/select.h>
static int s2comid; /* 串行口设备句柄 */
static int s2istty; /* 是否由应用程序打开了设备 */
static struct termios s2orgtm; /* 原始的属性,关闭时恢复 */
#ifdef DEBUG_S
/*
* 16进制显示一个字符串
*/
void DebugStr(char *buf, int len, char chFlag)
{
while (len-- > 0) {
fprintf(stderr, "%c%02X ", chFlag, (u_char)*buf++);
}
}
#endif
/*
* 由应用程序打开了设备, 因此, OpenDevice就不必打开了
*/
void com_Attach(int hnd)
{
s2comid = hnd;
}
/*
* 打开指定的串口设备
* 如果devname=NULL则直接使用s2comid的当前值; speed=-1则不设置速率
* 返回:该设备句柄,-1表示不能打开
*/
int com_OpenDevice(char *devname, long speed)
{
struct termios tm;
s2istty = (devname==NULL);
if (devname != NULL) s2comid = open(devname, 2);
if (s2comid != -1) {
ioctl(s2comid, TCGETA, &s2orgtm);
memcpy(&tm, &s2orgtm, sizeof(tm));
tm.c_iflag = 0;
tm.c_oflag = 0;
tm.c_lflag = 0;
tm.c_cflag = CS8|HUPCL;
tm.c_cc[VMIN] = 1;
if (speed != -1) {
tm.c_cflag &= ~CBAUD;
switch (speed) {
case 1200:
tm.c_cflag |= B1200;
break;
case 2400:
tm.c_cflag |= B2400;
break;
case 4800:
tm.c_cflag |= B4800;
break;
case 19200:
tm.c_cflag |= B19200;
break;
default:
tm.c_cflag |= B9600;
}
}
ioctl(s2comid, TCSETA, &tm);
}
return s2comid;
}
/*
* 关闭串行设备
*/
void com_CloseDevice(void)
{
if (s2comid != -1) {
ioctl(s2comid, TCSETA, &s2orgtm);
if (!s2istty) close(s2comid);
s2comid = -1;
}
}
/*
* 发送一个指定长度的包。timeout=-1永远等待, 0=无超时,否则为超时值(秒)
* 返回:0-成功,-3-超时
*/
int com_Send(char *buff, int len, int timeout)
{
fd_set v_send;
struct timeval t_out;
int rc, tmax, tleft;
#ifdef DEBUG_S
DebugStr(buff, len, 'w');
#endif
if (timeout > 0) {
tmax = time(NULL)+timeout;
tleft = timeout;
}
do {
FD_ZERO(&v_send);
FD_SET(s2comid, &v_send);
if (timeout >= 0) {
t_out.tv_sec = timeout?tleft:0;
t_out.tv_usec = 0;
}
rc = select(s2comid+1, NULL, &v_send, NULL, timeout==-1? NULL:&t_out);
if (rc == -1 || !FD_ISSET(s2comid, &v_send)) break;
rc = write(s2comid, buff, len);
if (rc > 0) {
buff += rc;
len -= rc;
if (len <= 0) return 0;
}
if (timeout == 0) break;
tleft = tmax - time(NULL);
} while (tleft > 0);
return -3;
}
/*
* 接收一个不超过指定长度的包。timeout=-1永远等待, 0=无超时,否则为超时值(秒)
* 返回:>0-成功收到的字节数,-3-超时
*/
int com_Recv(char *buff, int maxlen, int timeout)
{
fd_set v_recv;
struct timeval t_out;
int rc;
FD_ZERO(&v_recv);
FD_SET(s2comid, &v_recv);
if (timeout >= 0) {
t_out.tv_sec = timeout;
t_out.tv_usec = 0;
}
rc = select(s2comid+1, &v_recv, NULL, NULL, timeout==-1? NULL:&t_out);
if (rc == -1 || !FD_ISSET(s2comid, &v_recv)) return -3;
rc = read(s2comid, buff, maxlen);
#ifdef DEBUG_S
DebugStr(buff, rc, 'r');
#endif
if (rc > 0) return rc;
return -3;
}
/*
* 清除收发缓冲: 0=清读,1=清写,2=清读写
*/
void com_Flush(void)
{
ioctl(s2comid, TCFLSH, 2);
}
main()
{
com_Flush();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -