转载自:http://blog.sina.com.cn/s/blog_640531380100wiv8.html
串口简介
串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是 RS-232-C 接口(又称 EIARS-232-C)它是在 1970 年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"该标准规定采用一个 25 个脚的 DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于 4% 的情况下,传输电缆长度应为50 英尺。
Linux 操作系统从一开始就对串行口提供了很好的支持
计算机串口的引脚说明
序号 信号名称 符号 流向
2 发送数据 TXD DTE→DCE DTE发送串行数据
3 接收数据 RXD DTE←DCE DTE 接收串行数据
4 请求发送 RTS DTE→DCE DTE 请求 DCE 将线路切换到发送方式
5 允许发送 CTS DTE←DCE DCE 告诉 DTE 线路已接通可以发送数据
6 数据设备准备好 DSR DTE←DCE DCE 准备好
7 信号地
8 载波检测 DCD DTE←DCE 表示 DCE 接收到远程载波
20 数据终端准备好 DTR DTE→DCE DTE 准备好
22 振铃指示 RI DTE←DCE 表示 DCE 与线路接通,出现振铃
串口操作
串口操作需要的头文件
#include
#include
#include
#include
#include
#include
#include
#include
打开串口
在 Linux 下串口文件是位于 /dev 下的
串口一 为 /dev/ttyS0
串口二 为 /dev/ttyS1
打开串口是通过使用标准的文件打开函数操作:
int fd;
fd = open( "/dev/ttyS0", O_RDWR);
if (-1 == fd){
perror(" 提示错误!");
}
设置串口
最基本的设置串口包括波特率设置,效验位和停止位设置。
串口的设置主要是设置 struct termios 结构体的各成员值。
struct termio
{
};
设置这个结构体很复杂,我这里就只说说常见的一些设置:
波特率设置
下面是修改波特率的代码:
struct termios Opt;
tcgetattr(fd, &Opt);
cfsetispeed(&Opt,B19200);
cfsetospeed(&Opt,B19200);
tcsetattr(fd,TCANOW,&Opt);
设置波特率的例子函数:
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200,B300,
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,38400,
void set_speed(int fd, int speed){
{
}
}
}
效验位和停止位的设置:
无效验 8位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS8;
奇效验(Odd) 7位 Option.c_cflag |= ~PARENB;
Option.c_cflag &= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
偶效验(Even) 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag |= ~PARODD;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= ~CSIZE;
Option.c_cflag |= ~CS7;
Space效验 7位 Option.c_cflag &= ~PARENB;
Option.c_cflag &= ~CSTOPB;
Option.c_cflag &= &~CSIZE;
Option.c_cflag |= CS8;
设置效验的函数:
int set_Parity(int fd, int databits, int stopbits, intparity)
{
}
需要注意的是:
如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(RawMode)方式来通讯,设置方式如下:
options.c_lflag &= ~(ICANON | ECHO | ECHOE |ISIG);
options.c_oflag &=~OPOST;
读写串口
设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。
发送数据
char buffer[1024];
int
int
nByte = write(fd, buffer ,Length)
读取串口数据
使用文件操作read函数读取,如果设置为原始模式(RawMode)传输数据,那么read函数返回的字符数是实际串口收到的字符数。
可以使用操作文件的函数来实现异步读取,如fcntl,或者select等来操作。
char buff[1024];
int
int readByte = read(fd,buff,Len);
关闭串口
关闭串口就是关闭文件。
close(fd);
例子
下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件
#define FALSE -1
#define TRUE
int OpenDev(char *Dev)
{
}
int main(int argc, char **argv)
{
}
1、虚拟机下使用串口的方法
2、消除Linux串口收发的一些规则
Linux 串口收发有许多模式,如:
(1) 接收返回模式: 如果串口没有接收到数据,read()函数不返回。
(2) 数据接收\n才返回接收的数据,否则read()函数返回0
(3) 特殊字符解析问题,部分特殊字符接收/发送时,会被屏蔽或者转义。如发送0x0A 接收变为0x0A 0x0A,0x0D被屏蔽等。
(4) 接收反馈:如串口接收到数据,立即将该数据发送出去。
(上面是我遇到的一些问题,可能表述不很清楚,呵呵。如果用于收发txt文件,一般不大注意。)
3、解决问题的方法是,消除这些默认规则,关键是struct termios的参数影响。
struct termios {
};
由于研究不深,如果要消除所有上面的规则,我是如下处理的
struct termios options;
串口打开方式:
open ("dev/ttyS0" , O_RDWR|O_NOCTTY| O_NDELAY );
消除收发模式规则:
options.c_lflag
options.c_oflag
options.c_iflag
消除字符屏蔽规则:
options.c_cc[VINTR]
options.c_cc[VQUIT]
options.c_cc[VERASE]
options.c_cc[VKILL]
options.c_cc[VEOF]
options.c_cc[VTIME]
options.c_cc[VMIN]
options.c_cc[VSWTC]
options.c_cc[VSTART]
options.c_cc[VSTOP]
options.c_cc[VSUSP]
options.c_cc[VEOL]
options.c_cc[VREPRINT] =0;
options.c_cc[VDISCARD] =0;
options.c_cc[VWERASE] =0;
options.c_cc[VLNEXT]
options.c_cc[VEOL2]
以上设置,在其它参数串口设置前执行,如果你需要保留部分参数,请参阅http://blog.chinaunix.net/article.php?articleId=15964&blogId=60
在RedHat Feroda 4 下编译通过
= = = = = = = = = = = 非阻塞read= = = = = = = = = ==
Q:在调用串口read(fd,
A:使用非阻塞方式select函数(I/O多工机制)或者open的时候加O_NONBLOCK参数。
int select(int n,fd_set * readfds,fd_set *writefds,fd_set * exceptfds,struct timeval *timeout);关于这个函数的使用我会在下篇blog中整理。
= = = = = = = = = = = 串口收发源码= = = = = = = = = ==
= = = = = = receive.c= = = = = =
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define TRUE 1
//初始化串口选项:
void setTermios(struct termios * pNewtio, intuBaudRate)
{
}
#define BUFSIZE 512
int main(int argc, char **argv)
{
}
= = = = = send.c= = = = = =
#include
#include
#include
#include
#include
#include
#include
#include
#include
//初始化串口选项:
void setTermios(struct termios * pNewtio, int uBaudRate)
{
}
int main(int argc, char **argv)
{
}
CC = /usr/local/arm/2.95.3/bin/arm-linux-gcc
all:receive send
receive: rece