1..用户常见的数据通信的基本方式有两种:
并行通信;
串行通信;
串行通信是计算机常用的接口,如:RS-232-C接口。该标准规定采用一个DB25芯引脚连接器或DB9芯引脚连接器。
芯片内部常具有UART控制器,其可工作于Interrupt(中断模式)或DMA(直接内存访问)模式。
2. UART的操作主要包括以下几个部分:
数据发送;
数据接收;
产生中断;
产生波特率;
Loopback模式;
红外模式;
自动流控模式
串口参数的配置主要包括:波特率、数据位、停止位、流控协议。
3. linux中的串口设备文件存放于/dev目录下,其中串口一,串口二对应设备名依次为“/dev/ttyS0”、“/dev/ttyS1”。在linux下操作串口与操作文件相同。
4. 在使用串口之前必须设置相关配置,包括:波特率、数据位、校验位、停止位等。串口设置由下面结构体实现:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
4.1该结构中c_cflag最为重要,可设置波特率、数据位、校验位、停止位。在设置波特率时需在数字前加上‘B’,如B9600。B19200。使用其需通过“与”“或”操作方式。
4.2输入模式c_iflag成员控制端口接收端的字符输入处理。
5.串口控制函数
Tcgetattr 取属性(termios结构)
Tcsetattr 设置属性(termios结构)
cfgetispeed 得到输入速度
Cfgetospeed 得到输出速度
Cfsetispeed 设置输入速度
Cfsetospeed 设置输出速度
Tcdrain 等待所有输出都被传输
tcflow 挂起传输或接收
tcflush 刷清未决输入和/或输出
Tcsendbreak 送BREAK字符
tcgetpgrp 得到前台进程组ID
tcsetpgrp 设置前台进程组ID
6.串口配置流程
6.1保存原先串口配置使用tcgetattr(fd,&oldtio)函数
struct termios newtio,oldtio;
tcgetattr( fd,&oldtio );
6.2激活选项有CLOCAL和CREAD,用于本地连接和接收使能。
newtio.c_cflag | = CLOCAL | CREAD;
以下是我自己写的一个串口,仅供参考
/*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
memset( &newtio, sizeof( newtio ) );//将串口配置的结构体清零
newtio.c_cflag |= CLOCAL | CREAD; //激活选项有CLOCAL和CREAD,用于本地连接和接收使能
newtio.c_cflag &= ~CSIZE; //使原先的数据位清零
switch( nBits )//选择数据位的个数
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O'://奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': //偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //不进行奇偶校验
newtio.c_cflag &= ~PARENB;
break;
}
switch( nSpeed )//确定输入输出函数的波特率
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
newtio.c_cflag &= ~CSTOPB;//设置停止位为1位
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;//设置停止位为2位
newtio.c_cc[VTIME] = 1;//read调用读到数据则立即返回,否则将为每个字符最多等待1个时间
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);//发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
int open_port(int fd,int comport)
{
char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3"};
long vdisable;
if (comport==1)
{ fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
else
printf("open ttyS0 .....\n");
}
else if(comport==2)
{ fd = open( "/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
else
printf("open ttyS1 .....\n");
}
else if (comport==3)
{
fd = open( "/dev/ttyS2", O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open Serial Port");
return(-1);
}
else
printf("open ttyS2 .....\n");
}
if(fcntl(fd, F_SETFL, 0)<0)
printf("fcntl failed!\n");
else
printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
if(isatty(STDIN_FILENO)==0)
printf("standard input is not a terminal device\n");
else
printf("isatty success!\n");
printf("fd-open=%d\n",fd);
return fd;
}
int main(void)
{
int fd;
int nread,i;
char buff[]="Hello\n";
if((fd=open_port(fd,1))<0){
perror("open_port error");
return;
}
if((i=set_opt(fd,115200,8,'N',1))<0){
perror("set_opt error");
return;
}
printf("fd=%d\n",fd);
// fd=3;
while(1)
{
完成文件的读写操作
}
close(fd);
return;
}
/*****************************************************************************/
转载于:https://blog.51cto.com/decimal/303796