linux下串口编程简单实例

合集下载

07实验七 Linux环境下的串行通信实验

07实验七 Linux环境下的串行通信实验

连接驱动器的使能端,使得当RTS设置成高(逻辑1)时,有效RS485驱动器;设置RTS为低 时,使驱动器处于三态,这时候实际上从总线上断开了驱动器,从而允许其他节点可以使 用同一传输线。当使用RTS时,必须确保发送数据前将RTS设置成高,在发送完数据的最 后一位后,将RTS线设成低。。另一种可选方法是自动发送数据控制。这种方法要求特殊 的电路,当数据传输时自动使能或无效驱动器。它减少了软件开销和程序员的潜在错误。
五、基础知识
串行通信 1、基本原理 串行端口的本质功能是作为CPU和串行设备间的编码转换器。当数据从CPU经过串行 端口发送出去时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。 串口是系统资源的一部分,应用程序要使用串口进行通信,必须在使用之前向操作系统提 出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。 2、串口通信的基本任务 (1) 实现数据格式化:因为来自CPU的是普通的并行数据,所以,接口电路应具有实 现不同串行通信方式下的数据格式化的任务。在异步通信方式下,接口自动生成起止式的 帧数据格式。在面向字符的同步方式下,接口要在待传送的数据块前加上同步字符。 (2) 进行串-并转换:串行传送,数据是一位一位串行传送的,而计算机处理数据是 并行数据。所以当数据由计算机送至数据发送器时,首先把串行数据转换为并行数才能送 入计算机处理。因此串并转换是串行接口电路的重要任务。 (3) 控制数据传输速率:串行通信接口电路应具有对数据传输速率——波特率进行选 择和控制的能力。 (4) 进行错误检测:在发送时接口电路对传送的字符数据自动生成奇偶校验位或其他 校验码。在接收时,接口电路检查字符的奇偶校验或其他校验码,确定是否发生传送错误。 (5) 进行TTL与EIA电平转换:CPU和终端均采用TTL电平及正逻辑,它们与EIA采用

嵌入式Linux下串口应用编程

嵌入式Linux下串口应用编程
_
式标志
ns u i ne g d s h o r t c
_
I f l a g  ̄ l i n e ,
式标志
ns u i ne g d s h o r t c
_

u ns i ne g d s h o r t C
_
r e a d ( ) 函数立 即返 回。若有可读 的数据时 ,则 读 取数据并返 回被 读取的字节 数,否则读取 失 败 并返 回0 ( 2 ) M I N 大于0 ,T I M E 为0 :r e a d ( ) 函数会等 待 到有M I N 个字节可 以被读取 ,否则一直处于 阻塞状态 。 ( 3 ) M I N 为0 ,而 T I M E > O : 只要满 足 两种情 形下:a 、存在数 据可读 ;b 、阻塞T I M E 的十 分 之一秒 ,r e a d 函数 就会返 回,其中返 回值为 读 取到的字节数 。如果在有数据 可读前超 时,则 r e a d ( ) 函数返 回值为0 。 ( 4 ) M I N 和T I M E 全 都大于0 : 只有满足如 下 两种情形之一 时,r e a d 0函数才会返 回 : 缓存 区 中有 M I N 个字节 ,或 者在两个 字符 之 间超 时 T I 艇个 十分之 一秒 。 从严格意义上 来讲,原始模式是一 种特 殊 的非规范模 式。在原始模 式下,对输入数据 的 处理方式是按 字节为单位 ,并且终端是 不可回 显的 。通过 调用C f m a k e r a w ( ) 函数就 可 以将 把 终端的该工作模式设置为原始模式 。 三 、简单 的串口设置详解流程 下面 以指 纹识别系统为例介 绍下串 口的操 作流程 。 本 系统 中,对串 口的操作和使用 可 以分为 如下几个 部分 :串口的初 始化 ( 包括 串 口设备 的打开 、串 口设备属 性的设置 )、串 口数据单 字节读取 、串 口数据 的多字节读取 、串 口数据 的单字节 写入、串 口数据 的多字节写入 串 口 设备的关闭 。 I . 串口设备 的初始化过程 ( 1 ) 打开 串口 在L i n u x 系统 中,对设 备的操 作如 同普通 文件 一样,在本系统 中打开串 口设备 的代码如 下所示 :

Linux下串口通信编程

Linux下串口通信编程

Linux下串口通信编程一、什么是串口通信?串口通信是指计算机主机与外设之间以及主机系统与主机系统之间数据的串行传送。

使用串口通信时,发送和接收到的每一个字符实际上都是一次一位的传送的,每一位为1或者为0。

二、串口通信的分类串口通信可以分为同步通信和异步通信两类。

同步通信是按照软件识别同步字符来实现数据的发送和接收,异步通信是一种利用字符的再同步技术的通信方式。

2.1 同步通信同步通信是一种连续串行传送数据的通信方式,一次通信只传送一帧信息。

这里的信息帧与异步通信中的字符帧不同,通常含有若干个数据字符。

它们均由同步字符、数据字符和校验字符(CRC)组成。

其中同步字符位于帧开头,用于确认数据字符的开始。

数据字符在同步字符之后,个数没有限制,由所需传输的数据块长度来决定;校验字符有1到2个,用于接收端对接收到的字符序列进行正确性的校验。

同步通信的缺点是要求发送时钟和接收时钟保持严格的同步。

2.2 异步通信异步通信中,数据通常以字符或者字节为单位组成字符帧传送。

字符帧由发送端逐帧发送,通过传输线被接收设备逐帧接收。

发送端和接收端可以由各自的时钟来控制数据的发送和接收,这两个时钟源彼此独立,互不同步。

接收端检测到传输线上发送过来的低电平逻辑"0"(即字符帧起始位)时,确定发送端已开始发送数据,每当接收端收到字符帧中的停止位时,就知道一帧字符已经发送完毕。

在异步通行中有两个比较重要的指标:字符帧格式和波特率。

(1)字符帧,由起始位、数据位、奇偶校验位和停止位组成。

1.起始位:位于字符帧开头,占1位,始终为逻辑0电平,用于向接收设备表示发送端开始发送一帧信息。

2.数据位:紧跟在起始位之后,可以设置为5位、6位、7位、8位,低位在前高位在后。

3.奇偶校验位:位于数据位之后,仅占一位,用于表示串行通信中采用奇校验还是偶校验。

(2)波特率,波特率是每秒钟传送二进制数码的位数,单位是b/s。

异步通信的优点是不需要传送同步脉冲,字符帧长度也不受到限制。

嵌入式操作系统Linux中的串口应用编程

嵌入式操作系统Linux中的串口应用编程


嵌入式操作系统 L x 的审口应用编程 iu 中 n
■ 厦 门 大 学 唐 建 东 卢 贵 主
针 对 嵌 入 式 Linux 操 作 系统 的 特 点 , 分 析 在 该 系统 下 串行 通 信 口编 程 控 制 的 方 法 , 总 结 程 序


设 计 的 步 骤 ; 在 嵌 入 式 Linux 系 统 上 , 编 写控 制 程 序 , 成 功 地 实 现 嵌 入 式 系统 与微 机 系 统

Te s I s r m e s, U SA .TM ¥3 0C X / X / xa n t u nt 2 l C2
更详 细 的 内容 在 此 不 再 多述 , 本 人将 另 文 介 绍 。■ _
参考 文献
l 彭 启 琮 , 李 玉 柏 ,管 庆 .DS P与 实 时 数 字 信 号 处 理 .成 都 :电 子 科 技 大 学 出版 社 , l 9 5 9 2 戴 明 桢 .数 字 信 号 处理 的 硬 件 实现 . 北 京 :
根 据 不 同 条 件 控 制 不 同 的 设 备 。 基 于 美 国 电 子 工 业 协 会 E A 的 串 口通 信 标 准 一 I RS 3 , 是 目前 广 泛 使 22 用 的 设备 控 制 通 信 接 口 。在 嵌 入 式 系统 中实 现 串 口 通 信 , 可 延 伸 系 统 的 应 用 触 角 , 扩 大 系 统 的 数 据 采
# k od iln m e il tpe u b r um b r m n f e a f ey n m e n l e2
1 嵌 入式 操作 系统 L n x串 口模 块 u i
L n x操 作 系 统 的 主 要 优 点 是 稳 定 、 内 核 可 重 iu 新 编 译 、 提 供 开 放 的 内 核 源 代 码 。 Li u 内 核 采 用 n x

嵌入式linux串口应用程序编写流程

嵌入式linux串口应用程序编写流程

嵌入式linux串口应用程序编写流程嵌入式Linux系统提供了丰富的串口接口,可以通过串口与其他设备进行通信,这为开发嵌入式系统提供了很多可能性。

下面是编写嵌入式Linux串口应用程序的流程:1. 确定串口设备:首先要确定要使用的串口设备,可以使用命令`ls /dev/tty*`来查看系统中可用的串口设备列表。

根据需要选择合适的串口设备。

2. 打开串口设备:在Linux系统中,使用文件的方式来操作串口设备。

可以使用C语言中的open函数来打开串口设备文件,并返回串口设备的文件描述符。

例如:`int serial_fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);`。

其中,`O_RDWR`表示以读写模式打开串口设备,`O_NOCTTY`表示打开设备后不会成为该进程的控制终端,`O_NDELAY`表示非阻塞模式。

3. 配置串口参数:打开串口设备后,需要配置串口参数,包括波特率、数据位、停止位、校验位等。

可以使用C语言中的termios库来进行串口参数的配置。

例如:```cstruct termios serial_config;tcgetattr(serial_fd, &serial_config);cfsetispeed(&serial_config, B115200);cfsetospeed(&serial_config, B115200);serial_config.c_cflag |= CS8;serial_config.c_cflag &= ~PARENB;serial_config.c_cflag &= ~CSTOPB;tcsetattr(serial_fd, TCSANOW, &serial_config);```上述代码将波特率设置为115200,数据位设置为8位,无校验位,一个停止位。

linux下的串口通信原理及编程实例

linux下的串口通信原理及编程实例

linux下的串⼝通信原理及编程实例linux下的串⼝通信原理及编程实例⼀、串⼝的基本原理1 串⼝通讯串⼝通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进⾏传输数据的⼀种通讯⽅式。

串⼝是⼀种接⼝标准,它规定了接⼝的电⽓标准,没有规定接⼝插件电缆以及使⽤的协议。

2 串⼝通讯的数据格式 ⼀个字符⼀个字符地传输,每个字符⼀位⼀位地传输,并且传输⼀个字符时,总是以“起始位”开始,以“停⽌位”结束,字符之间没有固定的时间间隔要求。

每⼀个字符的前⾯都有⼀位起始位(低电平),字符本⾝由7位数据位组成,接着字符后⾯是⼀位校验位(检验位可以是奇校验、偶校验或⽆校验位),最后是⼀位或⼀位半或⼆位停⽌位,停⽌位后⾯是不定长的空闲位,停⽌位和空闲位都规定为⾼电平。

实际传输时每⼀位的信号宽度与波特率有关,波特率越⾼,宽度越⼩,在进⾏传输之前,双⽅⼀定要使⽤同⼀个波特率设置。

3 通讯⽅式单⼯模式(Simplex Communication)的数据传输是单向的。

通信双⽅中,⼀⽅固定为发送端,⼀⽅则固定为接收端。

信息只能沿⼀个⽅向传输,使⽤⼀根传输线。

半双⼯模式(Half Duplex)通信使⽤同⼀根传输线,既可以发送数据⼜可以接收数据,但不能同时进⾏发送和接收。

数据传输允许数据在两个⽅向上传输,但是,在任何时刻只能由其中的⼀⽅发送数据,另⼀⽅接收数据。

因此半双⼯模式既可以使⽤⼀条数据线,也可以使⽤两条数据线。

半双⼯通信中每端需有⼀个收发切换电⼦开关,通过切换来决定数据向哪个⽅向传输。

因为有切换,所以会产⽣时间延迟,信息传输效率低些。

全双⼯模式(Full Duplex)通信允许数据同时在两个⽅向上传输。

因此,全双⼯通信是两个单⼯通信⽅式的结合,它要求发送设备和接收设备都有独⽴的接收和发送能⼒。

在全双⼯模式中,每⼀端都有发送器和接收器,有两条传输线,信息传输效率⾼。

显然,在其它参数都⼀样的情况下,全双⼯⽐半双⼯传输速度要快,效率要⾼。

Linux串口通信编程

Linux串口通信编程

2) 设置属性:奇偶校验位、数据位、停止位。

主要设置<termbits.h>中的termios3) 打开、关闭和读写串口。

串口作为设备文件,可以直接用文件描述符来进行网上的一个例子:/*串口设备无论是在工控领域,还是在嵌入式设备领域,应用都非常广泛。

而串口编程也就显得必不可少。

偶然的一次机会,需要使用串口,而且操作系统还要求是Linux,因此,趁着这次机会,综合别人的代码,进行了一次整理和封装。

具体的封装格式为C代码,这样做是为了很好的移植性,使它可以在C和C++环境下,都可以编译和使用。

代码的头文件如下: *//////////////////////////////////////////////////////////////////// //////////////filename:stty.h#ifndef__STTY_H__#define__STTY_H__//包含头文件#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<termios.h>#include<errno.h>#include<pthread.h>//// 串口设备信息结构typedef struct tty_info_t{int fd;// 串口设备IDpthread_mutex_t mt;// 线程同步互斥对象char name[24];// 串口设备名称,例:"/dev/ttyS0"struct termios ntm;// 新的串口设备选项struct termios otm;// 旧的串口设备选项}TTY_INFO;//// 串口操作函数TTY_INFO *readyTTY(int id);int setTTYSpeed(TTY_INFO *ptty,int speed);int setTTYParity(TTY_INFO *ptty,int databits,int parity,int st opbits);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()是为了能够在多线程中使用。

Linux下 QT串口与51单片机通信实例

Linux下 QT串口与51单片机通信实例

QT串口与51单片机通信通过这个小例子主要想说明QT怎样进行线程编程的思想,实例如图,好吧,下面是过程上一个例子我们采用的是手工编写代码的方法,这个例子我们来玩一下designer,其实Qt4己经把界面与功能分开了,用designer来进行界面设计,再手工编写一些功能,如信号与槽,这样开发效率会大大提高,呵呵,开一个终端,输入/usr/local/Trolltech/Qt-4.5.1/bin/designer,如果第一次打开出现字体不对,可以打开qtconfig进行一些相关配置,打开后我们新建一个Main Window,在右边的属性框中设置一下界面大小,1.我ARM板的LCD大小为320x240,所以我也设为320x240;2.左边是一些我们常用的窗口部件,这里我们用到一个lable标签来做显示,再放几个pushButton按钮,在属性objectName重新更改它的名字,改为我们记得的,这样在写功能时记得哪个按钮叫什么名字,对于一个初学QT的人来说,很想知道每一个部件到底有什么信号和槽,别急,我们可以这样来看,选中一个lable,按F4,再点击lable拖动出现接地符号时松开,弹出编辑信号与槽,这时左边列出的是信号,右边为槽,这里我们不用配置连接,等下我们再手工写,3最后我们用到一个lable标签和三个pushButton按钮,并命名为dis_label、writeButton、readButton、closeButton,然后保存为mainwindow.ui,这样designer就完工了,呵呵..4.下面我们编写一个线程,用于管理串口收发工作,它不涉及到任何界面,只做好它的本份工作就得了,编写一个thread.h文件gedit thread.h,#ifndef THREAD_H#define THREAD_H#include<QThread>class Thread:public QThread{Q_OBJECTpublic:Thread();char buf[128];volatile bool stopped;volatile bool write_rs;volatile bool read_rs;protected:virtual void run();};#endif我们定义一个Thread类,它继承于QThread,看到只设有一些变量和一个run函数,virtual表示为虚函数,你也可以去掉,加上去会增加一些内存开销,但提高了效率,对于这个小程序是看不出什么效果的,volatile这个大家都懂了吧,就是防止偷懒,呵呵,5.再看看thread.cpp#include"thread.h"#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h> //串口用到的#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <strings.h>#define BAUDRATE B9600//#define RS_DEVICE "/dev/ttyS0" //串口1#define RS_DEVICE "/dev/ttySAC1" //串口1Thread::Thread(){} //析构void Thread::run() //这就是线程的具体工作了int fd,c=0,res;struct termios oldtio,newtio; //termios结构是用来保存波特率、字符大小等printf("start...\n");fd=open(RS_DEVICE,O_RDWR|O_NOCTTY); //以读写方式打开串口。

linux设备驱动,tty串口编程

linux设备驱动,tty串口编程

linux设备驱动,tty串口编程2011-12-04 08:56:33分类:LINUXXC2440开发板上已经含有S3C2440的3个串口驱动,我们只要知道各个串口的设备名称就可以了,204 s3c2410_serial ,204是串口的主设备号。

s3c2410_serial是设备名称,在 dev目录下 ls 一下就可以发现ptyd0 s3c2410_serial0 ttysaptyd1 s3c2410_serial1 ttysbptyd2 s3c2410_serial2 ttyscs3c2410_serial0,s3c2410_serial1,s3c2410_serial2 分别是串口1、2、3的设备名称下面是测试源码,打开串口1、2,程序执行后,串口1的波特率变为9600,这时候你的串口终端就没有反应了(串口1波特率默认115200),把终端软件串口1 波特率改为9600后,连接终端,回车一下,然后输入几个‘1’后,画面如上图。

这时用telnet工具登陆开发板,执行ps 查看现有运行的程序,找到tty [root@XC2440 /root]# psPID USER TIME COMMAND1 root 0:04 init2 root 0:00 [kthreadd]3 root 0:00 [ksoftirqd/0]5 root 0:00 [kworker/u:0]6 root 0:00 [khelper]7 root 0:00 [kworker/u:1]10 root 0:00 [netns]236 root 0:00 [sync_supers]238 root 0:00 [bdi-default]240 root 0:00 [kblockd]249 root 0:00 [khubd]252 root 0:00 [kseriod]258 root 0:00 [kmmcd]347 root 0:00 [rpciod]349 root 0:00 [kworker/0:1]355 root 0:00 [kswapd0]356 root 0:00 [aio]357 root 0:00 [nfsiod]358 root 0:00 [crypto]901 root 0:00 [mtdblock0]906 root 0:00 [mtdblock1]911 root 0:00 [mtdblock2]916 root 0:00 [mtdblock3]1028 root 0:00 [usbhid_resumer]1049 root 0:00 [yaffs-bg-1]1060 root 0:00 vsftpd /etc/vsftpd.conf1065 root 0:00 -/bin/sh1067 root 0:00 /usr/sbin/telnetd -l /bin/login1070 root 0:18 /usr/local/qtopia/bin/qpe -qws1071 root 0:00 boa1072 root 0:00 [kworker/0:2]1085 root 0:02 /usr/local/qtopia/bin/quicklauncher1086 root 0:00 /usr/local/qtopia/bin/qss1089 root 0:02 /usr/local/qtopia/bin/quicklauncher1098 root 0:00 [flush-31:3]1100 root 0:00 ./tty1101 root 0:00 -ash1104 root 0:00 ps[root@XC2440 /root]# kill 1100执行 kill 1100 后tty测试程序就被终止了,这时串口终端就可以用了,回车一下Terminated[@XC2440 pub]#Please press Enter to activate this console.Processing /etc/profile...Done[root@XC2440 /]#[root@XC2440 /]#测试代码如下:#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/types.h>#include <errno.h>#include <termios.h>#include <sys/time.h>#include <signal.h>#include <string.h>#include <fcntl.h>#include <asm/param.h>#include "pthread.h"//#include "serial_set.h"/******************************************************************* * 函数名称: set_opt* 功能描述:设置串口基本参数* 输入参数: fd 打开的串口标识符(通过open_port函数返回)nSpeed 波特率 2400、4800、9600、115200nBits 数据位 7、8nEvent 奇偶校验 'O' 'N' 'E'nStop 停止位 1、2* 输出参数:无* 返回值: 0 设置成功-1 设置过程出错* 其它说明:无* 修改日期版本号修改人修改内容*-------------------------------------------------------------------- * 2010/09/27 V1.0 *** 创建函数***********************************************************************/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;}//extern void bzero(void *s, int n); 置字节字符串s的前n个字节为零bzero( &newtio, sizeof( newtio ) );//设置字符大小newtio.c_cflag |= 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 &= ~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; else if ( nStop == 2 )//设置等待时间和最小接收字符newtio.c_cc[VTIME] = 0;newtio.c_cc[VMIN] = 0;//处理未接收字符tcflush(fd,TCIFLUSH);//激活新配置if((tcsetattr(fd,TCSANOW,&newtio))!=0){perror("com set error");//打印com set error及出错原因return -1;}printf("set done!\n");return 0;}/******************************************************************** *** 函数名称: open_port* 功能描述:打开指定串口* 输入参数: fd 文件描述符comport 串口号(1、2、3)* 输出参数:无* 返回值:出错返回 -1成功返回 fd文件描述符* 其它说明:无* 修改日期版本号修改人修改内容*-------------------------------------------------------------------- * 2010/09/27 V1.0 *** 创建函数********************************************************************* **//*static struct uart_driver s3c24xx_uart_drv = {.owner = THIS_MODULE,.dev_name = "s3c2410_serial",.nr = CONFIG_SERIAL_SAMSUNG_UARTS,.cons = S3C24XX_SERIAL_CONSOLE,.driver_name = S3C24XX_SERIAL_NAME,.major = S3C24XX_SERIAL_MAJOR,.minor = S3C24XX_SERIAL_MINOR,};*/int open_port(int fd,int comport){//char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"}; long vdisable;//没用//打开串口if (comport==1){//fd = open("/dev/ttySAC0",O_RDWR|O_NOCTTY|O_NDELAY);fd = open("/dev/s3c2410_serial0",O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd){perror("Can't Open s3c2410_serial0");return(-1);}elseprintf("open s3c2410_serial0 .....\n");}else if(comport==2){fd = open("/dev/s3c2410_serial1",O_RDWR|O_NOCTTY|O_NDELAY); if (-1 == fd){perror("Can't Open s3c2410_serial1");return(-1);}elseprintf("open s3c2410_serial1 .....\n");}else if (comport==3){fd = open("/dev/s3c2410_serial2",O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open s3c2410_serial2");return(-1);}elseprintf("open s3c2410_serial2 .....\n");}else if (comport==4){fd = open("/dev/s3c2410_serial3",O_RDWR|O_NOCTTY|O_NDELAY);if (-1 == fd){perror("Can't Open s3c2410_serial3");return(-1);}elseprintf("open s3c2410_serial3 .....\n");}//恢复串口的状态为阻塞状态,用于等待串口数据的读入if(fcntl(fd, F_SETFL, 0) < 0)printf("fcntl failed!\n");elseprintf("fcntl=%d\n",fcntl(fd, F_SETFL,0));//测试打开的文件描述符是否引用一个终端设备,以进一步确认串口是否正确打开if(isatty(STDIN_FILENO)==0)printf("standard input is not a terminal device\n");elseprintf("isatty success!\n");printf("fd-open=%d\n",fd);return fd;}unsigned int val=0;int main(int argc, char **argv){long ret=0;int receNum=0,receFlag=0;unsigned char ReceBuf[512],SendBuf[512];int fd,fdd;int nread,i;unsigned char buff[512];struct timeval timeout;bzero(buff, 512);if((fdd=open_port(fdd,2)) < 0)//打开串口 2{printf("open_port error2\n");return -1;}if((i=set_opt(fdd,9600,8,'N',1)) < 0)//设置串口 9600 8 N 1 {printf("set_opt error2\n");return -1;}printf("fd=%d\n",fdd);if((fd=open_port(fd,1)) < 0)//打开串口 1{printf("open_port error1\n");return -1;}if((i=set_opt(fd,9600,8,'N',1)) < 0)//设置串口 9600 8 N 1 {printf("set_opt error1\n");return -1;}printf("fd=%d\n",fd);_sec=1;//设置定时器_usec=0;while (1){nread = read(fd,buff,256);//读串口数据非阻塞if(nread>0){memcpy(&ReceBuf[receNum],buff,nread);receFlag=2;receNum +=nread; if(receNum>511)receNum=0;printf("nread = %d\n",nread);printf("%s\n",buff);bzero(buff,nread);//清空}else{//printf("main\n");if(receFlag>1)receFlag--;if(receFlag==1){write(fd,ReceBuf,receNum);//写数据receNum=0;receFlag=0;}_sec=0;_usec=20000;//设置时间 20MS 读取一下串口数据ret=select(0,NULL,NULL,NULL,&timeout);}}close(fdd);close(fd);return 0;}。

Linux串口测试程序

Linux串口测试程序

return g_PCUART_fd; }
uart_init int
( int COM, int BAUD, int databits, int stopbit, int paritybit )
{ int fd_uart;
struct termios options;
if( COM1 == COM ) {
/* ===============================================================================
********************
<lihf> linux串口测试代码
*******************
* Linux版本号2.6.23.17
printf("[ERROR]Uart databits is wrong! \n"); goto ↓uart_init_fail; }
switch( stopbit )
{
case 1 : options.c_cflag &= ~CSTOPB; break; //1位停止位 case 2 : options.c_cflag |= CSTOPB; break; //2位停止位
BAUD = B9600; }
if( cfsetospeed(&options, BAUD) < 0 )
{ printf("[fail] Set uart output baudrate fail!\n"); goto ↓uart_init_fail;
}
if( cfsetispeed(&options, BAUD) < 0 )

Linux C 串口编程

Linux C 串口编程

Linux C 串口编程arch/arm/include/asm/termbits.hstruct termios {tcflag_t c_iflag; /* input mode flags */tcflag_t c_oflag; /* output mode flags */tcflag_t c_cflag; /* control mode flags */tcflag_t c_lflag; /* local mode flags */cc_t c_line; /* line discipline */cc_t c_cc[NCCS]; /* control characters */ };串口的设置主要是设置struct termios结构体的各成员/***测试的时候应用程序在后台运行./serial_test &*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> //文件控制定义#include <termios.h>//终端控制定义#include <errno.h>#define DEVICE "/dev/s3c2410_serial0"int serial_fd = 0;//打开串口并初始化设置init_serial(void){serial_fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);if (serial_fd < 0) {perror("open");return -1;}//串口主要设置结构体termios <termios.h>struct termios options;/**1. tcgetattr函数用于获取与终端相关的参数。

linux下485通讯c语言代码

linux下485通讯c语言代码

linux下485通讯c语言代码Linux下的485通讯C语言代码在嵌入式系统和工控领域中,485通讯是一种常见的串行通讯方式。

Linux作为一种常用的操作系统,也提供了相应的接口和工具来支持485通讯。

本文将介绍在Linux下使用C语言实现485通讯的代码。

在开始编写485通讯的C语言代码之前,我们需要先了解一些基本的概念和原理。

485通讯是一种半双工的串行通讯方式,它使用两根信号线进行数据的传输,一根用于发送数据(TX),一根用于接收数据(RX)。

通常情况下,485通讯使用的波特率较低,例如9600bps或者19200bps。

在Linux下,我们可以通过打开串口设备文件来实现485通讯。

串口设备文件的命名规则为/dev/ttySx,其中x表示串口的编号。

例如,/dev/ttyS0表示第一个串口设备,/dev/ttyS1表示第二个串口设备。

我们可以使用open函数来打开串口设备文件,并使用read 和write函数来进行数据的读写操作。

下面是一个简单的示例代码,演示了如何在Linux下使用C语言实现485通讯:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>int main(){int fd;char data[10];// 打开串口设备文件fd = open("/dev/ttyS0", O_RDWR);if (fd == -1) {printf("无法打开串口设备文件\n");return -1;}// 配置串口参数struct termios options;tcgetattr(fd, &options);cfsetispeed(&options, B9600); // 设置波特率为9600bps cfsetospeed(&options, B9600);options.c_cflag |= CLOCAL | CREAD;options.c_cflag &= ~CSIZE;options.c_cflag |= CS8;options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;tcsetattr(fd, TCSANOW, &options);// 发送数据strcpy(data, "Hello");write(fd, data, strlen(data));// 接收数据read(fd, data, sizeof(data));printf("接收到的数据:%s\n", data);// 关闭串口设备文件close(fd);return 0;}```上述代码首先通过open函数打开了/dev/ttyS0这个串口设备文件,如果打开失败,则会提示无法打开串口设备文件并退出。

linux c语言编写modbus rtu例程 -回复

linux c语言编写modbus rtu例程 -回复

linux c语言编写modbus rtu例程-回复如何使用C语言在Linux下编写Modbus RTU例程,以实现数据的读取和写入。

Modbus是一种通信协议,用于在工业自动化系统中实现设备之间的数据通信。

RTU是Modbus协议的一种传输格式,其中数据以二进制形式传输。

在Linux系统中,我们可以使用C语言来编写Modbus RTU例程。

下面将一步一步回答如何实现数据的读取和写入。

第一步:设置串口参数在Linux中,我们可以使用串口来与Modbus设备进行通信。

首先,我们需要设置串口的波特率、数据位、停止位和校验位。

这可以通过C语言中的termios库函数来实现。

c#include <termios.h>int set_serial_port(int fd, int baudrate) {struct termios options;tcgetattr(fd, &options);cfsetispeed(&options, baudrate);cfsetospeed(&options, baudrate);options.c_cflag = (CLOCAL CREAD);options.c_cflag &= ~CSIZE;options.c_cflag = CS8;options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;options.c_cflag &= ~CRTSCTS;tcsetattr(fd, TCSANOW, &options);}以上代码中,`set_serial_port`函数用于设置串口参数。

`fd`参数为串口文件描述符,`baudrate`参数为波特率。

其中,`cfsetispeed`和`cfsetospeed`函数用于设置输入和输出速度,`CLOCAL`和`CREAD`标志用于使串口工作在本地模式和可读模式,`CS8`标志用于设置8位数据位,`PARENB`标志用于禁用奇偶校验,`CSTOPB`标志用于设置停止位为1位,`CRTSCTS`标志用于禁用硬件流控制。

linux c语言 串口读取数据的方法

linux c语言 串口读取数据的方法

linux c语言串口读取数据的方法Linux下使用C语言读取串口数据的方法引言:串口是计算机和外部设备进行通信的一种重要的通信接口。

在Linux系统中,要使用C语言读取串口数据,需要通过打开串口设备文件,设置串口参数,并进行读取数据的操作。

本文将介绍如何通过C语言在Linux下读取串口数据的方法。

目录:1. 了解串口的工作原理2. 打开串口设备文件3. 设置串口参数4. 读取串口数据5. 示例程序6. 总结1. 了解串口的工作原理:在开始编写C语言读取串口数据的方法前,首先需要了解串口的工作原理。

串口是通过硬件电路实现两台设备之间的数据传输,属于一种异步串行通信方式。

典型的串口包含发送数据引脚(TX)、接收数据引脚(RX)、数据位、停止位、奇偶校验位等。

2. 打开串口设备文件:在Linux系统中,每个串口设备都被映射到一个设备文件上,例如/dev/ttyS0代表第一个串口设备,/dev/ttyUSB0代表第一个USB串口设备。

要使用C语言读取串口数据,需要首先打开相应的串口设备文件。

在C语言中,使用open()函数打开串口设备文件。

open()函数的原型如下:cint open(const char *pathname, int flags);其中pathname参数指定要打开的串口设备文件路径,flags参数指定打开方式。

常用的flags参数有O_RDONLY(只读方式打开)、O_WRONLY (只写方式打开)和O_RDWR(读写方式打开)。

例如,要打开第一个串口设备文件,可以调用open()函数如下:cint fd = open("/dev/ttyS0", O_RDWR);if (fd == -1){perror("Error opening serial port");return -1;}当open()函数成功打开串口设备文件时,会返回一个非负整数的文件描述符fd,用于后续的操作。

Linux下串口协议控制51单片机

Linux下串口协议控制51单片机

linux下串口协议控制51单片机(涉及多线程操作)/***************************************************************************writen by jingshui 7-17 2011 12:53说明:这是一个linux下串口,多线程测试程序Version 0.26***************************************************************************/ # include <stdio.h># include <unistd.h># include <stdlib.h># include <termios.h># include <fcntl.h># include <string.h># include <sys/time.h># include <sys/types.h># include <pthread.h>int fd;pthread_t thread[2];pthread_mutex_t mutex;/**************************************************************************** 结构体说明:传送控制单片机的信息成员1:select 选择功能模块成员2:control 控制单片机相应的动作*****************************************************************************/ struct protocal{unsigned char select;unsigned char control;};struct protocal ptr[14]={{0xa1,0x01},{0xa1,0x02},{0xa1,0x03},{0xa1,0x04},{0xa1,0x05},{0xa1,0x06},{0xa1,0x07},{0xa1,0x08},{0xb2,0x00},{0xb2,0x03},{0xb2,0x06},{0xb2,0x09},{0xb2,0x0e},{0xc3,0xd4}};/********************************************************************功能说明:设置linux串口参数传入参数:fd nspeed nbit nevent nstop文件句柄波特率数据位奇偶校验停止位返回值: fd 文件句柄********************************************************************/int set_port(int fd ,int nspeed ,int nbits ,char nevent ,int nstop){struct termios newtio,oldtio;if (tcgetattr(fd,&oldtio)!= 0){perror("setup serial");return -1;}bzero(&newtio,sizeof(newtio));newtio.c_cflag |= 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 'N':newtio.c_cflag &= ~PARENB;break;}switch (nspeed){case 9600:cfsetispeed(&newtio,B9600);cfsetospeed(&newtio,B9600);break;}switch (nstop){case 1:newtio.c_cflag &= ~CSTOPB;break;case 2:newtio.c_cflag |= CSTOPB;break;}newtio.c_cc[VTIME]= 0;newtio.c_cc[VMIN]= 14;tcflush(fd,TCIFLUSH);if ((tcsetattr(fd,TCSANOW,&newtio))!= 0){perror("com set");return -1;}return 0;}int open_port(int fd,int comport){if (comport == 1){fd = open ("/dev/ttyUSB0",O_RDWR);if ( -1 == fd ){perror("can't open serial port");return -1;}}return fd;}void write_port(void){int nwrite,i;for (i=0;i<14;i++){nwrite = write(fd,&ptr[i],2);usleep(200000);/*每200ms秒发一次数据*/}}void read_port(void){fd_set rd;int nread,retval;unsigned char msg[14];struct timeval timeout;FD_ZERO(&rd);FD_SET(fd,&rd);_sec = 1;_usec = 0;retval = select (fd+1,&rd,NULL,NULL,&timeout);/*select 实现i/o复用*/ switch (retval){case 0:printf("no data input within 1 seconds.\n");break;case -1:perror("select");break;default:if((nread=read(fd,msg,14))>0){printf("nread=%d,msg=%s\n",nread,msg);}break;}}void *recv_thread(void ){pthread_mutex_lock(&mutex);read_port();pthread_mutex_unlock(&mutex);pthread_exit(NULL);}void *send_thread(void ){pthread_mutex_lock(&mutex);write_port();pthread_mutex_unlock(&mutex);pthread_exit(NULL);}void create_thread(void ){int temp;memset(thread, 0, sizeof(thread));if((temp = pthread_create(&thread[0], NULL,(void *)send_thread, NULL)) != 0) printf("create send_thread failed!\n");if((temp = pthread_create(&thread[1], NULL,(void *)recv_thread, NULL)) != 0) printf("create recev_thread failed!\n");}void wait_thread(void ){if(thread[0] !=0){pthread_join(thread[0],NULL);printf("send_thread end\n");}if(thread[1] !=0){pthread_join(thread[1],NULL);printf("recev_thread end\n");}}int main(void ){int i;if((fd=open_port(fd,1))<0){perror("open_port error");}if((i=set_port(fd,9600,8,'N',1))<0){perror("set_opt error");}/*用默认属性初始化互斥锁*/pthread_mutex_init(&mutex,NULL);int num = 100;while (num){create_thread();wait_thread();num--;}pthread_mutex_destroy(&mutex);close(fd);return 0;}51单片机程序#include <reg52.h>typedef unsigned char uint8;typedef unsigned int uint16;sbit key = P3^2;sbit s1 = P2^0; //选通数码管1sbit s2 = P2^1;sbit s3 = P2^2;sbit s4 = P2^3;sbit en = P2^5; //573锁存使能位sbit buzzer = P2^4; //蜂鸣器选通位sbit key1 = P3^2;sbit key2 = P3^3;sbit key3 = P3^4;sbit key4 = P3^5;sbit key5 = P3^7;uint8 i=0;uint8 r_data[2]; //用来接收数据的缓冲区uint8 code smg[16] = {0xC0,0xF9,0xA4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; unsigned char code pmd[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};unsigned char code s_data1[]="key1 pressed\n";unsigned char code s_data2[]="key2 pressed\n";unsigned char code s_data3[]="key3 pressed\n";unsigned char code s_data4[]="key4 pressed\n";unsigned char code s_data5[]="key5 pressed\n";void init_serial(void) //初始化串口{TMOD = 0x20; //设置定时器1工作方式1;TH1 = 0xFD; //波特率发生器,产生9600的波特率TL1 = 0xFD;PCON = 0x00;SCON = 0x50; //选择串口工作方式1,允许接收EA = 1; //开中断ES = 1;TR1 = 1; //启动定时器}void delay(uint16 i)//20ms{unsigned char j,k;for(j=i;j>0;j--)for(k=115;k>0;k--);}void test_serial1(void ){int i;EA=0;for(i=0;i<sizeof(s_data1);i++){SBUF=s_data1[i];while(TI==0);TI=0;}EA=1;}void test_serial2(void ){int i;EA=0;for(i=0;i<sizeof(s_data2);i++){SBUF=s_data2[i];while(TI==0);TI=0;}EA=1;}void test_serial3(void ){int i;EA=0;for(i=0;i<sizeof(s_data3);i++){SBUF=s_data3[i];while(TI==0);TI=0;}EA=1;}void test_serial4(void ){int i;EA=0;for(i=0;i<sizeof(s_data4);i++){SBUF=s_data4[i];while(TI==0);TI=0;EA=1;}void test_serial5(void ){int i;EA=0;for(i=0;i<sizeof(s_data5);i++){SBUF=s_data5[i];while(TI==0);TI=0;}EA=1;}void led_control(uint8 i) //led控制模块{unsigned char x;if (i>8){P1 = 0xff;delay(10);}else{x = i-1;P1 = pmd[x];delay(80);P1 = 0xff;}}void seg_control(uint8 i) //数码管控制模块{en = 1;s1 = 0;s3 = 0;s2 = 0;s4 = 0;if (i>0x0f)P0 = 0xff;delay(10);}else{P0 = smg[i];delay(80);P0 = 0xff;}}void buzzer_control(uint8 i) //蜂鸣器控制模块{if (i == 0xd4)buzzer = 0;delay(100);buzzer = 1;}void handle_date(){uint8 i = r_data[0];switch(i){case 0xa1:led_control(r_data[1]);break;case 0xb2:seg_control(r_data[1]);break;case 0xc3:buzzer_control(r_data[1]);default:break;}}void readkey(void){RI=0;if(!key1)delay(30);if(!key1){test_serial1();while(!key1);}}if(!key2){delay(30);if(!key2){test_serial2();while(!key2);}}if(!key3){delay(30);if(!key3){test_serial3();while(!key3);}}if(!key4){delay(30);if(!key4){test_serial4();while(!key4);}}if(!key5){delay(30);if(!key5){test_serial5();while(!key5);}}}void main(void ){init_serial();while(1){readkey();}}void server(void ) interrupt 4{ES = 0;RI = 0;r_data[i] = SBUF;if(2 == ++i){handle_date();i = 0;}ES = 1;}/****************************************************************************** *writen by jingshui说明:51单片机检测程序,把从上位机接收的数据发回去。

Linux下串口编程中断

Linux下串口编程中断

L i n u x下串口编程中断 The pony was revised in January 2021Linux 下串口编程的文章网上是满天飞,但大都是出自一篇文章,而且写的都是些基本的操作,像控制 RTS/CTS 等串口引脚状态,接收发送二进制数据等,都没有很好的说明,我在使用中遇到了些问题,写出来,希望能对大家有所帮助,少走弯路,呵呵!我使用的操作系统是 Redhat9 , gcc 版本是 3.2.2其实在 linux 下对串口的设置主要是通过 termios 这个结构体实现的,但是这个结构体却没有提供控制 RTS 或获得 CTS 等串口引脚状态的接口,可以通过 ioctl 系统调用来获得 / 控制。

获得:ioctl(fd, TIOCMGET, &controlbits);if (controlbits & TIOCM_CTS)printf(“有信号 \n”);elseprintf(“无信号 \n”);设置:ioctl(fd, TIOCMGET, &ctrlbits) ;if (flag)ctrlbits |= TIOCM_RTS;elsectrlbits &= ~TIOCM_RTS;ioctl(fd, TIOCMSET, &ctrlbits);其实 TIOCM_RTS 有效后是把串口的 RTS 设置为有信号,但串口的电平为低时是有信号,为高时为无信号,和用 TIOCMGET 获得的状态正好相反,也就是说 TIOCMGET/TIOCMSET 只是获得 / 控制串口的相应引脚是否有信号,并不反应当前串口的真实电平高低。

网上许多流行的 linux 串口编程的版本中都没对 c_iflag ( termios 成员变量)这个变量进行有效的设置,这样传送 ASCII 码时没什么问题,但传送二进制数据时遇到0x0d,0x11 和 0x13 却会被丢掉。

不用说也知道,这几个肯定是特殊字符,被用作特殊控制了。

基于linux (fedora 17)的QT串口通信实例

基于linux (fedora 17)的QT串口通信实例
下载到的文件为 qextserialport-1.2win-alpha.zip
2.解压下载的文件到当前目录
# unzip qextserialport-1.2win-alpha.zip
这里不对压缩包内的详细信息及qextserialport类的结构做详细介绍,直接说明需要用到的源文件
linux下:
myCom->setParity(PAR_NONE);
//奇偶校验设置,我们设置为无校验
myCom->setStopBits(STOP_1);
//停止位设置,我们设置为1位停止位
myCom->setFlowControl(FLOW_OFF);
//数据流控制设置,我们设置为无数据流控制
ui(new Ui::MainWindow){
ui->setupUi(this);
//myCom = new Win_QextSerialPort("COM1",QextSerialBase::EventDriven);
//【windows下使用】定义串口对象,指定串口名和查询模式,这里使用事件驱动EventDriven
3.打开Qt Creator集成开发环境,新建工程Qt4 Gui Application ,工程名为com ,其他默认即可。
4.将上述linux下需要用到的4个文件拷贝至com工程目录下,然后将该4个文件添加至工程。
5.将整个工程编译,会报错如下:
error: 'struct PortSettings' has no member named 'Timeout_Sec'
qextserialbase.cpp qextserialbase.h posix_qextserialport.cpp posix_qextserialport.h

Linux串口select编程

Linux串口select编程

Linux下串口程序开发串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。

常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。

它的全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"该标准规定采用一个25个脚的DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。

传输距离在码元畸变小于4%的情况下,传输电缆长度应为50英尺。

在linux文件中,所有的设备文件一般都位于/dev下,其中串口一、串口二分别对应的设备名依次为“/dev/ttyS0”、“/dev/ttyS1”,可以查看在/dev下的文件以确认。

在linux下面对于串口的读写就可以通过简单的read、write函数来完成,所不同的是只是需要对串口的其他参数另坐配置。

1.串口编程需要用到的头文件#include <stdio.h> // 标准输入输出定义#include <stdlib.h>#include <fcntl.h> // 文件控制定义,主要完成串口通信中对文件的读写操作#include <unistd.h> // linux标准函数定义#include <sys/ioctl.h>#include <termios.h> // POSIX终端控制定义#include <sys/time.h>#include <sys/types.h>2.串口终端函数2.1打开串口设备int fd;char *device = "/dev/tts/0"; // 设备路径,初始使用UART0for(t=1;t<argc;t++) // 获取程序入口时输入的参数{if(!strcmp(argv[t],"-d") && (argc > (t+1))){device = argv[t+1];}}if(!strcmp(device,"/dev/tts/1")) // 不允许使用UART1,因为它已和PC相连。

linux 读取串口数据方法

linux 读取串口数据方法

linux 读取串口数据方法【原创实用版2篇】目录(篇1)一、Linux 读取串口数据的方法概述二、使用 C 语言读取串口数据三、使用 Qt 库读取串口数据四、使用 Python 读取串口数据五、总结正文(篇1)一、Linux 读取串口数据的方法概述在 Linux 系统中,串口是一种常用的设备接口,可以用于接收和发送数据。

Linux 提供了多种方法来读取和操作串口数据。

本文将介绍几种常见的方法,包括使用 C 语言、Qt 库和 Python 语言来读取串口数据。

二、使用 C 语言读取串口数据1.打开串口在 C 语言中,打开串口需要使用 fcntl 函数。

首先,需要包含头文件<fcntl.h>和<termios.h>。

然后,使用以下代码打开串口:```cint fd = open("/dev/ttyS0", O_RDWR);if (fd < 0) {perror("Can"t Open Serial Port");return -1;}```2.设置串口速度打开串口成功后,需要设置串口的波特率、数据位、校验位和停止位等参数。

可以使用以下代码设置串口速度:```cstruct termios tty;if (tcgetattr(fd, &tty)!= 0) {perror("Can"t Get Serial Port Attributes");return -1;}tty.c_cflag &= ~PARENB; // 清除奇偶校验位tty.c_cflag &= ~CSTOPB; // 使用一个停止位tty.c_cflag |= CS8; // 8 位数据位tty.c_cflag &= ~CRTSCTS; // 禁用硬件流控制tty.c_cflag |= CREAD | CLOCAL; // 使能读和忽略 modem 控制线if (tcsetattr(fd, TCSANOW, &tty)!= 0) {perror("Can"t Set Serial Port Attributes");return -1;}```3.读取串口数据使用以下代码读取串口数据:char buf[64];int len = read(fd, buf, sizeof(buf));if (len < 0) {perror("Can"t Read from Serial Port");return -1;}printf("Read data: %s", buf);```三、使用 Qt 库读取串口数据在 Qt 中,可以使用 QSerialPort 类来读取串口数据。

linux串口收发程序

linux串口收发程序

下面简单介绍了,在REDHAT9操作系统下的使用终端接收发送串口数据recive程序的使用,它通过串口接收其它计算机传送到本地计算机的数据,程序稳定可靠2.源代码:接收串口程序recive.c的源码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <errno.h>#include <string.h>#define TRUE 1//初始化串口选项:void setTermios(struct termios * pNewtio, int uBaudRate){bzero(pNewtio, sizeof(struct termios)); /* clear struct for new port settings *///8N1pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;pNewtio->c_iflag = IGNPAR;pNewtio->c_oflag = 0;pNewtio->c_lflag = 0; //non ICANON/*initialize all control charactersdefault values can be found in /usr/include/termios.h, andare given in the comments, but we don't need them here*/pNewtio->c_cc[VINTR] = 0; /* Ctrl-c */pNewtio->c_cc[VQUIT] = 0; /* Ctrl-\ */pNewtio->c_cc[VERASE] = 0; /* del */pNewtio->c_cc[VKILL] = 0; /* @ */pNewtio->c_cc[VEOF] = 4; /* Ctrl-d */pNewtio->c_cc[VTIME] = 5; /* inter-character timer, timeout VTIME*0.1 */ pNewtio->c_cc[VMIN] = 0; /* blocking read until VMIN character arrives */ pNewtio->c_cc[VSWTC] = 0; /* '\0' */pNewtio->c_cc[VSTART] = 0; /* Ctrl-q */pNewtio->c_cc[VSTOP] = 0; /* Ctrl-s */pNewtio->c_cc[VSUSP] = 0; /* Ctrl-z */pNewtio->c_cc[VEOL] = 0; /* '\0' */pNewtio->c_cc[VREPRINT] = 0; /* Ctrl-r */pNewtio->c_cc[VDISCARD] = 0; /* Ctrl-u */pNewtio->c_cc[VWERASE] = 0; /* Ctrl-w */pNewtio->c_cc[VLNEXT] = 0; /* Ctrl-v */pNewtio->c_cc[VEOL2] = 0; /* '\0' */}#define BUFSIZE 512int main(int argc, char **argv){int fd;int nread;int input;int *p=&input;//char buff[BUFSIZE];char buff[1024];struct termios oldtio, newtio;struct timeval tv;char *dev ="/dev/ttyS0";fd_set rfds;if ((fd = open(dev, O_RDWR | O_NOCTTY))<0){printf("err: can't open serial port!\n");return -1;}tcgetattr(fd, &oldtio); /* save current serial port settings */setTermios(&newtio, B9600);tcflush(fd, TCIFLUSH);tcsetattr(fd, TCSANOW, &newtio);//printf("Please input an integer.");//scanf("%d",&input);//*p=input;//printf("The integer you input is %d\n",*p);//printf("The integer you input is %d\n",&input); _sec=30;_usec=0;while (TRUE){printf("wait...\n");FD_ZERO(&rfds);FD_SET(fd, &rfds);if (select(1+fd, &rfds, NULL, NULL, &tv)>0) {printf("wait...\n");if (FD_ISSET(fd, &rfds)){//nread=read(fd, buff, BUFSIZE);nread=read(fd, buff ,1024);printf("readlength=%d\n", nread);//buff[nread]='\0';//printf("%s\n", buff);// buff='\0';printf("date=%d\n",buff);//printf("%d\n",fd);printf("%d\n", buff[1]);printf("%d\n", buff[2]);printf("%d\n", buff[3]);printf("%d\n", buff[4]);printf("%d\n", buff[5]);printf("%d\n", buff[6]);printf("%d\n", buff[7]);printf("%d\n", buff[8]);printf("%d\n", buff[9]);printf("%d\n", buff[10]);printf("%d\n", buff[11]);printf("%d\n", buff[12]);printf("%d\n", buff[13]);printf("%d\n", buff[14]);printf("%d\n", buff[15]);printf("%d\n", buff[16]);printf("%d\n", buff[17]);printf("%d\n", buff[18]);printf("%d\n", buff[19]);//printf("%d\n", buff[20]);//printf("%d\n", buff[21]);//printf("%d\n", buff[22]);//printf("%d\n", buff[23]);//printf("%d\n", buff[24]);//printf("%d\n", buff[25]);//printf("%d\n", buff[26]);//printf("%d\n", buff[27]);//printf("%d\n", buff[28]);//printf("%d\n", buff[29]);//printf("%d\n", buff[30]);//printf("%d\n", buff[31]);//printf("%d\n", buff[32]);//printf("%d\n", buff[1]);//printf("%d\n", buff[2]);//printf("%d\n", buff[3]);//printf("%d\n", buff[4]);//printf("%d\n", buff[5]);//printf("%d\n", buff[6]);//printf("%d\n", buff[7]);//printf("%d\n", buff[8]);//printf("%d\n", buff[9]);//printf("%d\n", buff[10]);//printf("%d\n", buff[32]);//printf("%d\n", buff[12]);//printf("%d\n", buff[13]);//printf("%d\n", buff[14]);//printf("%d\n", buff[15]);//printf("%d\n", buff[16]);}}}tcsetattr(fd, TCSANOW, &oldtio); close(fd);}串口发送程序send.c的源码#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <errno.h>#include <string.h>//初始化串口选项:void setTermios(struct termios * pNewtio, int uBaudRate){bzero(pNewtio, sizeof(struct termios)); /* clear struct for new port settings */ //8N1pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;pNewtio->c_iflag = IGNPAR;pNewtio->c_oflag = 0;pNewtio->c_lflag = 0; //non ICANON/*initialize all control charactersdefault values can be found in /usr/include/termios.h, andare given in the comments, but we don't need them here*/pNewtio->c_cc[VINTR] = 0; /* Ctrl-c */pNewtio->c_cc[VQUIT] = 0; /* Ctrl-\ */pNewtio->c_cc[VERASE] = 0; /* del */pNewtio->c_cc[VKILL] = 0; /* @ */pNewtio->c_cc[VEOF] = 4; /* Ctrl-d */pNewtio->c_cc[VTIME] = 5; /* inter-character timer, timeout VTIME*0.1 */ pNewtio->c_cc[VMIN] = 0; /* blocking read until VMIN character arrives */ pNewtio->c_cc[VSWTC] = 0; /* '\0' */pNewtio->c_cc[VSTART] = 0; /* Ctrl-q */pNewtio->c_cc[VSTOP] = 0; /* Ctrl-s */pNewtio->c_cc[VSUSP] = 0; /* Ctrl-z */pNewtio->c_cc[VEOL] = 0; /* '\0' */pNewtio->c_cc[VREPRINT] = 0; /* Ctrl-r */pNewtio->c_cc[VDISCARD] = 0; /* Ctrl-u */pNewtio->c_cc[VWERASE] = 0; /* Ctrl-w */pNewtio->c_cc[VLNEXT] = 0; /* Ctrl-v */pNewtio->c_cc[VEOL2] = 0; /* '\0' */}int main(int argc, char **argv){int fd;int input;int *p=&input;int nCount, nTotal, i;struct termios oldtio, newtio;char *dev ="/dev/ttyS0";//if ((argc!=3) || (sscanf(argv[1], "%d", &nTotal) != 1))//{//printf("err: need tow arg =%d!\n", argc );//return -1;//}//sscanf(argv[1], "%d", &nTotal)//{//printf("send date!\n", argc );//return -1;//}if ((fd = open(dev, O_RDWR | O_NOCTTY))<0){printf("err: can't open serial port!\n");return -1;}while (1) //循环读取数据{tcgetattr(fd, &oldtio); /* save current serial port settings */ setTermios(&newtio, B9600);tcflush(fd, TCIFLUSH);tcsetattr(fd, TCSANOW, &newtio);//for (i=0; i<nTotal; i++)//{//nCount=write(fd, argv[2], s]trlen(argv[2]));//argv[]={010*********d5ca};printf("Please input an integer.");scanf("%d",&input);*p=input;//nCount=write(fd,argv[p],strlen(argv[]));printf("The integer you input is %d\n",*p);printf("The integer you input is %d\n",&input);nCount=write(fd,"010*********d5ca/r",512);nCount=write(fd,p,1024);nCount=write(fd,&input,1024);printf("send date *p");printf("send date input");printf("send date 010*********d5ca\n"); //sleep(1);}tcsetattr(fd, TCSANOW, &oldtio); close(fd);return 0;}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

linux下串口编程简单实例1、Linux中的串口设备文件存放于/dev目录下,其中串口一,串口二对应设备名依次为“/dev/ttyS0”、“/dev/ttyS1”。

在linux下操作串口与操作文件相同。

2、在使用串口之前必须设置相关配置,包括:波特率、数据位、校验位、停止位等。

串口设置由下面结构体实现:struct termios{tcflag_t c_iflag; /*input flags*/tcflag_t c_oflag; /*output flags*/tcflag_t c_cflag; /*control flags*/tcflag_t c_lflag; /*local flags*/cc_t c_cc[NCCS]; /*control characters*/};该结构中c_cflag最为重要,可设置波特率、数据位、校验位、停止位。

在设置波特率时需在数字前加上‘B’,如B9600、B19200。

使用其需通过“与”“或”操作方式。

常用的串口控制函数:Tcgetattr 取属性(termios结构)Tcsetattr 设置属性(termios结构)cfgetispeed 得到输入速度Cfgetospeed 得到输出速度Cfsetispeed 设置输入速度Cfsetospeed 设置输出速度tcflush 刷清未决输入和/或输出3、串口的配置(1) 保存原先串口配置使用tcgetattr(fd,&oldtio)函数:struct termios newtio,oldtio;tcgetattr(fd,&oldtio);(2) 激活选项有CLOCAL和CREAD,用于本地连接和接收使能。

newtio.c_cflag | = CLOCAL | CREAD;(3) 设置波特率,使用函数cfsetispeed、cfsetospeedcfsetispeed(&newtio, B115200);cfsetospeed(&newtio, B115200);(4) 设置数据位,需使用掩码设置。

newtio.c_cflag &= ~CSIZE;newtio.c_cflag |= CS8;(5) 设置奇偶校验位,使用c_cflag和c_iflag。

设置奇校验:newtio.c_cflag |= PARENB;newtio.c_cflag |= PARODD;newtio.c_iflag |= (INPCK | ISTRIP);设置偶校验:newtio.c_iflag |= (INPCK | ISTRIP);newtio.c_cflag |= PARENB;newtio.c_cflag &= ~PARODD;(6) 设置停止位,通过激活c_cflag中的CSTOPB实现。

若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB。

newtio.c_cflag &= ~CSTOPB;(7) 设置最少字符和等待时间,对于接收字符和等待时间没有特别要求时,可设为0。

newtio.c_cc[VTIME] = 0;newtio.c_cc[VMIN] = 0;(8) 处理要写入的引用对象tcflush函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送)。

int tcflush(int filedes, int queue )queue数应当是下列三个常数之一:•TCIFLUSH 刷清输入队列。

•TCOFLUSH 刷清输出队列。

•TCIOFLUSH 刷清输入、输出队列。

如:tcflush(fd,TCIFLUSH);(9) 激活配置。

在完成配置后,需激活配置使其生效。

使用tsettattr()函数。

原型:int tcgetattr(int filedes, struct termios * termptr);int tcsetattr(int filedes, int opt, const struct termios * termptr);tcsetattr的参数opt使我们可以指定在什么时候新的终端属性才起作用。

opt可以指定为下列常数中的一个:•TCSANOW 更改立即发生。

•TCSADRAIN 发送了所有输出后更改才发生。

若更改输出参数则应使用此选择项。

•TCSAFLUSH 发送了所有输出后更改才发生。

更进一步,在更改发生时未读的所有输入数据都被删除(刷清)使用如:tcsetattr(fd,TCSANOW,&newtio)4、在配置完串口的相关属性后,就可对串口进行打开,读写操作了。

其使用方式与文件操作一样,区别在于串口是一个终端设备。

(1) 打开串口fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);Open函数中除普通参数外,另有两个参数O_NOCTTY和O_NDELAY。

O_NOCTTY: 通知linux系统,这个程序不会成为这个端口的控制终端。

O_NDELAY: 通知linux系统不关心DCD信号线所处的状态(端口的另一端是否激活或者停止)。

(2) 恢复串口的状态为阻塞状态,用于等待串口数据的读入。

用fcntl函数:fcntl(fd, F_SETFL, 0);(3) 接着,测试打开的文件描述府是否引用一个终端设备,以进一步确认串口是否正确打开。

isatty(STDIN_FILENO);(4) 串口的读写与普通文件一样,使用read,write函数。

read(fd,buf,8);write(fd,buf,8);以下为一简单的程序实例:#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;}bzero( &newtio, sizeof( newtio ) );newtio.c_cflag |= 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;else if ( nStop == 2 )newtio.c_cflag |= CSTOPB;newtio.c_cc[VTIME] = 0;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"};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);}elseprintf("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);}elseprintf("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);}elseprintf("open ttyS2 .....\n");}if(fcntl(fd, F_SETFL, 0)<0)printf("fcntl failed!\n");elseprintf("fcntl=%d\n",fcntl(fd, F_SETFL,0));if(isatty(STDIN_FILENO)==0)printf("standard input is not a terminal device\n");elseprintf("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);nread=read(fd,buff,8);printf("nread=%d,%s\n",nread,buff); close(fd);return;}。

相关文档
最新文档