Linux下串口发送数据一段数据后发送不出去(可以正常接收)

Linux下串口发送数据一段数据后发送不出去(可以正常接收),在PC调试时一切正常,但是连接到别的板子上做数据透传时出现了这样的问题

解决办法:是串口的配置有问题,修改代码
用serial_init()初始化ttyS*串口
用open_ttyusb_port()和ttyusb_set_opt() 打开并配置ttyUSB*即可

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>

#include "gw_debug.h"
#include "uart.h"



//#define UART_DEBUG
static int support_baud[] = {
    0,     50,    75,    110,    134,    150,   200,
    300,   600,   1200,  1800,   2400,   4800,  9600,
    19200, 38400, 57600, 115200, 230400,
};

int is_support_baud(int baud)
{
    int i = 0;

    for (i = 0; i < ARRAY_SIZE(support_baud); i++)
        if (support_baud[i] == baud)
            return 1;

    return 0;
}

static speed_t int_to_speed(int baud)
{
    if (is_support_baud(baud)) {
        switch (baud) {
        case 0:
            return B0;
        case 50:
            return B50;
        case 75:
            return B75;
        case 110:
            return B110;
        case 134:
            return B134;
        case 150:
            return B150;
        case 200:
            return B200;
        case 300:
            return B300;
        case 600:
            return B600;
        case 1200:
            return B1200;
        case 1800:
            return B1800;
        case 2400:
            return B2400;
        case 4800:
            return B4800;
        case 9600:
            return B9600;
        case 19200:
            return B19200;
        case 38400:
            return B38400;
        case 57600:
            return B57600;
        case 115200:
            return B115200;
        case 230400:
            return B230400;
        default:
            return GW_FAIL;
        }
    }

    return GW_FAIL;
}
#ifdef UART_DEBUG 
static void serial_dump(unsigned char *data, int len)
{
    int i = 0;

    printf("data 0 ~ %d: ", len);
    for (i = 0; i < len; i++)
        printf("%x, ", data[i]);

    printf("\n");
    return;
}
#endif
int serial_init(UART_EX id, int baud)
{
    int fd = -1;
    char name[50] = {0};
    struct termios options;
    speed_t speed;

    if (id < UART_0 || id > UART_3 || !is_support_baud(baud))
        return GW_FAIL;
#if 0
    sprintf(name, "/dev/ttyUSB%d", id);
#else
    sprintf(name, "/dev/ttyS%d", id);
#endif

    fd = open(name, O_RDWR | O_NOCTTY);
    if (fd < 0) {
        perror("Can't open Serial Port");
        return GW_FAIL;
    }

    tcgetattr(fd, &options);

    options.c_cflag |= (CLOCAL | CREAD); //disenable dcd, start read func
    options.c_cflag &= ~CRTSCTS; //close hard stream control
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8; //set data bit 8 (8N1)
    options.c_cflag &= ~(PARENB | CSTOPB); //no use parity check bit and stop bit 1
    options.c_cflag &= ~(ICRNL | IXON);
    options.c_oflag = 0;
    options.c_lflag = 0;

    options.c_iflag &= ~(BRKINT | INPCK | ISTRIP | ICRNL | IXON);

    speed = int_to_speed(baud);
    cfsetispeed(&options, speed);
    cfsetospeed(&options, speed);

    tcsetattr(fd, TCSANOW, &options);

    return fd;
}

int uart_send(int fd, unsigned char *data, int data_len)
{
    int len = 0;

    if (!data || fd < 0 || data_len > UART_DATA_LEN)
        return GW_FAIL;

    len = write(fd, data, data_len);
    if (len == data_len)
        return len;
    else {
        tcflush(fd, TCOFLUSH);
        return GW_FAIL;
    }
}

int uart_recv(int fd, unsigned char *data, int data_len)
{
    int len = 0;

    if (fd < 0 || !data || data_len > UART_DATA_LEN)
        return GW_FAIL;

    len = read(fd, data, data_len);
    if (len < 0)
        return GW_FAIL;
#ifdef UART_DEBUG 
    serial_dump(data, len);
#endif

    return len;
}


int ttyusb_set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop, int time)
{
  struct termios newtio,oldtio;
  if ( tcgetattr( fd,&oldtio) != 0) { 
    perror("SetupSerial 1");
    return -1;
  }
//  bzero( &newtio, sizeof( newtio ) );
  newtio = oldtio;
  newtio.c_cflag |= CLOCAL | CREAD; 
  newtio.c_cflag &= ~CSIZE; 
  switch( nBits )
  {
  case 7:
    newtio.c_cflag |= CS7;
    break;
  case 8:
    newtio.c_cflag |= CS8;
    break;
  }

  switch( nEvent )
  {
  case 'O':
    newtio.c_cflag |= PARENB;
    newtio.c_cflag |= PARODD;
    newtio.c_iflag |= (INPCK | ISTRIP);
    break;
  case 'E': 
    newtio.c_iflag |= (INPCK | ISTRIP);
    newtio.c_cflag |= PARENB;
    newtio.c_cflag &= ~PARODD;
    break;
  case 'N': 
    newtio.c_cflag &= ~PARENB;
    break;
  }

switch( nSpeed )
  {
  case 2400:
    cfsetispeed(&newtio, B2400);
    cfsetospeed(&newtio, B2400);
    break;
  case 4800:
    cfsetispeed(&newtio, B4800);
    cfsetospeed(&newtio, B4800);
    break;
  case 9600:
    cfsetispeed(&newtio, B9600);
    cfsetospeed(&newtio, B9600);
    break;
  case 57600:
    cfsetispeed(&newtio, B57600);
    cfsetospeed(&newtio, B57600);
    break;
  case 115200:
    cfsetispeed(&newtio, B115200);
    cfsetospeed(&newtio, B115200);
    break;
  default:
    cfsetispeed(&newtio, B57600);
    cfsetospeed(&newtio, B57600);
    break;
  }
  if( nStop == 1 )
    newtio.c_cflag &= ~CSTOPB;
  else if ( nStop == 2 )
  newtio.c_cflag |= CSTOPB;

  newtio.c_cc[VTIME] = time;
  newtio.c_cc[VMIN] = 0;

  tcflush(fd,TCIFLUSH);
  if((tcsetattr(fd,TCSANOW,&newtio))!=0)
  {
    perror("com set error");
    return -1;
  }
  printf("set done!\n");
  return 0;
}

int open_ttyusb_port(int fd,int comport)
{
  char *dev[]={"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2", "/dev/ttyUSB3"};
  long vdisable;
  if (comport==0)
  { fd = open( "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd){
      perror("Can't Open Serial Port");
      return(-1);
    }
    else 
      printf("open ttyUSB0 .....\n");
  }
  else if(comport==1)
  { fd = open( "/dev/ttyUSB1", O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd){
      perror("Can't Open Serial Port");
      return(-1);
    }
    else 
      printf("open ttyUSB1 .....\n");
  }
  else if (comport==2)
  {
    fd = open( "/dev/ttyUSB2", O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd){
      perror("Can't Open Serial Port");
      return(-1);
    }
    else 
      printf("open ttyUSB2 .....\n");
  }
  else if (comport==3)
  {
    fd = open( "/dev/ttyUSB3", O_RDWR|O_NOCTTY|O_NDELAY);
    if (-1 == fd){
      perror("Can't Open Serial Port");
      return(-1);
    }
    else 
      printf("open ttyUSB3 .....\n");
  }

  if(fcntl(fd, F_SETFL, 0)<0)
    printf("fcntl failed!\n");
  else
    printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
  if(isatty(STDIN_FILENO)==0)
    printf("standard input is not a terminal device\n");
  else
    printf("isatty success!\n");

  printf("fd-open=%d\n",fd);
  return fd;
}

以下是发送接收逻辑,分别在单独的线程中进行

//发送
while (1) {
        //encodeLen = util_encode(cmd, 2, outbuf, 10);

        ret = uart_send(fd, cmd, sizeof(cmd));
        printf("WRITE[%d]\n", ret);

        sleep(1);
    }

//接收(阻塞接收)
while (1) {
        readLen = uart_recv(fd, buf, SER_BUF_LEN);
        if (readLen < 0) {
            continue;
        }

这个是在论坛别人遇到的相同的情况http://bbs.csdn.net/topics/310158478

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Linux 中使用 C 语言实现串口接收任意长度的数据,你可以使用以下代码作为参考: ```c #include <stdio.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> int main() { int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY); if (fd == -1) { perror("Open serial port failed"); return 1; } struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B9600); // 设置波特率为9600 cfsetospeed(&options, B9600); options.c_cflag |= (CLOCAL | CREAD); // 必要的控制标志 options.c_cflag &= ~PARENB; // 禁用奇偶校验 options.c_cflag &= ~CSTOPB; // 1位停止位 options.c_cflag &= ~CSIZE; // 清除数据位设置 options.c_cflag |= CS8; // 设置数据位为8位 tcsetattr(fd, TCSANOW, &options); char buffer[255]; // 接收缓冲区 int bytesRead = 0; // 已读取字节数 int totalBytesRead = 0; // 总共读取字节数 while (1) { bytesRead = read(fd, buffer + totalBytesRead, sizeof(buffer) - totalBytesRead); if (bytesRead > 0) { totalBytesRead += bytesRead; // 检查是否接收整的数据,可以根据自己的需求进行处理 if (buffer[totalBytesRead - 1] == '\n') { // 处理接收到的数据 buffer[totalBytesRead] = '\0'; // 添加字符串结尾符 printf("Received: %s", buffer); totalBytesRead = 0; // 重置总共读取字节数 } } } close(fd); return 0; } ``` 这段代码打开了串口设备文件`/dev/ttyS0`(根据你的实际情况可能需要修改)并设置了串口参数,如波特率、数据位、停止位等。然后,通过循环不断地读取串口数据。 在每次读取数据后,我们检查是否接收整的数据。这里的判断是根据接收到的数据中是否包含换行符('\n')来确定的。如果接收到了整的数据,我们可以对其进行处理,例如打印出来。然后,重置总共读取字节数,以准备接收一段数据。 请注意,在实际应用中,你可能需要根据自己的需求对代码进行适当的修改和优化。同时,还应该处理错误和异常情况,以确保程序的稳定性和可靠性。 希望这个例子可以帮助你实现串口接收任意长度的数据。如有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值