Linux串口通信编程.docx
- 文档编号:29495910
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:14
- 大小:19.46KB
Linux串口通信编程.docx
《Linux串口通信编程.docx》由会员分享,可在线阅读,更多相关《Linux串口通信编程.docx(14页珍藏版)》请在冰豆网上搜索。
Linux串口通信编程
Linux串口通信编程 2010-01-0811:
21:
03
分类:
C/C++
串口是计算机上一种非常通用设备通信的协议,常用PC机上包含的是RS232规格的串口,具有连接线少,通讯简单,得到广泛的使用。
Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口设备。
在linux系统下面,每一个串口设备都有设备文件与其关联,设备文件位于系统的/dev目录下面。
如linux下的/ttyS0,/ttyS1分别表示的是串口1和串口2。
在串口编程中,比较重要的是串口的设置,我们要设置的部分包括:
波特率,数据位,停止位,奇偶校验位;要注意的是,每台机器的串口默认设置可能是不同的,如果你没设置这些,仅仅按照默认设置进行发送数据,很可能出现n多异想不到而又查不出来的情况。
1)设置波特率
#include
#include
int cfsetispeed(struct termios *termios_p, speed_tspeed);
int cfsetospeed(struct termios *termios_p, speed_tspeed);
2)设置属性:
奇偶校验位、数据位、停止位。
主要设置
#define NCCS19
struct termios {
tcflag_tc_iflag; /*inputmodeflags*/
tcflag_tc_oflag; /*outputmodeflags*/
tcflag_tc_cflag; /*controlmodeflags*/
tcflag_tc_lflag; /*localmodeflags*/
cc_tc_line; /*linediscipline*/
cc_tc_cc[NCCS]; /*controlcharacters*/
};
有相应的函数供获取和设置属性:
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, struct termios *termios_p);
3)打开、关闭和读写串口。
串口作为设备文件,可以直接用文件描述符来进行操作。
#include
#include
#include
int open(const char *pathname, int flags);
#include
int close(int fd);
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
网上的一个例子:
/*串口设备无论是在工控领域,还是在嵌入式设备领域,应用都非常广泛。
而串口编程也就显得必不可少。
偶然的一次机会,需要使用串口,而且操作系统还要求是Linux,因此,趁着这次机会,综合别人的代码,
进行了一次整理和封装。
具体的封装格式为C代码,这样做是为了很好的移植性,使它可以在C和C++环境下,
都可以编译和使用。
代码的头文件如下:
*/
///////////////////////////////////////////////////////////////////////////////
//filename:
stty.h
#ifndef __STTY_H__
#define __STTY_H__
//包含头文件
#include
#include
#include
#include
#include
#include
#include
#include
#include
//
//串口设备信息结构
typedef struct tty_info_t
{
int fd; //串口设备ID
pthread_mutex_t mt; //线程同步互斥对象
char name[24]; //串口设备名称,例:
"/dev/ttyS0"
struct termiosntm; //新的串口设备选项
struct termiosotm; //旧的串口设备选项
} TTY_INFO;
//
//串口操作函数
TTY_INFO *readyTTY(int id);
int setTTYSpeed(TTY_INFO *ptty, int speed);
int setTTYParity(TTY_INFO *ptty,int databits,int parity,int stopbits);
int cleanTTY(TTY_INFO *ptty);
int sendnTTY(TTY_INFO *ptty,char *pbuf,int size);
int recvnTTY(TTY_INFO *ptty,char *pbuf,int size);
int lockTTY(TTY_INFO *ptty);
int unlockTTY(TTY_INFO *ptty);
#endif
/*从头文件中的函数定义不难看出,函数的功能,使用过程如下:
(1)打开串口设备,调用函数setTTYSpeed();
(2)设置串口读写的波特率,调用函数setTTYSpeed();
(3)设置串口的属性,包括停止位、校验位、数据位等,调用函数setTTYParity();
(4)向串口写入数据,调用函数sendnTTY();
(5)从串口读出数据,调用函数recvnTTY();
(6)操作完成后,需要调用函数cleanTTY()来释放申请的串口信息接口;
其中,lockTTY()和unlockTTY()是为了能够在多线程中使用。
在读写操作的前后,需要锁定和释放串口资源。
具体的使用方法,在代码实现的原文件中,main()函数中进行了演示。
下面就是源代码文件:
*/
////////////////////////////////////////////////////////////////////////////////
//stty.c
#include
#include
#include "stty.h"
///////////////////////////////////////////////////////////////////////////////
//初始化串口设备并进行原有设置的保存
TTY_INFO *readyTTY(int id)
{
TTY_INFO *ptty;
ptty = (TTY_INFO *)malloc(sizeof(TTY_INFO));
if(ptty == NULL)
return NULL;
memset(ptty,0,sizeof(TTY_INFO));
pthread_mutex_init(&ptty->mt,NULL);
sprintf(ptty->name,"/dev/ttyS%d",id);
//
//打开并且设置串口
ptty->fd = open(ptty->name, O_RDWR | O_NOCTTY |O_NDELAY);
if (ptty->fd <0)
{
free(ptty);
return NULL;
}
//
//取得并且保存原来的设置
tcgetattr(ptty->fd,&ptty->otm);
return ptty;
}
///////////////////////////////////////////////////////////////////////////////
//清理串口设备资源
int cleanTTY(TTY_INFO *ptty)
{
//
//关闭打开的串口设备
if(ptty->fd>0)
{
tcsetattr(ptty->fd,TCSANOW,&ptty->otm);
close(ptty->fd);
ptty->fd = -1;
free(ptty);
ptty = NULL;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//设置串口通信速率
//ptty参数类型(TTY_INFO*),已经初始化的串口设备信息结构指针
//speed参数类型(int),用来设置串口的波特率
//return返回值类型(int),函数执行成功返回零值,否则返回大于零的值
///////////////////////////////////////////////////////////////////////////////
int setTTYSpeed(TTY_INFO *ptty, int speed)
{
int i;
//
//进行新的串口设置,数据位为8位
bzero(&ptty->ntm, sizeof(ptty->ntm));
tcgetattr(ptty->fd,&ptty->ntm);
ptty->ntm.c_cflag = /*CS8|*/ CLOCAL | CREAD;
switch(speed)
{
case 300:
ptty->ntm.c_cflag |= B300;
break;
case 1200:
ptty->ntm.c_cflag |= B1200;
break;
case 2400:
ptty->ntm.c_cflag |= B2400;
break;
case 4800:
ptty->ntm.c_cflag |= B4800;
break;
case 9600:
ptty->ntm.c_cflag |= B9600;
break;
case 19200:
ptty->ntm.c_cflag |= B19200;
break;
case 38400:
ptty->ntm.c_cflag |= B38400;
break;
case 115200:
ptty->ntm.c_cflag |= B115200;
break;
}
ptty->ntm.c_iflag = IGNPAR;
ptty->ntm.c_oflag = 0;
//
//
tcflush(ptty->fd, TCIFLUSH);
tcsetattr(ptty->fd,TCSANOW,&ptty->ntm);
//
//
return 0;
}
//设置串口数据位,停止位和效验位
//ptty参数类型(TTY_INFO*),已经初始化的串口设备信息结构指针
//databits参数类型(int),数据位,取值为7或者8
//stopbits参数类型(int),停止位,取值为1或者2
//parity参数类型(int),效验类型取值为N,E,O,,S
//return返回值类型(int),函数执行成功返回零值,否则返回大于零的值
///////////////////////////////////////////////////////////////////////////////
int setTTYParity(TTY_INFO *ptty,int databits,int parity,int stopbits)
{
//
//取得串口设置
if( tcgetattr(ptty->fd,&ptty->ntm) !
= 0)
{
printf("SetupSerial[%s]\n",ptty->name);
return 1;
}
bzero(&ptty->ntm, sizeof(ptty->ntm));
ptty->ntm.c_cflag = CS8 | CLOCAL | CREAD;
ptty->ntm.c_iflag = IGNPAR;
ptty->ntm.c_oflag = 0;
//
//设置串口的各种参数
ptty->ntm.c_cflag &= ~CSIZE;
switch (databits)
{ //设置数据位数
case 7:
ptty->ntm.c_cflag |= CS7;
break;
case 8:
ptty->ntm.c_cflag |= CS8;
break;
default:
printf("Unsupporteddatasize\n");
return 5;
}
//
//
switch (parity)
{ //设置奇偶校验位数
case n:
case N:
ptty->ntm.c_cflag &= ~PARENB; /*Clearparityenable*/
ptty->ntm.c_iflag &= ~INPCK; /*Enableparitychecking*/
break;
case o:
case O:
ptty->ntm.c_cflag |= (PARODD|PARENB); /*设置为奇效验*/
ptty->ntm.c_iflag |= INPCK; /*Disnableparitychecking*/
break;
case e:
case E:
ptty->ntm.c_cflag |= PARENB; /*Enableparity*/
ptty->ntm.c_cflag &= ~PARODD; /*转换为偶效验*/
ptty->ntm.c_iflag |= INPCK; /*Disnableparitychecking*/
break;
case S:
case s:
/*asnoparity*/
ptty->ntm.c_cflag &= ~PARENB;
ptty->ntm.c_cflag &= ~CSTOPB;
break;
default:
printf("Unsupportedparity\n");
return 2;
}
//
//设置停止位
switch (stopbits)
{
case 1:
ptty->ntm.c_cflag &= ~CSTOPB;
break;
case 2:
ptty->ntm.c_cflag |= CSTOPB;
break;
default:
printf("Unsupportedstopbits\n");
return 3;
}
//
//
ptty->ntm.c_lflag = 0;
ptty->ntm.c_cc[VTIME] = 0; //inter-charactertimerunused
ptty->ntm.c_cc[VMIN] = 1; //blockingreaduntil1charsreceived
tcflush(ptty->fd, TCIFLUSH);
if (tcsetattr(ptty->fd,TCSANOW,&ptty->ntm) !
= 0)
{
printf("SetupSerial\n");
return 4;
}
return 0;
}
int recvnTTY(TTY_INFO *ptty,char *pbuf,int size)
{
int ret,left,bytes;
left = size;
while(left>0)
{
ret = 0;
bytes = 0;
pthread_mutex_lock(&ptty->mt);
ioctl(ptty->fd, FIONREAD, &bytes);
if(bytes>0)
{
ret = read(ptty->fd,pbuf,left);
}
pthread_mutex_unlock(&ptty->mt);
if(ret >0)
{
left -= ret;
pbuf += ret;
}
usleep(100);
}
return size - left;
}
int sendnTTY(TTY_INFO *ptty,char *pbuf,int size)
{
int ret,nleft;
char *ptmp;
ret = 0;
nleft = size;
ptmp = pbuf;
while(nleft>0)
{
pthread_mutex_lock(&ptty->mt);
ret = write(ptty->fd,ptmp,nleft);
pthread_mutex_unlock(&ptty->mt);
if(ret >0)
{
nleft -= ret;
ptmp += ret;
}
//usleep(100);
}
return size - nleft;
}
int lockTTY(TTY_INFO *ptty)
{
if(ptty->fd < 0)
{
return 1;
}
return flock(ptty->fd,LOCK_EX);
}
int unlockTTY(TTY_INFO *ptty)
{
if(ptty->fd < 0)
{
return 1;
}
return flock(ptty->fd,LOCK_UN);
}
#ifdef LEAF_TTY_TEST
///////////////////////////////////////////////////////////////////////////////
//接口测试
int main(int argc,char **argv)
{
TTY_INFO *ptty;
int nbyte,idx;
unsigned char cc[16];
ptty = readyTTY(0);
if(ptty == NULL)
{
printf("readyTTY(0)error\n");
return 1;
}
//
//
lockTTY(ptty);
if(setTTYSpeed(ptty,9600)>0)
{
printf("setTTYSpeed()error\n");
return -1;
}
if(setTTYParity(ptty,8,N,1)>0)
{
printf("setTTYParity()error\n");
return -1;
}
//
idx = 0;
while
(1)
{
cc[0] = 0xFA;
sendnTTY(ptty,&c
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 串口 通信 编程