serial programming - termios and read/write raw...

本文讨论了在使用tty(UART)进行通信时遇到的字符乱码问题,通过termios结构体深入理解控制字符处理,并展示了如何清除特定位字段以避免乱码现象。文章还介绍了如何设置raw模式进行数据的直接读写,以及如何调整c_cc数组来控制读取行为。

​上次 tty (UART) 的測試,結果我丟一個 0x0d, 0x0a ,對方卻收到 0x0d,0x0d,0x0a。 因為tty 會特別處理 控制字元,用 termios structure 可以知道:

<!-- lang: cpp -->
tty = open("/dev/ttymxc2",O_RDWR | O_NOCTTY | O_NONBLOCK);
tcgetattr(tty,&tio);
printf("c_oflag:");
if(tio.c_oflag & OPOST){
        printf("OPOST ");
        if( tio.c_oflag & ONLCR)
                printf("-ONLCR");
        if( tio.c_oflag & OCRNL)
                printf("-OCRNL");
        if( tio.c_oflag & ONOCR)
                printf("-ONOCR");
        if( tio.c_oflag & ONLRET)
                printf("-ONLRET");
        printf("\n");
}
printf("c_iflag:");
if(tio.c_iflag & IGNBRK)
        printf("-IGNBRK");
if(tio.c_iflag & BRKINT)
        printf("-BRKINT");
if(tio.c_iflag & IGNPAR)
        printf("-IGNPAR");
if(tio.c_iflag & PARMRK)
        printf("-PARMRK");
if(tio.c_iflag & INPCK)
        printf("-INPCK");
if(tio.c_iflag &  ISTRIP)
        printf("-ISTRIP");
if(tio.c_iflag & INLCR)
        printf("-INLCR");
if(tio.c_iflag & IGNCR)
        printf("-IGNCR");
if(tio.c_iflag & ICRNL)
        printf("-ICRNL");
if(tio.c_iflag & IUCLC)
        printf("-IUCLC");
if(tio.c_iflag & IXON)
          printf("-IXON");
if(tio.c_iflag & IXANY)
        printf("-IXANY");
if(tio.c_iflag & IXOFF)
        printf("-IXOFF");
if(tio.c_iflag & IMAXBEL)
        printf("-IMAXBEL");
printf("\n");

run 的結果是: c_oflag:OPOST -ONLCR c_iflag:-ICRNL-IXON 參考這一篇,有解釋每個 bit field 的意義。 ONLCR - 會把 0x0a 變成 0x0d,0x0a. 所以我要把 OPST 這個 bit clear 掉... 要 read raw data, 參考 這一篇 (Serial Proramming Guide in POSIX System)。 termios 的 lflag 是: options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 如果是要 output raw data,就只要: options.c_oflag &= ~OPOST;... 那篇文章最後就有 raw data input/output 的 code:

<!-- lang: cpp -->

int fd; struct termios options;

/* open the port */ fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); fcntl(fd, F_SETFL, 0);

/* get the current options */ tcgetattr(fd, &options);

/* set raw input, 1 second timeout */ options.c_cflag |= (CLOCAL | CREAD); options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); options.c_oflag &= ~OPOST; options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 10;

/* set the options */ tcsetattr(fd, TCSANOW, &options);

/* set the options */ tcsetattr(fd, TCSANOW, &options); read tty 的動作 (block, no block , wait time, how many bytes.. etc) 是由 c_cc[VMIN], c_cc[VTIME] 的值決定的。 有關 c_cc[] 中 VMIN, VTIME 的功能: (ref : Nonecanonical Input)

VMIN : 至少收到多少 bytes 後 returnVTIME : 達成 收到 VMIN bytes 的條件後,多少時间timout 後 return.

所以..

c_cc[VMIN], c_cc[VTIME] 的值都是 0 : 有沒有資料都會立刻 return,不過有資料的時候,會把資料都讀出來再return.

c_cc[VMIN]=0, c_cc[VTIME] 不是 0 : 等 c_cc[VTIME] 都沒有資料就 return.,如果有收到 data 就立刻 return

c_cc[VMIN] 不是 0, c_cc[VTIME] = 0 : 一定要等到收到 c_cc[VMIN] 個資料後才 return. c_cc[VMIN], c_cc[VTIME] 都不是 0 : ..

後來又發現,對方送 0x0d, 0x0a,我收到 0x0a, 0x0a。 確認一下, c_iflag 要 mask 掉+ options.c_iflag &= ~(INLCR | IGNCR | ICRNL);才行

转载于:https://my.oschina.net/fenglinwansu/blog/158283

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值