LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2688|回复: 12

linux串口多线程读写

[复制链接]
发表于 2010-3-8 11:33:42 | 显示全部楼层 |阅读模式
我起了两个线程来操作串口:一个用于读数据,一个用于写数据。该程序用于两个arm9之间的串口全双工通信:即用一根串口线将两块板子连接起来。
问题是:我不知道该在哪里打开串口,若在主线程main中打开,则双方的读线程都收到乱码,同时也可以检测出写线程发出去的字符也有异常;若读写线程各自单独打开关闭串口,则写线程可以发出字符,但读线程始终无法读到数据。难道是我的线程有问题?
目前本人正处于非常苦恼之中,清各位大侠帮忙,贴出我的代码如下:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <termios.h>
#include <pthread.h>

#define NUM  20
int fd;

void writeThread(void* arg);
void readThread(void* arg);
/*
int openport(void)
  {
  //    int fd;
      struct termios options;
      if((fd=open("/dev/tts/0",O_RDWR|O_NOCTTY|O_NONBLOCK|O_NDELAY))==-1)
      {
          perror("Can't open serial1 port.");
          return -1;
      }
/*      tcgetattr(fd,&options);
    cfsetispeed(&options,B9600);
    cfsetospeed(&options,B9600);
      options.c_cflag|=(CLOCAL|CREAD);    //忽略控制信号线和使能读功能
      options.c_cflag|=PARENB;    //奇偶检验
      options.c_cflag&=~PARODD;    //偶校验
      options.c_iflag |= (INPCK | ISTRIP);
      options.c_cflag|=CSTOPB;    //两个停止位
      options.c_cflag&=~CSIZE;
      options.c_cflag|=CS8;    //8个数据位
      options.c_lflag&=~(ICANON|ECHO|ISIG);    //原始输入模式
      options.c_oflag&=~OPOST;    //原始输出

      options.c_cc[VMIN]=0;
      options.c_cc[VTIME]=0;
      tcsetattr(fd,TCSANOW,&options);

printf("\nfd = %d\n",fd);
      return fd;
  }
*/

int
main(int argc, char* argv[])
{
int iret;
pthread_t id1, id2;

if((fd=open("/dev/tts/0",O_RDWR|O_NOCTTY|O_NONBLOCK|O_NDELAY))==-1)
      {
          perror("Can't open serial1 port.");
          return -1;
      }

iret = pthread_create(&id1, NULL, (void*)readThread, NULL);
if(iret != 0) {
printf("\nthread1_create is failed!\n");
}

iret = pthread_create(&id2, NULL, (void*)writeThread, NULL);
if(iret != 0) {
printf("\nthread1_create is failed!\n");
}

pthread_join(id1, NULL);
pthread_join(id2, NULL);

close(fd);
return 0;
}

void readThread(void* arg)
{
int nread, i;
int rcount = 0;
unsigned char buf[21];
while(1) {
sleep(1);
printf("\nnow it begain to read words.\n");
// printf("\nbefore reading, the words inf buf are  %s\n",buf);
nread = read(fd, buf, 20);
if(nread == 20) {
printf("\nnread=%d", nread);
for(i = 0; i < 20; i++) {
printf("%c ", buf[1]);
}
rcount++;
printf("\nreceive packets: %d\n", rcount);
}
}
}

void writeThread(void* arg)
{
int i,j;
int fd;
unsigned char k = 'a';
int m;
int nwrite;
int scount = 0;
unsigned char serialTest[NUM] = {0};

for(m= 0;m <NUM;m++)
{
serialTest[m] = k++;
}
/* open serial port */
while(1) {
sleep(1);
fd=open("/dev/tts/0",O_RDWR|O_NOCTTY|O_NONBLOCK|O_NDELAY);
nwrite = write(fd, serialTest, NUM);
write(fd, "\n", 1);
if(nwrite == 20) {
printf("\nwriteRadioFramewriteRadioFramewriteRadioFramewriteRadioFrame\n");
printf("\nnwrite = %d\n", nwrite);
for(j = 0; j < NUM; j++) {
printf("%c ",serialTest[j]);
}
scount++;
printf("\nsend packets: %d \n", scount++);
printf("\nwriteRadioFramewriteRadioFramewriteRadioFramewriteRadioFrame\n");
}
close(fd);
}
}
 楼主| 发表于 2010-3-8 14:59:56 | 显示全部楼层
这里与串口的打开方式有关吗?
比如串口以独占方式打开,这样的话,请问哪位大虾知道如何以独占方式打开串口?
回复 支持 反对

使用道具 举报

发表于 2010-3-8 17:08:10 | 显示全部楼层
打开方式去掉O_NONBLOCK和O_NDELAY试试。
回复 支持 反对

使用道具 举报

发表于 2010-3-8 17:16:23 | 显示全部楼层
哇!你的串口被打开了n次!没这样试过。
既然你的fd是全局变量,我觉得你只要在操作fd之前保证fd指向你打开的串口就行了。
乱码可能是你的线程没做好同步造成的,简单验证的方法就是先不要用多线程,在单一进程下尝试下收发,如果没问题,那么就是你同步没做好造成的!
一般地向串口写数据和读数据都需要一系列的操作才能完成的,如果你同时收发把他们的顺序打乱了,就不能正常工作了!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-3-8 17:47:30 | 显示全部楼层
将O_NONBLOCK和O_NDELAY去掉后,每块板子就什么都收不到了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-3-8 17:52:37 | 显示全部楼层
我做单向测试时,发现若想用一个线程来连续发包,就必须每发一个包就打开关闭串口一次,否则,在接受段就无法正确收到数据。所以,我才进行多次打开关闭串口操作。
至于线程同步,我在读写线程都上了锁:pthread_mutex_t mut;但结果还是有乱码。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-3-8 17:54:29 | 显示全部楼层
Post by haohao_h;2073976
哇!你的串口被打开了n次!没这样试过。
既然你的fd是全局变量,我觉得你只要在操作fd之前保证fd指向你打开的串口就行了。
乱码可能是你的线程没做好同步造成的,简单验证的方法就是先不要用多线程,在单一进程下尝试下收发,如果没问题,那么就是你同步没做好造成的!
一般地向串口写数据和读数据都需要一系列的操作才能完成的,如果你同时收发把他们的顺序打乱了,就不能正常工作了!
请教haohao_h大侠,如何做到线程同步?
回复 支持 反对

使用道具 举报

发表于 2010-3-8 18:04:34 | 显示全部楼层
你没有理解VMIN和VTIME的含义。
回复 支持 反对

使用道具 举报

发表于 2010-3-8 18:09:57 | 显示全部楼层
Post by silink;2073983
我做单向测试时,发现若想用一个线程来连续发包,就必须每发一个包就打开关闭串口一次,否则,在接受段就无法正确收到数据。所以,我才进行多次打开关闭串口操作。
至于线程同步,我在读写线程都上了锁:pthread_mutex_t mut;但结果还是有乱码。

我的建议是由简到繁,先把单进程收发调通了,再去调多线程收发。照你的这个说法,你目前的环境是有问题的,往串口中多次写入数据,没理由要多次打开关闭串口的,如果是缓存造成的话,每次写完后,尝试下fflush,如果还是不行的话,要跟进串口驱动里去看看了。
对于接收我觉得你也还是先调通单向收的好!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-3-8 20:46:16 | 显示全部楼层
Post by haohao_h;2073987
我的建议是由简到繁,先把单进程收发调通了,再去调多线程收发。照你的这个说法,你目前的环境是有问题的,往串口中多次写入数据,没理由要多次打开关闭串口的,如果是缓存造成的话,每次写完后,尝试下fflush,如果还是不行的话,要跟进串口驱动里去看看了。
对于接收我觉得你也还是先调通单向收的好!
好的,多谢haohao_h,今天我也仔细想了一下,发现我的单向通信确实存在问题,我会再试试的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表