您的位置:首页 > 运维架构 > Linux

linux下串口控制 分类: arm-linux-Ubuntu 2013-08-12 16:02 394人阅读 评论(0) 收藏

2013-08-12 16:02 721 查看
/* 本程序符合GPL条约

* Beneboy 2003-5-16

*/

#include <stdio.h> // printf

#include <fcntl.h> // open

#include <string.h> // bzero

#include <stdlib.h> // exit

#include <sys/times.h> // times

#include <sys/types.h> // pid_t

#include <termios.h> //termios, tcgetattr(), tcsetattr()

#include <unistd.h>

#include <sys/ioctl.h> // ioctl

#include "MyCom.h"

#define TTY_DEV "/dev/ttyS" //端口路径

//接收超时

#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)

#define TIMEOUT_USEC 0

/*******************************************

* 获得端口名称

********************************************/

char *get_ptty(pportinfo_t pportinfo)

{

char *ptty;

switch(pportinfo->tty){

case '0':{

ptty = TTY_DEV"0";

}break;

case '1':{

ptty = TTY_DEV"1";

}break;

case '2':{

ptty = TTY_DEV"2";

}break;

}

return(ptty);

}

/*******************************************

* 波特率转化转换函数

********************************************/

int convbaud(unsigned long int baudrate)

{

switch(baudrate){

case 2400:

return B2400;

case 4800:

return B4800;

case 9600:

return B9600;

case 19200:

return B19200;

case 38400:

return B38400;

case 57600:

return B57600;

case 115200:

return B115200;

default:

return B9600;

}

}

/*******************************************

* Setup comm attr

* fdcom: 串口文件描述符, pportinfo: 待设置的端口信息s

*

********************************************/

int PortSet(int fdcom, const pportinfo_t pportinfo)

{

struct termios termios_old, termios_new;

int baudrate, tmp;

char databit, stopbit, parity, fctl;

bzero(&termios_old, sizeof(termios_old));

bzero(&termios_new, sizeof(termios_new));

cfmakeraw(&termios_new);

tcgetattr(fdcom, &termios_old); //get the serial port attributions

/*------------设置端口属性----------------*/

//baudrates

baudrate = convbaud(pportinfo -> baudrate);

cfsetispeed(&termios_new, baudrate); //填入串口输入端波特率

cfsetospeed(&termios_new, baudrate); //填入串口输出端波特率

termios_new.c_cflag |= CLOCAL; //控制模式, 保证程序不会成为端口的占有者

termios_new.c_cflag |= CREAD; //控制模式, 使能端口读取输入的数据

// 控制模式, flow control

fctl = pportinfo-> fctl;

switch(fctl){

case '0':{

termios_new.c_cflag &= ~CRTSCTS; //no flow control

}break;

case '1':{

termios_new.c_cflag |= CRTSCTS; //hardware flow control

}break;

case '2':{

termios_new.c_iflag |= IXON | IXOFF |IXANY; //software flow control

}break;

}

//控制模式, data bits

termios_new.c_cflag &= ~CSIZE; //控制模式, 屏蔽字符大小位

databit = pportinfo -> databit;

switch(databit){

case '5':

termios_new.c_cflag |= CS5;

case '6':

termios_new.c_cflag |= CS6;

case '7':

termios_new.c_cflag |= CS7;

default:

termios_new.c_cflag |= CS8;

}

//控制模式 parity check

parity = pportinfo -> parity;

switch(parity){

case '0':{

termios_new.c_cflag &= ~PARENB; //no parity check

}break;

case '1':{

termios_new.c_cflag |= PARENB; //odd check

termios_new.c_cflag &= ~PARODD;

}break;

case '2':{

termios_new.c_cflag |= PARENB; //even check

termios_new.c_cflag |= PARODD;

}break;

}

//控制模式, stop bits

stopbit = pportinfo -> stopbit;

if(stopbit == '2'){

termios_new.c_cflag |= CSTOPB; //2 stop bits

}

else{

termios_new.c_cflag &= ~CSTOPB; //1 stop bits

}

//other attributions default

termios_new.c_oflag &= ~OPOST; //输出模式, 原始数据输出

termios_new.c_cc[VMIN] = 1; //控制字符, 所要读取字符的最小数量

termios_new.c_cc[VTIME] = 1; //控制字符, 读取第一个字符的等待时间, unit: (1/10)second

tcflush(fdcom, TCIFLUSH); //溢出的数据可以接收,但不读

tmp = tcsetattr(fdcom, TCSANOW, &termios_new); //设置新属性, TCSANOW: 所由改变立即生效

tcgetattr(fdcom, &termios_old);

return(tmp);

}

/*******************************************

* Open serial port

* tty: 端口号 ttyS0, ttyS1, ....

* 返回值为串口文件描述符

********************************************/

int PortOpen(pportinfo_t pportinfo)

{

int fdcom; //串口文件描述符

char *ptty;

ptty = get_ptty(pportinfo);

//fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);

fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK);

return (fdcom);

}

/*******************************************

* Close serial port

********************************************/

void PortClose(int fdcom)

{

close(fdcom);

}

/********************************************

* send data

* fdcom: 串口描述符, data: 待发送数据, datalen: 数据长度

* 返回实际发送长度

*********************************************/

int PortSend(int fdcom, char *data, int datalen)

{

int len = 0;

len = write(fdcom, data, datalen); //实际写入的长度

if(len == datalen){

return (len);

}

else{

tcflush(fdcom, TCOFLUSH);

return -1;

}

}

/*******************************************

* receive data

* 返回实际读入的字节数

*

********************************************/

int PortRecv(int fdcom, char *data, int datalen, int baudrate)

{

int readlen, fs_sel;

fd_set fs_read;

struct timeval tv_timeout;

FD_ZERO(&fs_read);

FD_SET(fdcom, &fs_read);

tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate);

tv_timeout.tv_usec = TIMEOUT_USEC;

fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);

if(fs_sel){

readlen = read(fdcom, data, datalen);

return(readlen);

}

else{

return(-1);

}

return (readlen);

}

//*************************Test*********************************

int main(int argc, char *argv[])

{

int fdcom, i, SendLen, RecvLen;

struct termios termios_cur;

char RecvBuf[256];

char writeBuf[256];

portinfo_t portinfo ={

'0', // print prompt after receiving

9600, // baudrate: 9600

'8', // databit: 8

'0', // debug: off

'0', // echo: off

'2', // flow control: software

'0', // default tty: COM1

'0', // parity: none

'1', // stopbit: 1

0 // reserved

};

if(argc != 2){

printf("Usage: <type 0 -- send 1 -- receive>\n");

printf(" eg:");

printf(" MyPort 0");

exit(-1);

}

fdcom = PortOpen(&portinfo);

if(fdcom<0){

printf("Error: open serial port error.\n");

exit(1);

}

PortSet(fdcom, &portinfo);

while(1)

if(atoi(argv[1]) == 0)

{

//send data

//for(i=0; i<1000; i++)

{

//fgets(writeBuf,256,stdin);

scanf("%s",writeBuf);

SendLen = PortSend(fdcom, writeBuf, strlen(writeBuf));

if(SendLen>0)

{

//printf("send data %s", writeBuf);

}

else

{

printf("Error: send failed.\n");

}

if(strncmp(writeBuf,"exit",4)==0)

break;

sleep(1);

}

//PortClose(fdcom);

}

else

{

//for(;;)

{

RecvLen = PortRecv(fdcom, RecvBuf, 256, portinfo.baudrate);

if(RecvLen>0)

{

/*for(i=0; i<RecvLen; i++)

{

printf("Receive data No %d is %x.\n", i, RecvBuf[i]);

}//*/

RecvBuf[RecvLen] = '\0';

printf("read data %s\n",RecvBuf);

if(strncmp(RecvBuf,"exit",4)==0)

break;

}

else

{

//printf("Error: receive error.\n");

}

sleep(1);

}

}

PortClose(fdcom);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐