天嵌 ARM开发社区

 找回密码
 注册
查看: 3565|回复: 7

linux 2.6.30.4 串口驱动问题

[复制链接]
liehuo5210 发表于 2010-6-2 12:35:47 | 显示全部楼层 |阅读模式
最近做项目用到串口通信,碰到问题如下:                              
无论用串口收数据还是发数据,始终用的都是控制台所用的串口(终端为超级终端和CRT),而不能用其他串口,
既无论我开串口几,都是在当前串口,也就是控制台串口打印。
看懂的可不看例

/***********************************************************************************************************************************************************************************************************
例如:

我现在要用串口发的程序发数据,板子控制台用的是串口0(正常的是ttyS0,我的板子是tq2440_serial0,以此类推),open的是串口1,既发数据用的是串口1;
1,运行程序,串口0发送成功,在控制台打印出发送信息,而串口1的终端没反应;
2,而然后我不连接串口1的串口线,运行程序,串口0依然发送成功,在控制台打印出发送信息。
3,依然不连接串口一的串口线,仍然只连接控制台,也就是串口0的串口线,open依次改为串口2,。。。娱乐一下,改为串口4X,多次验证,结果依然以串口0发送,成功;
4,NOW我们把控制台控制权交给串口1,重复上述实验,结果为无论open的是串口几,都是在控制台串口,既串口1,发送成功,其他串口无反应(串口线插着);拔掉其他串口,只剩控制台串口,发送依然成功;
5,若OPEN错误的设备,则程序无法执行,但只要是个串口,哪怕是ttyS4X,5X,只要设备里有,就会在控制台串口下发收数据,且open的串口无法应;
串口接收程序同上;
************************************************************************************************************************************************************************************************************/


经认识的高人分析,可能是内核串口驱动这块有问题;
我的收发程序如下:
uart.c 串口设置程序uartwf.c发程序 uartrf.c收程序

//uart.c          串口配置

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

struct termios old_cfg;
int speed_arr[]={B115200,B57600,B38400,B19200,B9600,B4800,B2400,B1800};
int name_arr[]={115200,57600,38400,19200,9600,4800,2400,1800};
int set_speed(int fd,int speed){
int i;
int ret;
struct termios Opt;
tcgetattr(fd,&Opt);
for(i=0;i<sizeof(speed_arr)/sizeof(speed_arr[0]);i++){
  if(speed=name_arr){
   tcflush(fd,TCIOFLUSH);
   cfsetispeed(&Opt,speed_arr);
   cfsetispeed(&Opt,speed_arr);
#if 1
   Opt.c_cflag|=CLOCAL|CREAD;
   Opt.c_oflag&=~(OPOST);
//   cfmakeraw(&Opt);
   Opt.c_lflag&=~(ICANON|ISIG|ECHO|IEXTEN);
//   Opt.c_lflag=ICANON;
   Opt.c_iflag&=~(INPCK|BRKINT|ICRNL/*|IGNCR|INLCR*/|ISTRIP|IXON);
//   Opt.c_iflag=0;
//   Opt.c_iflag|=IGNPAR|IGNBRK;
#if 0
/*   初始化所有的控制特性预设值可以在   /usr/include/termios.h   找到,     
                在注解中也有,   但我们在这不需要看它们   */   
          Opt.c_cc[VINTR]         =   0;           /*   Ctrl-c   */   
          Opt.c_cc[VQUIT]         =   0;           /*   Ctrl-\   */   
          Opt.c_cc[VERASE]       =   0;           /*   del   */   
          Opt.c_cc[VKILL]         =   0;           /*   @   */   
          Opt.c_cc[VEOF]           =   0;           /*   Ctrl-d   */   
//        Opt.c_cc[VTIME]         =   5;           /*   不使用分割字元组的计时器   */   
//        Opt.c_cc[VMIN]           =   0;           /*   在读取到   1   个字元前先停止   */     
          Opt.c_cc[VSWTC]         =   0;           /*   '\0'   */   
          Opt.c_cc[VSTART]       =   0;           /*   Ctrl-q   */   
          Opt.c_cc[VSTOP]         =   0;           /*   Ctrl-s   */   
          Opt.c_cc[VSUSP]         =   0;           /*   Ctrl-z   */   
          Opt.c_cc[VEOL]           =   0;           /*   '\0' CR  */   
          Opt.c_cc[VREPRINT]   =   0;           /*   Ctrl-r   */   
          Opt.c_cc[VDISCARD]   =   0;           /*   Ctrl-u   */   
          Opt.c_cc[VWERASE]     =   0;           /*   Ctrl-w   */   
          Opt.c_cc[VLNEXT]       =   0;           /*   Ctrl-v   */   
          Opt.c_cc[VEOL2]         =   0;           /*   '\0'   */   
#endif   
#endif
   ret=tcsetattr(fd,TCSANOW,&Opt);
   if(ret!=0){
    perror("tcsetattr fd");
    return 0;
   }
   tcflush(fd,TCIOFLUSH);
   return 1;
  }
}
}
int set_Parity(int fd,int databits,int stopbits,char parity)
{
struct termios options;
if(tcgetattr(fd,&options)!=0){
  perror("tcgetattr options");
  return 0;
}
options.c_cflag&=~CSIZE;
switch(databits){
  case 7: options.c_cflag|=CS7;
      break;
  case 8:  options.c_cflag|=CS8;
      break;
  default:
   fprintf(stderr,"Unsupported date size\nPlease input 7or8\n");
   return 0;
}
switch(stopbits){
  case 1: options.c_cflag&=~CSTOPB;
      break;
  case 2:  options.c_cflag|=CSTOPB;
      break;
  default:
   fprintf(stderr,"Unsupported stop bits\nPlease input 1or2\n");
   return 0;
}
switch(parity){
  case 'n':           
  case 'N': options.c_cflag&=~PARENB;
      options.c_iflag&=~INPCK;
      break;
  case 'o':           
  case 'O': options.c_cflag|=(PARODD|PARENB);
      options.c_iflag|=INPCK;
      break;
  case 'e':           
  case 'E': options.c_cflag&=~PARODD;
      options.c_cflag|=PARENB;
      options.c_iflag|=INPCK;
      break;
  default:
   fprintf(stderr,"Unsupported parity\nPlease input n o or e\n");
   return 0;
}
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME]=255;
options.c_cc[VMIN]=0;
if(tcsetattr(fd,TCSANOW,&options)!=0){
  perror("tcsetattr options");
  return 0;
}
tcflush(fd,TCIFLUSH);
return 1;
}
//串口初始化,包括波特率(115200~1800),数据位(7,8),停止位(1,2),校验位(n,o,e)的的设置
int uart_init(int fd,int speed,int databitss,int stopbits,char party)
{
// struct termios old_cfg;                  //保存原先串口配置
if(tcgetattr(fd,&old_cfg)!=0){
  perror("tcgetattr old_cfg");
  return 0;
}
if(set_speed(fd,speed)<0){
  printf("set_speed failed");
  return 0;
}
if(set_Parity(fd,databitss,stopbits,party)<0){
  printf("set_Parity failed");
  return 0;
}
return 1;
}




//uartwf.c               发送


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
#include "sys/ioctl.h"
extern struct termios old_cfg;
int main()
{
int len=0;
int fd,fd2,/*fd3,*/loops,rc;
char *buffer;
int size = 128;
buffer = (char *) malloc(size);  
char *dev="/dev/tq2440_serial1";
// char *dev="/dev/ttyS0";
if(fd=open(dev,O_RDWR|O_NOCTTY)<0){
  perror("Open Serial Port");
  return 0;
}
// ioctl(fd, TIOCEXCL, 0);
if(uart_init(fd,115200,8,1,'n')<0){
  printf("uart_init err\n");
  return 0;
}
/* if((fd2=open("/My_Documents/12345.c",O_RDWR,0777))<0){
  perror("open fd2");  
}      */
fd2=open("/My_Documents/sound.raw",O_RDWR,0777);
   if(fd2<0)
    perror("open fd2");  
/* fd3=open("/My_Documents/s123.raw",O_RDWR,0777);
   if(fd2<0)
    perror("open fd2");                   */
loops=6880;
while (loops > 0) {
  loops--;
  rc = read(fd2, buffer, size);   
  if (rc == 0) {      
  fprintf(stderr, "end of file on input\n");     
   break;   
   }
  else if (rc != size) {      
  fprintf(stderr,"short read: read %d bytes\n", rc);
  }   
/*  rc = write(fd3, buffer, size);   
  if (rc == 0) {      
  fprintf(stderr, "end of file on output\n");     
   break;   
   }
  else if (rc != size) {      
  fprintf(stderr,"short read: write %d bytes\n", rc);
  }                                             */
//  printf(buffer);
  rc=write(fd,buffer,size);
  if(rc<0){
   perror("uart write faild");
  }
  if (rc != size){
      fprintf(stderr, "short write: wrote %d bytes\n", rc);
  }            
  len+=size;
  //printf("Send total: %d\r\n", len);         
//  usleep(100000);
}
tcflush(fd,TCIFLUSH);
if(tcsetattr(fd,TCSANOW,&old_cfg)!=0){
  perror("tcsetattr options");
  return 0;
}
close(fd);
close(fd2);
// close(fd3);
free(buffer);
return 1;
}
 楼主| liehuo5210 发表于 2010-6-2 12:37:31 | 显示全部楼层
//uartrf.c       接收

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include<string.h>
#include<sys/wait.h>
//#include "sys/ioctl.h"
extern struct termios old_cfg;
int main()
{
int len, tlen;
int fd,fd2,loops,rc;
char *buffer;
// int size = 128;
int size = 238000;
buffer = (char *) malloc(size);  
char *dev="/dev/tq2440_serial1";
// char *dev="/dev/ttyS0";
if(fd=open(dev,O_RDWR|O_NOCTTY|O_SYNC)<0){
  perror("Open Serial Port");
  return 0;
}
if(uart_init(fd,115200,8,1,'n')<0){
  printf("uart_init err\n");
  return 0;
}
fd2=open("/My_Documents/s125.raw",O_CREAT|O_RDWR,0777);
   if(fd2<0)
    perror("open fd2");  
// ioctl(fd, TIOCEXCL, 0);

// loops=6880;
loops=100;

len = 0;
tlen = 204800;
while(1)
{
rc = read(fd, buffer, size);
  if(rc<=0){
   printf("uart read faild.\n");
   break;
  }
  printf("Received %d bytes, \n\r", rc);
  rc = write(fd2, buffer, rc);   

len+=rc;
if(len>=tlen)
  break;
}
printf("Received total: %d\r\n", len);
#if 0

while (loops > 0) {
  loops--;   
  rc=read(fd,buffer,size);
  if(rc<0){
   printf("uart read faild.\n");
  }
  
  printf("Received %d bytes, \n", rc);
  if (rc != size){
      fprintf(stderr, "short read: wrote %d bytes\n", rc);
/*  rc = write(fd2, buffer, size);   
  if (rc != size) {      
  fprintf(stderr,"short write: wrote %d bytes\n", rc);
  }   
  break;    */
  }
/*  rc = write(1, buffer, size);   
  if (rc != size) {      
  fprintf(stderr,"short write: wrote %d bytes\n", rc);
  }           */   
  rc = write(fd2, buffer, rc);   
  if (rc != size) {      
  fprintf(stderr,"short write: wrote %d bytes\n", rc);
  }   
//  usleep(100000);
}
#endif
tcflush(fd,TCIFLUSH);
if(tcsetattr(fd,TCSANOW,&old_cfg)!=0){
  perror("tcsetattr options");
  return 0;
}
close(fd);
close(fd2);
free(buffer);
return 1;
}
亚瑟王 发表于 2010-6-2 19:34:39 | 显示全部楼层
你用这个帖子中的串口测试程序测试吧:http://bbs.embedsky.net/viewthre ... &extra=page%3D2
 楼主| liehuo5210 发表于 2010-6-14 18:20:08 | 显示全部楼层
3# 亚瑟王

已解决:isatty(STDIN_FLENO)
调用就OK,否则就如上所述
十分感谢您,如果没有您的帮忙,将会是十分尴尬的局面,衷心的感谢您,谢谢
 楼主| liehuo5210 发表于 2010-6-14 19:16:12 | 显示全部楼层
3# 亚瑟王


完了,好使了一下,又完了,您的依然好使,我的又完了。。。
 楼主| liehuo5210 发表于 2010-6-15 11:09:04 | 显示全部楼层
5# liehuo5210
 楼主| liehuo5210 发表于 2010-6-15 11:13:24 | 显示全部楼层
5# liehuo5210

问题查出来了,已解决,原来if(fd=open(...)<0)    这错了。。且不报错
应为if((fd=open(...))<0)

再次对黄哥表示中心的感谢,感谢您百忙之中帮助我们这些新人
亚瑟王 发表于 2010-6-18 18:54:46 | 显示全部楼层
不好意思,没有看你的源码,不过就C中的运算符的级别来讲,<的级别是高于=号的,所以fd得到的不是设备句柄,而是open()<0这个比较式的结论,即0或1。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2024-9-19 15:48 , Processed in 1.022501 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

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