设置串口参数

时间:2016-03-23 10:42:17

标签: c linux

在我的程序中,使用串行端口打开连接,该端口接收具有设定频率(通常为100 Hz)的10字节包。但是我遇到了以下问题:有时(但并非总是)当我关闭连接时,程序会挂起。

在下面的代码中,我没有指定常量;在运行时连接参数(波特率,奇偶校验...)由命令行确定。实际上,通常以波特率230400,无奇偶校验,8位字符大小和1个停止位打开连接。

这就是我打开串口的方式:

struct termios config;
LOGPRINT("Will operate on device \'%s\'\n", pconfig->device);
LOGPRINT("Opening serial device\n");
int flag = O_RDWR | O_NOCTTY | ASYNC_LOW_LATENCY;
// pconfig contains some necessary information to set connection parameters
// async == false for connectin that causes problems
int fd = open(pconfig->device, async? flag | O_NONBLOCK: flag);
if(fd == -1)
{ /* skipped error handling */  }

LOGPRINT("Retrieving terminal attributes\n");
if(!!tcgetattr(fd, &config))
{ /* skipped error handling */  }
else
{
    // backup old configuration for restoring it on exit
    if(poldconfig != NULL)
        memcpy(poldconfig, &config, sizeof(struct termios));

    LOGPRINT("Setting terminal attributes\n");
    set_attribs(fd, &config, pconfig);
}
...
int set_attribs(const int fd, struct termios* pterm, const struct serial_config* pconfig)
{
    // set baud rate
    // baud_rates contains integers of actual rates
    LOGPRINT("Setting baud rate to %d.\n", baud_rates[pconfig->baud_rate_index]);
    // change to raw mode
    LOGPRINT("Setting terminal to raw mode\n");
    pterm->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
                        | IGNCR | ICRNL | IXON);
    pterm->c_oflag &= OPOST;
    pterm->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    // baud_bits contains actual pre-defined baud rate flags
    cfsetispeed(pterm, baud_bits[pconfig->baud_rate_index]);
    cfsetospeed(pterm, baud_bits[pconfig->baud_rate_index]);
    LOGPRINT("Set character size, parity and stop bit flags.\n");
    // set character size
    pterm->c_cflag &= ~CSIZE;
    pterm->c_cflag |= pconfig->csize_flag;
    // set parity
    pterm->c_cflag &= ~(PARENB | PARODD);
    pterm->c_cflag |= pconfig->parity_flag;
    // set stopbits
    pterm->c_cflag &= ~CSTOPB;
    pterm->c_cflag |= pconfig->stopbits_flag;

    // enable reading; ignore control lines
    pterm->c_cflag |= CREAD | CLOCAL;
    LOGPRINT("Flush terminal.\n");
    // flush terminal
    tcflush(fd, TCIOFLUSH);
    LOGPRINT("Apply parameters.\n");
    return tcsetattr(fd, TCSANOW, pterm);
}

出于正当理由,我需要强制串行设备驱动程序使用1字节缓冲区来处理传入/传出数据,这是我使用此功能设置的:

int set_port_type(int fd, int ptype)
{
    struct serial_struct temp;
    int res = ioctl(fd, TIOCGSERIAL, &temp);
    if(!!res)
    { /* stipped error handling */ }
    temp.type = ptype;
    res = ioctl(fd, TIOCSSERIAL, &temp);
    if(!!res)
    { /* stipped error handling */ }
    return res;
}

ptype = PORT_UNKNOWN或ptype = PORT_16450。

完成串口后,执行以下操作:

  1. 冲洗
  2. 将其类型设置回16550A
  3. 将其settigns恢复为已保存的
  4. 关闭它
  5. 它会不时导致程序挂起并停止响应任何外部刺激。它迫使我暂停程序,然后重启系统,因为它永远不会释放它所拥有的文件描述符。

    我能做些什么来确保不会发生这种情况?即使设置未恢复,程序也需要自行关闭 - 可能是错误代码。

    我正在使用的操作系统是TinyCore Linux。没有其他用户程序与我的程序同时运行。

    重要的澄清。我正在使用的串行设备实际上是NPort 5232 - 异步RS-422/485 - 以太网通信器(description from vendor。因此,我使用的串行设备是虚拟的,这使我能够尝试改变它们的类型/大小内部缓冲区。

0 个答案:

没有答案