Linux下用C实现串口读写


 http://hi.baidu.com/weiweisuo1986/item/b33200134ceaac6871d5e81d    

    之前要做一个和串口相关的项目,才认真研究了下串口,首先就是要实现串口和PC机的通信。

         串口的驱动一般不需要我们写,都是很成熟的驱动,要知道的一点就是你开发板串口的名称,比如ttySAC0,等。所以主要的工作就是编程序,实现串口的收发,这当然也好理解,就把串口当成文件,对其进行读写就可以了。

         首先说明下我的编译环境,Linux使用的版本是2.6.30.4,交叉编译器使用的是EABI4.3.3。下面是程序代码,只有一个文件:serialport.c!

/**************serialport**************************/

/*************Designed by Suo*********************/

#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>

   

//serial port set function

void setTermios(struct termios *pNewtio, unsigned short uBaudRate)

{

      bzero(pNewtio,sizeof(struct termios));

      pNewtio->c_cflag = uBaudRate|CS8|CREAD|CLOCAL;

      pNewtio->c_iflag = IGNPAR;

      pNewtio->c_oflag = 0;

      pNewtio->c_lflag = 0;

      pNewtio->c_cc[VINTR] = 0;

      pNewtio->c_cc[VQUIT] = 0;

      pNewtio->c_cc[VERASE] = 0;

      pNewtio->c_cc[VKILL] = 0;

      pNewtio->c_cc[VEOF] = 4;

      pNewtio->c_cc[VTIME] = 5;

      pNewtio->c_cc[VMIN] = 0;

      pNewtio->c_cc[VSWTC] = 0;

      pNewtio->c_cc[VSTART] = 0;

      pNewtio->c_cc[VSTOP] = 0;

      pNewtio->c_cc[VSUSP] = 0;

      pNewtio->c_cc[VEOL] = 0;

      pNewtio->c_cc[VREPRINT] = 0;

      pNewtio->c_cc[VDISCARD] = 0;

      pNewtio->c_cc[VWERASE] = 0;

      pNewtio->c_cc[VLNEXT] = 0;

      pNewtio->c_cc[VEOL2] = 0;

}

int main(int argc,char **argv)

{

      int fd;

      int nCount,nTotal;

      int i,j,m;

      int ReadByte = 0;

      struct termios oldtio,newtio;

      char *dev = "/dev/tq2440_serial1";

  

      if((argc!=3)||(sscanf(argv[1],"%d",&nTotal)!=1))

      {

             printf("Usage:COMSend count datat!\n");

             return -1;

      }

  

      if((fd=open(dev,O_RDWR|O_NOCTTY|O_NDELAY))<0) //open serial COM2

      {

             printf("Can't open serial port!\n");

             return -1;

      }

      tcgetattr(fd,&oldtio);

      setTermios(&newtio,B9600);

      tcflush(fd,TCIFLUSH);

      tcsetattr(fd,TCSANOW,&newtio);

       

      //Send data

      for(i=0;i<nTotal;i++)

      {

             nCount = write(fd,argv[2],strlen(argv[2]));

             printf("send data OK!count=%d\n",nCount);

             sleep(1);

      }

     

      //receive data

      for(j=0;j<20;j++)

      {

             ReadByte = read(fd,Buffer,512);

             if(ReadByte>0)

             {

                    printf("readlength=%d\n",ReadByte);

                    Buffer[ReadByte]='\0';

                    printf("%s\n",Buffer);

                    sleep(3);

             }

             else printf("Read data failure times=%d\n",j);

      }     

      printf("Receive data finished!\n");

      tcsetattr(fd,TCSANOW,&oldtio);

      close(fd);

      return 0;

}

         此程序实现的功能是:运行程序时,输入要发送的次数及待发送数据,就向串口2发送数据,如果有数据过了,程序会把接收到的数据显示在终端上。

        相应的Makefile是:

CROSS=arm-linux-

all:shuserial

shuserial:shuserial.c

      $(CROSS)gcc -o shuserial shuserial.c

      $(CROSS)strip shuserial

clean:

      @rm -vf shuserial*.o*~

make出可执行文件serialport后,就可以在开发板上调试了。调试方法:1、把程序用U盘拷到开发板中(当然前提是已启动Linux系统),我的开发板是Linux2.6.30内核+Qtopia2.2.0。2、连接串口,用串口线把开发板串口2和电脑相连,PC打开超级终端,设置串口COM1属性为9600波特率,8N1,然后等待接收。3、打开开发板系统中的终端Terminal,输入./serialport 10 abcdefghijk ,即可运行此程序,程序向PC串口发送发送10次“abcdefghijk”,发送完成后,如果你向超级终端输入了数据,程序会把数据显示到Terminal上。

           完成了,程序就是这么简单,只是实现了简单的收发功能。

         以后用Qt实现此程序……





成功的测试程序:

ReadUart.cpp


#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>


#define TRUE 1


//初始化串口


void setTermios(struct termios * pNewtio, int uBaudRate)
{
bzero(pNewtio, sizeof(struct termios));
//8N1
pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = 0;
pNewtio->c_lflag = 0; //non ICANON


pNewtio->c_cc[VINTR] = 0;
pNewtio->c_cc[VQUIT] = 0;
pNewtio->c_cc[VERASE] = 0;
pNewtio->c_cc[VKILL] = 0;
pNewtio->c_cc[VEOF] = 4;
pNewtio->c_cc[VTIME] = 5;
pNewtio->c_cc[VMIN] = 0;
pNewtio->c_cc[VSWTC] = 0;
pNewtio->c_cc[VSTART] = 0;
pNewtio->c_cc[VSTOP] = 0;
pNewtio->c_cc[VSUSP] = 0;
pNewtio->c_cc[VEOL] = 0;
pNewtio->c_cc[VREPRINT] = 0;
pNewtio->c_cc[VDISCARD] = 0;
pNewtio->c_cc[VWERASE] = 0;
pNewtio->c_cc[VLNEXT] = 0;
pNewtio->c_cc[VEOL2] = 0;
}






#define BUFSIZE 512


int main(int argc, char **argv)
{
int fd;
int nread;
int Rlength = BUFSIZE;
int Length = 0;
char buff[BUFSIZE] = {0};
char cMsg[BUFSIZE] = {0};
char *pch = buff;
int i = 0;
struct termios oldtio, newtio;
struct timeval tv;
char *dev =(char *)"/dev/ttyO1";
//char *dev =(char *)"/dev/ttyS1";
fd_set rfds;
if ((fd = open(dev, O_RDWR | O_NOCTTY))<0)
{
printf("err: can't open serial port!\n");
return -1;
}
tcgetattr(fd, &oldtio);
//setTermios(&newtio, B9600);
setTermios(&newtio, B115200);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);


tv.tv_sec=3;
tv.tv_usec=0;
while (TRUE)
{
//printf("fd is <%d> wait...\n", fd);
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
if (select(1+fd, &rfds, NULL, NULL, &tv)>0)
{
//printf("wait.......\n");
if (FD_ISSET(fd, &rfds))
{
//printf("FD_ISSET...\n");
//nread=read(fd, buff, BUFSIZE);
nread=read(fd, pch, BUFSIZE-Length);
//buff[nread]='\0';

for(i=Length;i<nread+Length;i++)
{
//printf("buff[%d] = <0x%x><%c>.\n", i,buff[i],buff[i]);
printf("%c\n", buff[i]);
}
//printf("\n");
//printf("nread = %d,Length = %d, %s\n",nread,Length, buff);
Length += nread;
if(Length >= BUFSIZE)
{
printf("######Length<%d> is too long.\n", Length);
return -1;
}   
//printf("nread is %d...\n", nread);      
pch += nread;  
}
}
else
{
//memcpy(cMsg,buff,Length);
printf("Uart msg is :\n");
printf("%s\n", buff);
//printf("\n");
memset(buff, 0, BUFSIZE);
pch = buff;
Length = 0;

tv.tv_sec=3;
tv.tv_usec=0;

//sleep(1);
}
}
tcsetattr(fd, TCSANOW, &oldtio);
close(fd);
}


WriteUart.cpp


#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>


//serial port set function
void setTermios(struct termios *pNewtio, unsigned short uBaudRate)
{
bzero(pNewtio,sizeof(struct termios));
pNewtio->c_cflag = uBaudRate|CS8|CREAD|CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = 0;
pNewtio->c_lflag = 0;
pNewtio->c_cc[VINTR] = 0;
pNewtio->c_cc[VQUIT] = 0;
pNewtio->c_cc[VERASE] = 0;
pNewtio->c_cc[VKILL] = 0;
pNewtio->c_cc[VEOF] = 4;
pNewtio->c_cc[VTIME] = 5;
pNewtio->c_cc[VMIN] = 0;
pNewtio->c_cc[VSWTC] = 0;
pNewtio->c_cc[VSTART] = 0;
pNewtio->c_cc[VSTOP] = 0;
pNewtio->c_cc[VSUSP] = 0;
pNewtio->c_cc[VEOL] = 0;
pNewtio->c_cc[VREPRINT] = 0;
pNewtio->c_cc[VDISCARD] = 0;
pNewtio->c_cc[VWERASE] = 0;
pNewtio->c_cc[VLNEXT] = 0;
pNewtio->c_cc[VEOL2] = 0;
}
int main(int argc,char **argv)
{
int fd;
int nCount = 0, ulen = 0, nTotal = 0;
int i,j,m;
int ReadByte = 0;


char Buffer[512];
struct termios oldtio,newtio;
char *dev = (char*)"/dev/ttyO1";


if((argc!=3)||(sscanf(argv[1],"%d",&nTotal)!=1))
{
printf("Usage:COMSend count datat! ");
return -1;
}


if((fd=open(dev,O_RDWR|O_NOCTTY|O_NDELAY))<0) //open serial COM2
{
printf("Can't open serial port! ");
return -1;
}
tcgetattr(fd,&oldtio);
setTermios(&newtio,B115200);  // B9600
//setTermios(&newtio,B57600);  
tcflush(fd,TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);


//Send data
for(i=0;i<nTotal;i++)
{
nCount = write(fd,argv[2],strlen(argv[2]));
        ulen = write(fd, "\r\n",2);
printf("send data OK!count=%d, nTotal=%d, ulen=%d.\n",nCount, nTotal, ulen);
//tcflush(fd,TCIFLUSH);
//tcsetattr(fd,TCSANOW,&newtio);
usleep(500000);
}
    
/*
//receive data
for(j=0;j<20;j++)
{
ReadByte = read(fd,Buffer,512);
if(ReadByte>0)
{
printf("readlength=%d ",ReadByte);
Buffer[ReadByte]='\0';
printf("%s ",Buffer);
sleep(3);
}
else printf("Read data failure times=%d ",j);
}     
printf("Receive data finished! ");
tcsetattr(fd,TCSANOW,&oldtio);
*/
close(fd);
return 0;
}





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值