| 接口名称 | 目的 |
|---|---|
tcgetattr(3C), tcsetattr(3C) | 获取并设置终端属性 |
tcsendbreak(3C), tcdrain(3C), tcflush(3C), tcflow(3C) | 执行行控制接口 |
cfgetospeed(3C), cfgetispeed(3C)cfsetispeed(3C), cfsetospeed(3C) | 获取并设置波特率 |
tcsetpgrp(3C) | 获取并设置终端前台进程组 ID |
tcgetsid(3C) | 获取终端会话 ID |
以下示例说明服务器如何从其处于非 DEBUG 操作模式下的调用方的控制终端分离出来。
tcflush函数清空输入缓存区(终端驱动已经接收到数据,但用户尚未读)或输出缓存(用户已经写,但尚未发送). int tcflush(int filedes,int quene)
quene数该当是下列三个常数之一:
*TCIFLUSH 刷清输入队列
*TCOFLUSH 刷清输出队列
*TCIOFLUSH 刷清输入、输出队列
例如:
tcflush(fd,TCIFLUSH);
tcflush(fdcom, TCIFLUSH);
sleep(2);
RecvLen = PortRecv(fdcom, RecvBuf, 10, portinfo.baudrate);
TCOOFF:输出被挂起(暂停输出)
TCOON:重新启动以前被挂起(暂停)的输出
TCIOFF:系统发送一个STOP字符。这将使终端设备暂停发送数据。
TCION:系统发送一个START字符。这将使终端恢复发送数据。
rs485Service.h
#ifndef __RS485_SERVER_H__
#define __RS485_SERVER_H__
#include "dataType.h"
typedef enum
{
OPEN_485_SUCCESS = 0,
OPEN_485_FAIL,
}Open485State;
class Rs485Service
{
private:
Rs485Service();
~Rs485Service();
public:
static Rs485Service& Get();
public:
int Rs485Read(ubyte *buf, uint32 size);
int Rs485Write(const ubyte *data, uint32 len);
int InitRs485Dev(uint32 bound);
void UninitRs485Dev();
private:
int m_devFd;
int m_bound;
int32_t m_485WriteState; //true 485处于写状态
};
#endif
rs485Service.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "rs485Service.h"
#define RS485COM "/dev/???"
Rs485Service::Rs485Service()
{
m_devFd = -1;
}
Rs485Service::~Rs485Service()
{
}
Rs485Service& Rs485Service::Get()
{
static Rs485Service Rs485server;
return Rs485server;
}
int Rs485Service::InitRs485Dev(uint32 bound)
{
/*
* Hi3536 GPIO的读写操作,有两种方法:
* 1、重新编写GPIO的驱动程序,在通过访问设备进行GPIO的读写
。
* 2、根据海思提供的工具himm,进行寄存器值的读写
* sprintf(buffer, "himm 0x%x r", data_addr);
* system(buffer);
* sprintf(buffer, "himm 0x%x 0x%x", data_addr, (value << (pin)) );
* system(buffer);
*/
system("himm 0x11111111 1");
system("himm 0x2222222 1");
system("himm 0x33333333 0");
system("echo ???> /sys/class/gpio/export");
system("echo out > /sys/class/gpio/gpio???/direction");
system("echo 0 > /sys/class/gpio/gpio???/value");
m_devFd = open(RS485COM, O_RDWR | O_NOCTTY); //加上O_NDELAY,就变为了非阻塞
if (m_devFd != -1)
{
struct termios cfg;
memset(&cfg, 0, sizeof(cfg));
tcgetattr(0, &cfg);
switch(bound)
{
case 19200:
cfsetispeed(&cfg, B19200);
cfsetispeed(&cfg, B19200);
m_bound = 19200;
break;
case 9600:
cfsetispeed(&cfg, B9600);
cfsetispeed(&cfg, B9600);
m_bound = 9600;
break;
default:
cfsetispeed(&cfg, B19200);
cfsetispeed(&cfg, B19200);
m_bound = 19200;
break;
}
cfg.c_oflag &= ~(ONLCR);
cfg.c_oflag &= (OCRNL);
cfg.c_iflag &= (INLCR);
cfg.c_cflag |= CLOCAL | CREAD; //使能串口输入
//cfg.c_lflag |= ICANON; //标准模式
cfg.c_lflag &= ~ICANON;//原始模式
cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
//8bit数据
cfg.c_cflag &= ~CSIZE;
cfg.c_cflag |= CS8;
//1bit停止位
cfg.c_cflag &= ~CSTOPB;
//无校验
cfg.c_cflag &= ~PARENB;
//禁用硬件流控制:
cfg.c_cflag &= ~CRTSCTS;
// cfg.c_cc[VTIME] = 1; //设置超时时间,如果采用非阻塞模式则不设置
cfg.c_cc[VMIN] = 1; //设置最小接收的数据长度
//清楚输入输出缓冲区
tcflush(m_devFd, TCIOFLUSH);
tcsetattr(m_devFd, TCSANOW, &cfg);
return OPEN_485_SUCCESS;
}
else
{
printf("open dev err.\n");
return OPEN_485_FAIL;
}
}
void Rs485Service::UninitRs485Dev()
{
if (m_devFd != -1)
{
struct termios cfg;
memset(&cfg, 0, sizeof(cfg));
tcgetattr(0, &cfg);
cfg.c_cc[VTIME] = 1;
tcflush(m_devFd, TCIOFLUSH);
tcsetattr(m_devFd, TCSANOW, &cfg);
close(m_devFd);
}
}
int Rs485Service::Rs485Read(ubyte* buf, uint32 size)
{
int rlen = -1;
if (m_devFd != -1)
{
rlen = read(m_devFd, buf, size);
tcflush(m_devFd, TCIOFLUSH);
}
return rlen;
}
int Rs485Service::Rs485Write(const ubyte* data, uint32 len)
{
int wlen = -1;
//485是半双工,置为发送状态
system("echo 1 > /sys/class/gpio/gpio42/value");
if (m_devFd != -1)
{
wlen = write(m_devFd, data, len);
}
//等待数据输出完毕
tcdrain(m_devFd);
//清空输入输出缓冲区
tcflush(m_devFd, TCIOFLUSH);
//485是半双工,置为接收状态
system("echo 0 > /sys/class/gpio/gpio42/value");
return wlen;
}