分类: LINUX
#include <stdlib.h> /*标准函数库定义*/
#include <unistd.h> /*Unix标准函数定义*/
#include <sys/types.h> /**/
#include <sys/stat.h> /**/
#include <fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX终端控制定义*/
#include <errno.h> /*错误号定义*/
B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300,
38400, 19200, 9600, 4800, 2400, 1200, 300, };
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
/**
*@brief 设置串口数据位,停止位和效验位
*@param fd 类型 int 打开的串口文件句柄*
*@param databits 类型 int 数据位 取值 为 7 或者8*
*@param stopbits 类型 int 停止位 取值为 1 或者2*
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return(FALSE);
}
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
options.c_iflag |= INPCK; /* Disnable parity checking */
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
/* 设置停止位*/
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
/* Set input parity option */
if (parity != 'n')
options.c_iflag |= INPCK;
options.c_cc[VTIME] = 150; // 15 seconds
options.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
/**
*@breif 打开串口
*/
int OpenDev(char *Dev)
{
int fd = open( Dev, O_RDWR ); //| O_NOCTTY | O_NDELAY
if (-1 == fd)
{ /*设置数据位数*/
perror("Can't Open Serial Port");
return -1;
}
else
return fd;
}
/*
*@breif main()
*/
int main(int argc, char **argv)
{
int fd;
int nread;
char buff[512];
char *dev ="/dev/ttyS1";
fd = OpenDev(dev);
if (fd>0)
set_speed(fd,19200);
else
{
printf("Can't Open Serial Port!\n");
exit(0);
}
if (set_Parity(fd,8,1,'N')== FALSE)
{
printf("Set Parity Error\n");
exit(1);
}
while(1)
{
while((nread = read(fd,buff,512))>0)
{
printf("\nLen %d\n",nread);
buff[nread+1]='\0';
printf("\n%s",buff);
}
}
//close(fd);
//exit(0);
}
* 系统头文件 *.h
**********************************************************************************/
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <linux/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include "def_type.h"
#include "app.h"
#include "Comapi.h"
// 功能: 完成串口设备的打开,与底层交互设备状态
// 参数: void
// 返回: -1 打开失败 >0 打开成功
// 说明: 打开串口1
//=======================================================================//
int databit = 8;
int stopbit = 1;
int parity = 0;
int flowcontrol = 0;
{
char dev[]="/dev/ttyAMA1";
int fdcom = open(dev, O_RDWR);
fcntl(fdcom,F_SETFL,O_NONBLOCK);
if (-1 == fdcom)
{
perror("Can't Open Serial Port");
return -1;
}
else
return fdcom;
}
// 功能: 设置串口设备的波特率,与底层交互设备状态,完成波特率的设置
// 参数: int fd 文件描述符,int speed 串口速率
// 返回: 无
// 说明: 完成串口设备的波特率设置
//=======================================================================//
void Set_Speed(int fd, int speed)
{
app_SetSysValue(dbserialbaudrate,speed);
int speed_arr[] = { B115200, B57600, B38400, B19200, B9600,B4800,B2400,B1200,B600,B300,B150,B110,B75,B50,
B115200, B57600, B38400, B19200, B9600,B4800,B2400,B1200,B600,B300,B150,B110,B75,B50,};
int name_arr[] = { 115200, 57600, 38400, 19200, 9600,4800,2400,1200,600,300,150,110,75,50,
115200, 57600, 38400, 19200, 9600,4800,2400,1200,600,300,150,110,75,50};
unsigned int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
perror("tcsetattr fd");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
// 功能: 设置串口设备属性,与底层交互设备状态,完成数据位,停止位,奇偶校验,流控位的设置
// 参数: int fd 文件描述符,int databit 数据位,int parity 奇偶校验,int flowctrl 流控位
// 返回: 无
// 说明: 完成串口设备属性,与底层交互设备状态,完成数据位,停止位,奇偶校验,流控位的设置
//=======================================================================//
int Set_Com(int fd,int databit,int stopbit,int parity, int flowctrl)
{
struct termios options;
if( tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return -1;
}
options.c_cflag &= ~CSIZE;
options.c_oflag &= ~OPOST; /*OutPUT*/
switch (databit) /* 设置数据位数 */
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\n");
break;
}
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\n");
break;
}
{
case 0:
options.c_cflag &= ~PARENB; /* no parity check */
options.c_cflag &= ~CSTOPB;
break;
case 1:
options.c_cflag |= PARENB; /* odd check */
options.c_cflag &=~PARODD;
options.c_iflag |=INPCK;
break;
case 2:
options.c_cflag |= PARENB; /* even check */
options.c_cflag |= PARODD;
options.c_iflag |= INPCK;
break;
}
{
case 0:
options.c_cflag &= ~CRTSCTS; /*no flow control*/
break;
case 1:
options.c_cflag |= CRTSCTS; /*hardware flow control*/
break;
case 2:
options.c_cflag |= IXON|IXOFF|IXANY; /*software flow control*/
break;
}
/* Set input parity option */
if (parity != 0)
options.c_iflag |= INPCK;
options.c_oflag &=~OPOST; //输出模式原始数据输出
options.c_cc[VTIME] = 150; // 150 15 seconds 控制字符,读取第一个字符的等待时间
options.c_cc[VMIN] = 0; // 0 控制字符,所要读取的字符的最小数量
tcflush(fd,TCIFLUSH); //溢出的数据可以接收,但不读
if (tcsetattr(fd,TCSANOW,&options) != 0) /* Update the options and do it NOW 设置新属性,所有改变立即生效*/
{
perror("SetupSerial 3");
return -1;
}
return 0;
}
//=======================================================================//
// 功能: 把需要传输的数据写入到串口输出
// 参数: int fd 文件描述符,char *buf 需要写入的数据指针, int length写入的数据长度
// 返回: 写入的数据长度
// 说明: 完成数据写入到串口输出
//=======================================================================//
int WriteToCom(int fd, char *buf, int length)
{
//app_GetSysValue(dbserialbaudrate, &baudrate);
//app_GetSysValue(dbserialdatabit, &databit);
//app_GetSysValue(dbserialstopbit, &stopbit);
//app_GetSysValue(dbserialparity, &parity);
//app_GetSysValue(dbserialflowcontrol, &flowcontrol);
Set_Speed(fd,baudrate);
Set_Com(fd,databit,stopbit,parity,flowcontrol);
int len = 0;
len = write(fd,buf,length);
return len;
}
//=======================================================================//
// 功能: 关闭串口
// 参数: int fd 文件描述符
// 返回: 0 关闭成功
// 说明: 关闭串口
//=======================================================================//
{
close(fd);
return 0;
}
{
baudrate = pu->baudRate;
databit = pu->dataBit;
stopbit = pu->stopBit;
parity = pu->parity;
flowcontrol = pu->flowControl;
}
#if 0
int main()
{
daemon(1,1);
int fd = OpenCom();
Set_Speed(fd,9600);
Set_Com(fd,8,1,0,0);
int i=100;
while(i--)
{
char wbuf[]=" abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+={}[]:;',.?";
WriteToCom(fd, wbuf, 36);
usleep(100*1000);
if (i == 10)
CloseCom(fd);
}
}
#endif
Linux 下串口编程入门![]() | ![]() |
![]() |
级别: 初级 左锦 (zuo170@163.com), 副总裁, 南沙资讯科技园 2003 年 7 月 03 日 Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍。 串 行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是 RS-232-C 接口(又称 EIA RS-232-C)它是在 1970 年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换 接口技术标准"该标准规定采用一个 25 个脚的 DB25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于 4% 的情况下,传输电缆长度应为 50 英尺。 Linux 操作系统从一开始就对串行口提供了很好的支持,本文就 Linux 下的串行口通讯编程进行简单的介绍,如果要非常深入了解,建议看看本文所参考的 《Serial Programming Guide for POSIX Operating Systems》 计算机串口的引脚说明
串口操作需要的头文件
在 Linux 下串口文件是位于 /dev 下的 串口一 为 /dev/ttyS0 串口二 为 /dev/ttyS1 打开串口是通过使用标准的文件打开函数操作:
最基本的设置串口包括波特率设置,效验位和停止位设置。 串口的设置主要是设置 struct termios 结构体的各成员值。
设置这个结构体很复杂,我这里就只说说常见的一些设置: 波特率设置 下面是修改波特率的代码:
设置波特率的例子函数:
效验位和停止位的设置:
设置效验的函数:
需要注意的是: 如果不是开发终端之类的,只是串口传输数据,而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯,设置方式如下:
设置好串口之后,读写串口就很容易了,把串口当作文件读写就是。
关闭串口就是关闭文件。
下面是一个简单的读取串口数据的例子,使用了上面定义的一些函数和头文件
|