美文网首页程序员
C编程实现键盘LED灯闪烁

C编程实现键盘LED灯闪烁

作者: 网路元素 | 来源:发表于2019-10-11 07:24 被阅读0次

在《Shell脚本实现键盘LED灯闪烁》一文中,我们已感受到了控制的乐趣,一步步向硬件逼近,这次我们在Linux下使用C语言进行系统调用来实现该功能。这里面会涉及到应用层定时器和ioctl系统调用来控制键盘LED灯状态。

关于应用层定时器需要涉及到信号机制,其包含有alarm闹钟和timer定时器两种,其与信号机制分别说明如下(这两种均是自动循环的,即不需要处理函数里再设置一遍定时器超时设置):

1.alarm

运行man alarm命令后有关于该函数的使用说明,其函数原型如下:

#include <unistd.h>
unsigned int alarm(unsigned int seconds);

当设定的时间到了后会发出SIGALRM信号,需要对应的信号处理函数配套处理。

2.timer

运行man setitimer命令后有相关说明,本次会用到的函数原型如下:

#include <sys/timer.h>
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

其中which是设置的定时器类型,分别对应如下:

ITIMER_REAL:实时定时器,发SIGALRM信号;
ITIMER_VIRTUAL:应用进程执行时间定时器,发SIGVTALRM信号;
ITIMER_PROF:应用进程执行和内核交互时间定时器,发SIGPROF信号。

从上面可以看出,同一时间只能有3个定时器存在,分别对应3种类型。那么上面的信号要如何处理呢?执行man signal命令有相关的函数原型如下:

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

这signal函数除了与定时器配套外,还可以捕获其他信号,执行man 7 signal命令可以查看到。 

好了,关于定时器部分就说到这。而关于键盘LED灯控制,我们需要用到TTY设备的ioctl系统调用函数,该函数是标准的字符设备接口(可以不实现),其接口原型(执行man ioctl)如下:

#include <sys/ioctl.h>
int ioctl(int d, int request, ...);

其中d为相应的设备描述符号,request是命令码,…是命令码对应的参数值。对于Keyboard的LED,我们使用到KDSETLED这个命令码,而其对应的设备是/dev/console,这里的d就对应open这个设备的返回值,而…对应传入的值,恢复未定义状态是0xff,而键盘右上角3个灯(Number lock,Caps Lock,Scroll Lock)全亮对应0x07。 

下面是实现C编程控制PC键盘LED灯闪烁的源码:

#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <linux/kd.h>
#include <sys/ioctl.h>

void slam_alarm_handler(int a)
{
        int tty = open("/dev/console", 0), led;
        if(tty<3)
        {
                perror("open:");
                exit(0);
        }

        led = 0x07;
        if(ioctl(tty,KDSETLED,led)>0)
                perror("ioctl led on:");

        sleep(1);

        led = 0xff;
        if(ioctl(tty,KDSETLED,led)>0)
                perror("ioctl led off:");

        close(tty);
}

int main(void)
{
        /* The struct itimerval
         * it_interval:means interval everytime after first time
         * it_value:means the first time interval
         * The ITIMER_REAL timer come with SIGALRM signal
         */

        struct itimerval t;
        t.it_interval.tv_usec = 0;
        t.it_interval.tv_sec = 2;
        t.it_value.tv_usec = 0;
        t.it_value.tv_sec = 2;

        if(setitimer(ITIMER_REAL, &t, NULL) < 0)
        {
                printf("Setitimer failed.\n");
                exit(-1);
        }

        signal(SIGALRM, slam_alarm_handler);

        while(1)
        {
                sleep(2);
        }

        exit(0);
}

相应的Makefile文件内容如下:

all:
        gcc -o timer_keyboard_led_flash timer_keyboard_led_flash.c

clean:
        rm -rf timer_keyboard_led_flash

对应的源码文件目录树如下: 

/home/xinu/xinu/c_cpp/timer_keyboard_led_flash/
├── Makefile
└── timer_keyboard_led_flash.c 

编译生成的文件后,执行时需要root用户权限,在ubuntu下需sudo ./timer_keyboard_led_flash命令去执行。 

参考网址: 

http://www.cppblog.com/jerryma/archive/2012/01/31/164704.html
http://jpkc.zju.edu.cn/k/505/pdf/nihe4.pdf
http://blog.csdn.net/fanwenbo/article/details/2645362
http://falldog7.blogspot.com/2008/05/linux-timer.html
http://ubuntuforums.org/showthread.php?t=1372521

相关文章

  • C编程实现键盘LED灯闪烁方法2

    在《C编程实现键盘LED灯闪烁》一文中使用了定时器和ioctl的方式实现键盘LED灯周期性闪烁,而键盘本身作为一个...

  • C编程实现键盘LED灯闪烁

    在《Shell脚本实现键盘LED灯闪烁》一文中,我们已感受到了控制的乐趣,一步步向硬件逼近,这次我们在Linux下...

  • shell脚本实现键盘LED灯闪烁

    很幸运,在Ubuntu13.10的Terminal下发现了setleds命令,直接运行该命令后有如下输出: xin...

  • OSAL-led

    1、 LED灯设置 2、 LED灯闪烁 官方把代码写好了且开源了,大家有空可以看看(hal_led.c),学习一下...

  • 跪求单片机大佬

    [题]LED流水灯左循环点亮:用AT89C51单片机和C51语言实现8个LED灯的左循环依次流水点亮,两个LED灯...

  • PWM实现“流星雨”效果

    1、不同频率LED灯闪烁 接下来我们以下面LED灯的闪烁代码为例子,改变延时长短来看LED灯的效果 通过三个对比实...

  • stm32学习之路--点亮一个LED编码

    目标:使用库函数一个LED闪烁 main.c led.c led.h

  • 08 LED流水灯

    单片机STC89C52学习——07 LED闪烁 汇总:00 单片机STC89C52学习参考教程:普中科技 1 编程...

  • 07 LED闪烁

    单片机STC89C52学习——07 LED闪烁 汇总:00 单片机STC89C52学习参考教程:普中科技 1 编程...

  • Android Things之脉冲宽度调制(PWM)

    上一篇文章讲了Android Things之闪烁的LED灯,不明白的请查看http://www.jianshu.c...

网友评论

    本文标题:C编程实现键盘LED灯闪烁

    本文链接:https://www.haomeiwen.com/subject/pvalyctx.html