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