[serial]基于select/poll/epoll的串口操作-程序员宅基地

技术标签: epoll  raspberry pi  

转自:http://www.cnblogs.com/darryo/p/selectpollepoll-on-serial-port.html

In this article, I will use three asynchronous conferencing--select, poll and epoll on serial port to transmit data between PC and Raspberry pi.


Outline

  1. Character device file of serial port
  2. Naive serial communication
  3. Asynchronous conferencing
  4. Select
  5. Poll
  6. Epoll

Character device of serial port

My device is Raspberry pi with debian system and PC with ubuntu12.04 system.

And I have used a USB-TTL to link the these device.

The character device files on the two device is :

/dev/ttyUSB0 #Ubuntu

/dev/ttyAMA0 #Debian Raspberry pi

These two files are what we must use to achieve the lab.

But there is a little trap of /dev/ttyAMA0.

By default, Raspberry pi uses /dev/ttyAMA0 as a output of serial. Therefor we could use minicom or putty to control our device. However, we have to modify the default function of serial, since we will use our own method to use serial port.

So we should modify two files:

/boot/comdline.txt

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 rootfstype=ext4 elevator=deadline rootwait console=tty1 root=/dev/mmcblk0p2

Delete console=ttyAMA0,115200

/etc/inittab

T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

Comment the line above.


Now, start to code:

Naive version

The naive serial port communication version

Open the device, set the baud rate, and set parity

#include     <stdio.h>      /*标准输入输出定义*/
#include     <string.h>
#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>      /*错误号定义*/
#define FALSE 0
#define TRUE 1

void set_speed(int fd) {
    struct  termios Opt;
    tcgetattr(fd, &Opt);
    cfsetispeed(&Opt,B115200);
    cfsetospeed(&Opt,B115200);
    tcsetattr(fd,TCSANOW,&Opt);
    return;
}

void set_Parity(int fd) {
    struct termios options;
    tcgetattr(fd, &options);
    options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag  &= ~OPOST;   /*Output*/
    tcsetattr(fd,TCSANOW,&options);
    return;
}

int OpenSerial(char *Dev) {
    int fd = open( Dev, O_RDWR );         //| O_NOCTTY | O_NDELAY
    if (-1 == fd) { /*设置数据位数*/
        perror("Can't Open Serial Port");
        return -1;
    }
    else {
        set_speed(fd);
        set_Parity(fd);
        return fd;
    }

}

int main(){
    int fd; 
    ssize_t length;
    char buff[512];
    char *dev ="/dev/ttyAMA0";
    fd = OpenSerial(dev);
    for(;;){
        length = read(fd,buff,sizeof(buff));
        if(length > 0) {
            buff[length] = 0;
            printf("plain:%s\n",buff);
        }
    }
    close(fd);
    exit(0);
}

Select version

#include <sys/time.h>
#include <sys/types.h>
#include "serial/serial.h"

int main() {
    int fd;
    fd_set rfds;
    struct timeval tv;
    char buff[512];
    ssize_t length;
    fd = OpenSerial("/dev/ttyAMA0");
   
    for(;;) {
        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);

        //timeout = 5s
        tv.tv_sec = 5;
        tv.tv_usec = 0;
        //Wait for 5 seconds, then go
        int n;
        n = select(fd + 1, &rfds, NULL, NULL, &tv);
        //choose the target from set
        if(n > 0) {
            if (FD_ISSET(fd, &rfds)) {
                length = read(fd, &buff, sizeof(buff));
                buff[length] = 0;
                printf("select:%s\n", buff);
            }
        } else {
            printf("No data within 5 seconds.\n");
        }
    }
    return 0;
}

 

Poll version

#include <sys/poll.h>
#include "serial/serial.h"
int main(void) {
    struct pollfd fds[1];
    ssize_t length;
    char buff[512];
    fds[0].fd = OpenSerial("/dev/ttyAMA0");
    fds[0].events = POLLIN ;
    for(;;) {
        int n;
        n = poll( fds, 1, 5000);
        //got data, and look up which fd has data, but we just have 1
        if(n > 0) {
        //if( fds[0].revents & POLLIN ) {
     
            length = read(fds[0].fd, buff, sizeof(buff) );
            buff[length] = 0;
            printf("poll:%s\n",buff);

        } else {
            printf("No data within 5 seconds.\n");
        }
    }
} 

 

Epoll version

#include <sys/epoll.h>
#include "serial/serial.h"

#define MAXEVENTS 64

int main(void){
    int fd;
    int efd;
    struct epoll_event event;
    struct epoll_event *events;
    int length;
    char buff[512];
    fd = OpenSerial("/dev/ttyAMA0");
    efd = epoll_create1 (0);//initial is 0

    event.data.fd = fd;
    event.events = EPOLLIN | EPOLLET;

    epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
    /* Buffer where events are returned */
    events = calloc (MAXEVENTS, sizeof event);

    /* The event loop */
    for(;;) {
        int n;
        n = epoll_wait (efd, events, MAXEVENTS, 5000);
        if(n > 0) {
            length = read(events[0].data.fd, buff, sizeof(buff));
        
            if(length > 0) {
                buff[length] = 0;
                printf("epoll:%s\n", buff);
            }
        } else {
            printf("No data whthin 5 seconds.\n");
        }
    }
    free (events);
    close (fd);
    return 0;
}

 

转载于:https://www.cnblogs.com/aaronLinux/p/9055016.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/anxuan3201/article/details/101119925

智能推荐

源代码图纸文档防泄密场景方案分析-程序员宅基地

文章浏览阅读161次,点赞5次,收藏3次。财务数据、员工信息、工资信息、客户和业务数据等被员工非法获取、外泄

React学习记录-程序员宅基地

文章浏览阅读936次,点赞22次,收藏26次。React核心基础

Linux查磁盘大小命令,linux系统查看磁盘空间的命令是什么-程序员宅基地

文章浏览阅读2k次。linux系统查看磁盘空间的命令是【df -hl】,该命令可以查看磁盘剩余空间大小。如果要查看每个根路径的分区大小,可以使用【df -h】命令。df命令以磁盘分区为单位查看文件系统。本文操作环境:red hat enterprise linux 6.1系统、thinkpad t480电脑。(学习视频分享:linux视频教程)Linux 查看磁盘空间可以使用 df 和 du 命令。df命令df 以磁..._df -hl

Office & delphi_range[char(96 + acolumn) + inttostr(65536)].end[xl-程序员宅基地

文章浏览阅读923次。uses ComObj;var ExcelApp: OleVariant;implementationprocedure TForm1.Button1Click(Sender: TObject);const // SheetType xlChart = -4109; xlWorksheet = -4167; // WBATemplate xlWBATWorksheet = -4167_range[char(96 + acolumn) + inttostr(65536)].end[xlup]

若依 quartz 定时任务中 service mapper无法注入解决办法_ruoyi-quartz无法引入ruoyi-admin的service-程序员宅基地

文章浏览阅读2.3k次。上图为任务代码,在任务具体执行的方法中使用,一定要写在方法内使用SpringContextUtil.getBean()方法实例化Spring service类下边是ruoyi-quartz模块中util/SpringContextUtil.java(已改写)import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.s..._ruoyi-quartz无法引入ruoyi-admin的service

CentOS7配置yum源-程序员宅基地

文章浏览阅读2w次,点赞10次,收藏77次。yum,全称“Yellow dog Updater, Modified”,是一个专门为了解决包的依赖关系而存在的软件包管理器。可以这么说,yum 是改进型的 RPM 软件管理器,它很好的解决了 RPM 所面临的软件包依赖问题。yum 在服务器端存有所有的 RPM 包,并将各个包之间的依赖关系记录在文件中,当管理员使用 yum 安装 RPM 包时,yum 会先从服务器端下载包的依赖性文件,通过分析此文件从服务器端一次性下载所有相关的 RPM 包并进行安装。_centos7配置yum源

随便推点

【方位估计】基于MUSIC算法、加权MUSIC算法和ROOT-MUSIC算法方位估计附Matlab代码-程序员宅基地

文章浏览阅读921次,点赞17次,收藏19次。方位估计是信号处理领域中一个重要的问题,它涉及到了信号的方向和角度的估计。在无线通信、雷达、声呐等领域,方位估计都有着重要的应用。本文将介绍三种常用的方位估计算法:MUSIC算法、加权MUSIC算法和ROOT-MUSIC算法。首先我们来介绍MUSIC算法。MUSIC算法是一种基于信号子空间的方法,它利用信号子空间的特性来实现方位估计。

DZMFullPage - 前端分页动画插件,兼容IE9+,支持Vue-程序员宅基地

文章浏览阅读73次。分页指定DOM页页页页页页导入插件。

【图像分割】基于Crow搜索优化模糊聚类算法的医学图像分割研究附matlab代码-程序员宅基地

文章浏览阅读1.1k次,点赞30次,收藏24次。图像分割是医学图像分析中的关键步骤,它可以将图像中的不同组织或结构区分开来。模糊聚类算法是一种常用的图像分割方法,但其聚类中心的选择对分割结果有很大的影响。本文提出了一种基于 Crow 搜索优化(CSO)算法的模糊聚类算法,用于医学图像分割。CSO 是一种新型的群智能优化算法,具有收敛速度快、鲁棒性强等优点。本文将 CSO 应用于模糊聚类算法的聚类中心优化,以提高分割精度。

Android开发-Android常用组件-TextView文本框-程序员宅基地

文章浏览阅读1k次。04 常用组件4.1 TextViewTextView (文本框),用于显示文本的一个控件。文本的字体尺寸单位为sp :sp: scaled pixels(放大像素). 主要用于字体显示。文本常用属性:属性名作用id为TextView设置一个组件id,根据id,我们可以在Java代码中通过findViewById()的方法获取到该..._

STM32单片机示例:多个定时器同步触发启动_stm32 定时器同步-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏14次。多个定时器同步触发启动是一种比较实用的功能,这里将对此做个示例说明。_stm32 定时器同步

android launcher分析和修改10,Android Launcher分析和修改9——Launcher启动APP流程(转载)...-程序员宅基地

文章浏览阅读348次。出处 : http://www.cnblogs.com/mythou/p/3187881.html本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务。客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题。没办法,只能看看是怎么回事。今天分析一下Launcher启动APP的过程。从用户点击到程序启动的流程,下面针对WorkSpa..._回调bubbletextview

推荐文章

热门文章

相关标签