Ehome:智能家居之led控制系统

Ehome:智能家居之led控制系统_第1张图片

3. LED的控制
3.1 LED驱动程序
     实质就是一个linux字符设备驱动
     
     $:' cd project
     $:' mkdir drivers
     $:' cd drivers
     $:' mkdir leds
     $:' cd leds
        // ---> madir drivers/leds -p
     $:' vi led_drv.c
     $:' vi Makefile
     $:' make
     $:' mkdir ../../rootfs/home/drivers
     $:' cp leds_drv.ko  ../../rootfs/home/drivers/
     $:' vi test.c
        // 验证程序。使用arm-...-gcc编译。
     
     编译test.c,测试驱动程序是否好用
     
3.2 编写LED的控制应用程序
      有两种方式
      3.2.1 简单的方式 - 槽函数方式1
           当点击亮灯按钮时,完成该信号的槽函数
           在槽函数中
           fd = open("/dev/leds", ...)
           ioctl(fd, CMD_LED_ON, &i); // i 是第几盏灯
           close (fd);
           修改图片
           
           再次点击时灭灯
           fd = open("/dev/leds", ...)
           ioctl(fd, CMD_LED_OFF, &i);
           close (fd);
           修改图片 
           GUI界面程序一定部署到开发板才能有效果
           
      3.2.2 复杂方式 - 槽函数方式2
           希望GUI界面程序不管是运行在PC
           或者运行在开发板,都能控制开发板的LED状态
           
           'Client (GUI 开发板/PC)'       'Server (UDP 运行在开发板)'
            点击按钮发送命令LED_ON         接收命令,根据命令open设备 ioctl亮灯
            sendto (sd, cmd);

        公共头文件:project/include/ehome.h
        
         1)界面客户端程序 client
           $:' mkdir gui_client
           $:' cd gui_client
           $:' qtcreator
              建立工程 完成界面编程
              先将mainwindow窗口的大小调整为 1024*600
              添加按钮 - 转到槽
                  槽函数中给UDP服务器发送命令
              ---> 3.2.1
        2)服务器程序  server
           $:' cd project
           $:' mkdir server
           $:' cd server
           $:' vi server.c
              // udp 创建socket,接收客户端发送的命令,解析命令调用不同的硬件操作
              recvfrom(cmd) 
              if(cmd == LED_ON)
                 open("/dev/leds",...)
                 ioctl(fd, LED_ON, 0)  
          $:' vi leds.c
            // 进一步解析命令:操作哪盏灯,如何操作,调用对应灯的对应操作函数
          $:' vi leds_hw.c
            // hw 代表硬件 hardware,操作硬件
                      open
                      ioctl
                      close
          $:' arm-cor.....gcc server.c -o server
          $:' cp server rootfs/home/bin/
    #:' insmod /home/drivers/leds_drv.ko
    #:' source /home/etc/profile
    #:' /home/bin/server &
    #:' /home/bin/client

              启动server
              启动client
              点击按钮实验是否亮灯
    
   注意编程过程中的调试技巧
#define DEBUG
#ifdef DEBUG
    /*##表示如果可变参数被忽略或为空,将使预处理器( preprocessor )去除掉它前面的那个逗号。*/
    #define pr_debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
    #define pr_debug(fmt, ...) 
#endif



   BUG的调试,顺着数据流分析该调用的函数是否调用到。


Ehome:智能家居之led控制系统_第2张图片


/* leds_drv.c 驱动源代码 */

#include 
#include 
#include 

#include 
#include 
#include 
#include 

MODULE_LICENSE("GPL");

#define LED_ON  0x100001
#define LED_OFF 0x100002

struct led_desc 
{
    char *name;
    int gpio;
};

struct led_desc leds[]=
{
    {"led_bedroom", PAD_GPIO_C+12},
    {"led_saloon", PAD_GPIO_C+7},
    {"led_kitchen", PAD_GPIO_C+11},
    {"led_restroom", PAD_GPIO_B+26},
};

long leds_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
    //1.定义内核缓冲区
    int kindex = 0;
    int ret = 0;
    int status = 0;

    //2.拷贝用户缓冲区到内核
    ret = copy_from_user(&kindex, (int *)arg, 4);

    //3.解析命令,操作硬件
    switch(cmd) {
        case LED_ON:
            status = 0;
            break;
        case LED_OFF:
            status = 1;
            break;
        default:
            return -EINVAL;
    }
    if(kindex>= 0 && kindex <4)
    {
        gpio_direction_output(leds[kindex].gpio, status);
    }
    return 0;
}


struct file_operations leds_fops =
{
    .owner = THIS_MODULE,
    .unlocked_ioctl = leds_ioctl,
};

struct miscdevice leds_misc =
{
    .minor = MISC_DYNAMIC_MINOR,//自动分配次设备号
    .name  = "leds", //设备文件名称
    .fops = &leds_fops,
};
int __init leds_drv_init(void)
{
    int i = 0;

    for(; i


你可能感兴趣的:(Embedded,Product)