1. 程式人生 > >Linux下用C實現串列埠讀寫

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;
}