【Linux驱动】四、按键控制LED灯<POLL方式>
【Linux驱动】四、按键控制LED灯<POLL方式>
本文最后更新于333 天前,其中的信息可能已经过时,如有错误请发送邮件到273925452@qq.com
Avatar
只修改了第三节的按键程序button_test.c LED的程序是第二节的程序
测试环境:
VsCode(远程)+Ubuntu
IMX6ULL_PRO

POLL机制(闹钟)

POLL
POLL机制是Linux系统中用于实现I/O多路复用的一种方法,允许一个进程同时监控多个文件描述符的I/O状态。与select()相比,poll()没有文件描述符数量的限制,并且提供了更灵活的事件类型支持。POLL机制的核心在于poll()函数,它允许用户指定一个pollfd结构体数组来跟踪多个文件描述符的事件。POLL机制提供了一种非阻塞的方式监控多个I/O通道,适用于需要同时处理多个网络连接或设备的应用场景。

主要涉及的函数

poll() 函数

   #include <sys/poll.h>
   int poll(struct pollfd *fds, nfds_t nfds, int timeout);
poll() 函数
其中:
struct pollfd *fds 是一个指向pollfd结构体数组的指针,每个元素代表一个需要监控的文件描述符及其事件。
nfds_t nfds 是数组中元素的数量。
int timeout 是一个以毫秒为单位的超时值,如果在该时间内没有任何事件发生,则poll()将返回。

pollfd 结构体

pollfd结构体定义了每个文件描述符的监控信息:

struct pollfd {
    int   fd;         /* 文件描述符 */
    short events;     /* 要监控的事件掩码 */
    short revents;    /* 实际发生的事件掩码 */
};

监控的事件

events成员可以设置以下事件之一或组合:

events成员
– POLLIN:表示文件描述符可读。
– POLLPRI:紧急数据可读(如带外数据)。
– POLLOUT:表示文件描述符可写。
– POLLERR:错误发生。
– POLLHUP:挂起或终止。
– POLLNVAL:无效的请求描述符。
– POLLWRBAND:带外数据可写。
– POLLMSG:消息队列中有数据。

使用流程

events成员
1.初始化pollfd数组,设置每个pollfd的fd和events字段。
2.调用poll()函数,传入pollfd数组、数组长度和超时时间。
3.poll()函数阻塞直到至少有一个文件描述符准备就绪或超时。
4.检查pollfd数组中的revents字段,确定哪些文件描述符发生了事件。
5.根据事件类型采取相应的操作,如读取数据或写入数据。

程序

button_test.c


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <signal.h>

#define LED_DEV "/dev/led"
#define BUTTON_DEV "/dev/100ask_button0"




/*
 * ./button_test /dev/100ask_button0
 *
 */
int main(int argc, char **argv)
{
    int fd,fd1;
    char val;
    struct pollfd fds[2]; // fds数组用于注册要监控的事件,fds[0]监控fd上的读事件(POLLIN),fds[1]监控fd1上的写事件(POLLOUT)。
    int ret;
    char buf[2];
    const int timeout = 1000; // Wait for up to 1 second

     /* 1. 判断参数 */
    if (argc != 2) 
    {
        printf("Usage: %s <dev>\n", argv[0]);
        return -1;
    }

    /* 2. 打开文件key */
    fd = open(BUTTON_DEV, O_RDWR | O_NONBLOCK); //非阻塞(查询)
    if (fd == -1)
    {
        printf("can not open file %s\n", argv[1]);
        return -1;
    }

    /* 3. 读文件 */
    if (read(fd, &val, 1) != 1)
    {
        printf("read error %s\n", argv[1]);
        close(fd);
        return -1;
    }
    printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    fd1 = open(LED_DEV, O_RDWR);
    if (fd1 == -1)
    {
        perror("can not open LED device");
        close(fd);
        return -1;
    }
    printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    /* Setup poll descriptors */
    fds[0].fd = fd;
    fds[0].events = POLLIN;
    fds[1].fd = fd1;
    fds[1].events = POLLOUT;

    /* Main loop */
    buf[0] = 0;
    while (1)
    {
        if(poll(fds, 2, -1) == -1)
        {
            perror("poll error");
            break;
        }
        /* Check if button has data available */
        if (fds[0].revents & POLLIN) // fds[0]上的读事件发生,说明按钮有数据可用
        {
            if (read(fd, &val, 1) != 1) // 读取按钮的状态到val变量中
            {
                perror("read error");
                break;
            }

            /* Control LED based on button state */
            if (val == 0)
            {
                buf[1] = 0;
                ret = write(fd1, buf, 2);
            }
            else if (val == 1)
            {
                buf[1] = 1;
                ret = write(fd1, buf, 2);
            }
            else
            {
                fprintf(stderr, "Unknown button state: %c\n", val);
            }
            if (ret != 2)
            {
                perror("write error");
                break;
            }

            printf("get button : %d\n", val);
            usleep(timeout); // Sleep for 500 milliseconds
        }
    }

    /* 清理 */
    close(fd);
    close(fd1);

    return 0;
}


上机

安装LED,KEY驱动

执行程序

./button_test /dev/100ask_button0

测试成功

按着按键控制灯亮,松开灯灭

修改程序控制亮灭方式

按下亮,在按一下灭


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <poll.h>
#include <signal.h>

#define LED_DEV "/dev/led"
#define BUTTON_DEV "/dev/100ask_button0"




/*
 * ./button_test /dev/100ask_button0
 *
 */
int main(int argc, char **argv)
{
    int fd,fd1;
    char val;
    struct pollfd fds[2]; // fds数组用于注册要监控的事件,fds[0]监控fd上的读事件(POLLIN),fds[1]监控fd1上的写事件(POLLOUT)。
    int ret;
    char buf[2];
    const int timeout = 100000; 
    int led_state = 0;

    /* 1. 判断参数 */
    if (argc != 2) 
    {
        printf("Usage: %s <dev>\n", argv[0]);
        return -1;
    }

    /* 2. 打开文件key */
    fd = open(BUTTON_DEV, O_RDWR | O_NONBLOCK); //非阻塞(查询)
    if (fd == -1)
    {
        printf("can not open file %s\n", argv[1]);
        return -1;
    }

    /* 3. 读文件 */
    if (read(fd, &val, 1) != 1)
    {
        printf("read error %s\n", argv[1]);
        close(fd);
        return -1;
    }
    printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    fd1 = open(LED_DEV, O_RDWR);
    if (fd1 == -1)
    {
        perror("can not open LED device");
        close(fd);
        return -1;
    }
    printf("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    /* Setup poll descriptors */
    fds[0].fd = fd;
    fds[0].events = POLLIN;
    fds[1].fd = fd1;
    fds[1].events = POLLOUT;

    /* Main loop */
    buf[0] = 0;
    while (1)
    {
        if(poll(fds, 2, -1) == -1)
        {
            perror("poll error");
            break;
        }
        /* Check if button has data available */
        if (fds[0].revents & POLLIN) // fds[0]上的读事件发生,说明按钮有数据可用
        {
            if (read(fd, &val, 1) != 1) // 读取按钮的状态到val变量中
            {
                perror("read error");
                break;
            }

            /* Control LED based on button state */
            if (val == 0)
            {
                led_state ^= 0x01;
            }
                if (led_state == 0)
                {
                    buf[1] = 0;
                    ret = write(fd1, buf, 2);
                }
                else if (led_state == 1)
                {
                    buf[1] = 1;
                    ret = write(fd1, buf, 2);
                }
                else
                {
                    fprintf(stderr, "Unknown button state: %c\n", val);
                }
            if (ret != 2)
            {
                perror("write error");
                break;
            }

            printf("get button : %d\n", val);
            usleep(timeout); // Sleep for 500 milliseconds
        }
    }

    /* 清理 */
    close(fd);
    close(fd1);

    return 0;
}


💡商业转载请联系作者获得授权,非商业转载请注明出处。
协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)。
使用这些免费资源的时候应遵守版权意识,切勿非法利用,售卖,尊重原创内容知识产权。未经允许严禁转载。

评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇