资讯详情

基于ARM的智能灯光控制系统总结(2-驱动开发)

本工程设计的硬件有:

(1)nanopi s2(linux nanopi2 3.4.39)及其连接的继电器,5v转3.3v使用模块、光感设备、声感设备linux-3.4.y-nanopi2-lollipop-mr1.zip内核开发字符驱动程序

(2)tiny6410(linux FriendlyARM 2.6.38)使用连接的继电器和红外传感器linux-2.6.38-20110325.tar.gz内核开发字符驱动程序

将相应的交叉编译器分别编译,然后移植到相应的开发板加载驱动(如:insmod mic_driver.ko,前面的自动加载驱动体验好用)

不同内核的gpio操作函数不同,见之前发布的相关信息gpio驱动发展经验。需要注意的是阅读io下拉电阻设置在高低电平的驱动下,以确保io口电平状态稳定,否则会有数据跳动。

一、 nanopi s2的相关驱动

1.1 光感设备驱动及测试程序

#include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/uaccess.h> #include <linux/list.h>  #include <linux/clk.h> #include <linux/io.h> #include <linux/gpio.h> #include <mach/platform.h> #include <mach/devices.h> #include <mach/soc.h>  #define DEVICE_NAME "4418_light"  //nanopi2s -s5p4418 #define LGPIO PAD_GPIO_C  11       //模块GPIO脚   static int light_read(struct file *file, char * buffer, size_t count, loff_t * ppos) {     unsigned tmp;        unsigned long err;               tmp = gpio_get_value(LGPIO);     printk("==%d==\n",tmp);     err = copy_to_user(buffer, &tmp, 1);       return 1; }   static struct file_operations dev_fops={     read:light_read, };  static struct miscdevice misc = {     .minor = MISC_DYNAMIC_MINOR,     .name = DEVICE_NAME,     .fops = &dev_fops, };  static int __init my_light_init(void) {     int ret;     gpio_direction_input(LGPIO);//设置io为输入  nxp_soc_gpio_set_io_pull_sel(LGPIO,0);//设置下拉电阻          ret = misc_register(&misc);     printk (DEVICE_NAME"\tinitialized\n");      return ret;  }  static void __exit my_light_exit(void) {     misc_deregister(&misc); }  module_init(my_light_init); module_exit(my_light_exit);  MODULE_LICENSE("GPL"); MODULE_AUTHOR("cumtzd"); 

其测试程序

#include     <stdio.h>       #include     <stdlib.h>      #include     <unistd.h>      #include     <sys/types.h>   #include     <sys/stat.h>    #include     <fcntl.h>       #include     <errno.h>   #define DEV_FILE "/dev/4418_light"  int main() {     int fd_dev=-1;     char dat;     printf("nanoPi driver Test\n");      fd_dev = open(DEV_FILE,O_RDWR);     if(fd_dev<0){         printf("open device err\n");         return 0;     }      while(1){         read(fd_dev,&dat,1);         printf("Light status [%d]\n",dat);         sleep(1);     }     return 0; }

1. 2 声学设备驱动及测试程序

#include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/moduleparam.h> #include <linux/slab.h> #include <linux/errno.h> #include <linux/ioctl.h> #include <linux/cdev.h> #include <linux/string.h> #include <linux/uaccess.h> #include <linux/list.h>  #include <linux/clk.h> #include <linux/io.h> #include <linux/gpio.h> #include <mach/platform.h> #include <mach/devices.h> #include <mach/soc.h>  #define DEVICE_NAME "4418_mic"  //nanopi2s -s5p4418 #define LGPIO PAD_GPIO_C  13        //模块GPIO脚   static int mic_read(struct file *file, char * buffer, size_t count, loff_t * ppos) {     unsigned tmp;        unsigned long err;               tmp = gpio_get_value(LGPIO);     printk("mic==%d==\n",tmp);     err = copy_to_user(buffer, &tmp, 1);       return 1; }   static struct file_operations dev_fops={     read:mic_read, };  static struct miscdevice misc = {     .minor = MISC_DYNAMIC_MINOR,     .name = DEVICE_NAME,     .fops = &dev_fops, };  static int __init my_mic_init(void) {     int ret;     gpio_direction_input(LGPIO);//设置io为输入  nxp_soc_gpio_set_io_pull_sel(LGPIO,0);//设置下拉电阻      ret = misc_register(&misc);     printk (DEVICE_NAME"\tinitialized\n");      return ret;  }  static void __exit my_mic_exit(void) {     misc_deregister(&misc); }  module_init(my_mic_init); module_exit(my_mic_exit);  MODULE_LICENSE("GPL"); MODULE_AUTHOR("cumtzd");

其测试程序

#include     <stdio.h>       #include     <stdlib.h>      #include     <unistd.h>      #include     <sys/types.h>   #include     <sys/stat.h>    #include     <fctl.h>      
#include     <errno.h> 

#define DEV_FILE "/dev/4418_mic"

int main()
{
    int fd_dev=-1;
    char dat;
    int time=1000,ms,count=0;

    printf("nanoPi driver Test\n");

    fd_dev = open(DEV_FILE,O_RDWR);
    if(fd_dev<0){
        printf("open device err\n");
        return 0;
    }

    printf("input ms:");//控制检测时间间隔多少ms
    scanf("%d",&ms);
    time = time * ms;

    while(1){
        read(fd_dev,&dat,1);		
        if(dat==0)
            count++;//统计声响次数
        printf("MIC status [%d],count=%d\n",dat,count);
        usleep(time);
    }

    return 0;
}

1. 3    电压转换模块设备驱动及测试程序

#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/list.h>

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <mach/devices.h>
#include <mach/soc.h>


#define DEVICE_NAME "4418_search"


//nanopi2S S5P4418
#define GPIO_MIC PAD_GPIO_B +30     //连接声音传感器的5-3.3v电压转换模块对应的GPIO脚
#define GPIO_LIGHT PAD_GPIO_B +31   //连接光感传感器的5-3.3v电压转换模块对应的GPIO脚

static int pir_read(struct file *file, char * buffer, size_t count, loff_t * ppos)
{
        char tmp[2];
        unsigned long err;
        tmp[0] = gpio_get_value(GPIO_MIC);
		  tmp[1] = gpio_get_value(GPIO_LIGHT);
       // printk("==%d==\n",tmp);
        err = copy_to_user(buffer, &tmp, 2);
        return 1;
}


static struct file_operations dev_fops={
        read:pir_read,
};


static struct miscdevice misc = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = DEVICE_NAME,
        .fops = &dev_fops,
};

static int __init my_pir_init(void)
{
        int ret;

        gpio_direction_input(GPIO_MIC);//设置io为输入
		nxp_soc_gpio_set_io_pull_sel(GPIO_MIC,0);//设置下拉电阻
		
		gpio_direction_input(GPIO_LIGHT);//设置io为输入
		nxp_soc_gpio_set_io_pull_sel(GPIO_LIGHT,0);//设置下拉电阻
		
        ret = misc_register(&misc);
        printk (DEVICE_NAME"\t initialized\n");

        return ret;
}

static void __exit my_pir_exit(void)
{
        misc_deregister(&misc);
}

module_init(my_pir_init);
module_exit(my_pir_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("cumtzd");

其测试程序

#include     <stdio.h>      
#include     <stdlib.h>     
#include     <unistd.h>     
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>      
#include     <errno.h> 

#define DEV_FILE "/dev/4418_search"

int main()
{
    int fd_dev=-1;
    char dat[2];
    printf("nanoPi 5-3.3v driver Test\n");

    fd_dev = open(DEV_FILE,O_RDWR);
    if(fd_dev<0){
        printf("open device err\n");
        return 0;
    }

    while(1){
        dat[0]=0;
		  dat[1]=0;		
        read(fd_dev,dat,2);
        printf("dat[0]=%d,dat[1]=%d\n",dat[0],dat[1]);
        sleep(1);
    }
    return 0;
}
1. 4    继电器驱动及测试程序
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/list.h>

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <mach/devices.h>

#define DEVICE_NAME "4418_relay1"

//nanopi2s -s5p4418
#define J1_GPIO PAD_GPIO_C +7       //模块GPIO脚


#define J1_OFF 0x00
#define J1_ON  0x01

char drv_buf[2];

static int update_relay(void)
{

    switch(drv_buf[0]) {
    case J1_ON:
        gpio_set_value(J1_GPIO, 0);  //输出低电平,低电平触发,即磁铁和触点常闭状况
        return 0;
    case J1_OFF:
        gpio_set_value(J1_GPIO, 1);  //输出高电平
        return 0;
    default:
        return -EINVAL;
    }
}

static int relay_write(struct file *file, const char * buffer, size_t count, loff_t * ppos)
{
    unsigned long err;          
    err = copy_from_user(drv_buf, buffer, 1);
    update_relay();
    return 1;
}

static struct file_operations dev_fops={
    write:relay_write,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init my_relay_init(void)
{
    int ret;

    gpio_direction_output(J1_GPIO,1);//设置输出
    //gpio_direction_output(J2_GPIO,1);//设置输出

    ret = misc_register(&misc);
    printk (DEVICE_NAME"\t#J1 J2 initialized\n"); 
    return ret; 
}

static void __exit my_relay_exit(void)
{
    misc_deregister(&misc);
}

module_init(my_relay_init);
module_exit(my_relay_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CUMTZD");
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/list.h>

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <mach/devices.h>

#define DEVICE_NAME "4418_relay2"

//nanopi2s -s5p4418
#define J2_GPIO PAD_GPIO_C +8       //模块GPIO脚

#define J2_OFF 0x00
#define J2_ON  0x01

char drv_buf[2];

static int update_relay(void)
{

    switch(drv_buf[0]) {
    case J2_ON:
        gpio_set_value(J2_GPIO, 0);  //输出低电平
        return 0;
    case J2_OFF:
        gpio_set_value(J2_GPIO, 1);  //输出高电平
        return 0;
    default:
        return -EINVAL;
    }
}

static int relay_write(struct file *file, const char * buffer, size_t count, loff_t * ppos)
{
    unsigned long err;          
    err = copy_from_user(drv_buf, buffer, 1);
    update_relay();
    return 1;
}

static struct file_operations dev_fops={
    write:relay_write,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init my_relay_init(void)
{
    int ret;

    //gpio_direction_output(J1_GPIO,1);//设置输出
    gpio_direction_output(J2_GPIO,1);//设置输出

    ret = misc_register(&misc);
    printk (DEVICE_NAME"\t#J1 J2 initialized\n"); 
    return ret; 
}

static void __exit my_relay_exit(void)
{
    misc_deregister(&misc);
}

module_init(my_relay_init);
module_exit(my_relay_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CUMTZD");

其测试程序

#include     <stdio.h>    
#include     <stdlib.h>     
#include     <unistd.h>     
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>      
#include     <errno.h> 


#define RELAY1_DEV	"/dev/4418_relay1"
#define RELAY2_DEV	"/dev/4418_relay2"

#define J1_OFF  0x00
#define J1_ON   0x01
#define J2_OFF  0x00
#define J2_ON   0x01

int main()
{
    int fd_dev1=-1;
	int fd_dev2=-1;
    char dat[2];
    int cmd;
    printf("nanoPi driver Test\n");

    fd_dev1 = open(RELAY1_DEV,O_RDWR);
	fd_dev2 = open(RELAY2_DEV,O_RDWR);
	
    if(fd_dev1<0||fd_dev2<0){
        printf("open device err\n");
        return 0;
    }

    while(1)
	{
        printf("1:J1 OFF 2:J1 ON\n");
        printf("Please input:"); 
        scanf("%d",&cmd);
        switch(cmd){
            case 1:     
                dat[0] = J1_OFF;
                break;
            case 2:
                dat[0] = J1_ON;
                break;
            default:
                break;
        }
        write(fd_dev1,dat,1);
		
		sleep(2);
		printf("3:J2 OFF 4:J2 ON\n");
        printf("Please input:"); 
        scanf("%d",&cmd);
        switch(cmd){
            case 3:
                dat[0] = J2_OFF;
                break;
            case 4:
                dat[0] = J2_ON;
                break;
            default:
                break;
        }
        write(fd_dev2,dat,1);
    }
    return 0;
}

二、  tiny6410的相关驱动

2.1    红外感应设备驱动及测试程序

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/list.h>

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>


#include <mach/hardware.h>
#include <plat/gpio-cfg.h>

#define DEVICE_NAME "6410_hongwai"


//nanopi2451
//#define LGPIO PAD_GPIO_C +28   //模块GPIO脚

//Tiny6410-s3c6410
#define LGPIO  S3C64XX_GPB(1)

static int pir_read(struct file *file, char * buffer, size_t count, loff_t * ppos)
{
        unsigned tmp;
        unsigned long err;
        tmp = gpio_get_value(LGPIO);
        printk("==%d==\n",tmp);
        err = copy_to_user(buffer, &tmp, 1);
        return 1;
}


static struct file_operations dev_fops={
        read:pir_read,
};


static struct miscdevice misc = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = DEVICE_NAME,
        .fops = &dev_fops,
};

static int __init my_pir_init(void)
{
        int ret;

        gpio_direction_input(LGPIO);//设置io为输入
		//nxp_soc_gpio_set_io_pull_sel(LGPIO,0);//设置下拉电阻
			s3c_gpio_setpull(LGPIO,S3C_GPIO_PULL_DOWN);//设置下拉电阻
		
        ret = misc_register(&misc);
        printk (DEVICE_NAME"\t initialized\n");

        return ret;
}

static void __exit my_pir_exit(void)
{
        misc_deregister(&misc);
}

module_init(my_pir_init);
module_exit(my_pir_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("cumtzd");

其测试程序

#include     <stdio.h>      
#include     <stdlib.h>     
#include     <unistd.h>     
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>      
#include     <errno.h> 

#define DEV_FILE "/dev/6410_hongwai"

int main()
{
    int fd_dev=-1;
    char dat[8];
    printf("Tiny6410 driver Test\n");

    fd_dev = open(DEV_FILE,O_RDWR);
    if(fd_dev<0){
        printf("open device err\n");
        return 0;
    }

    while(1){
        dat[0]=0x55;
        read(fd_dev,dat,1);
        printf("dat=%x\n",dat[0]);
        sleep(1);
    }
    return 0;
}

2.2    继电器驱动及测试程序

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/list.h>

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>

#include <mach/hardware.h>
#include <plat/gpio-cfg.h>

#define DEVICE_NAME "6410_relay"

//nanopi 2s -s5p4418
//#define J1_GPIO PAD_GPIO_C +7       //模块GPIO脚


//Tiny6410-s3c6410
#define J1_GPIO  S3C64XX_GPB(0)

#define J1_OFF 0x00
#define J1_ON  0x01


char drv_buf[2];

static int update_relay(void)
{

    switch(drv_buf[0]) {
    case J1_ON:
        gpio_set_value(J1_GPIO, 0);  //输出低电平,低电平触发,即磁铁和触点常闭状况
        return 0;
    case J1_OFF:
        gpio_set_value(J1_GPIO, 1);  //输出高电平
        return 0;
    default:
        return -EINVAL;
    }
}

static int relay_write(struct file *file, const char * buffer, size_t count, loff_t * ppos)
{
    unsigned long err;          
    err = copy_from_user(drv_buf, buffer, 1);
    update_relay();
    return 1;
}

static struct file_operations dev_fops={
    write:relay_write,
};

static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};

static int __init my_relay_init(void)
{
    int ret;

    gpio_direction_output(J1_GPIO,1);//设置输出
	 //s3c_gpio_setpull(J1_GPIO,S3C_GPIO_PULL_DOWN);//设置下拉电阻
    

    ret = misc_register(&misc);
    printk (DEVICE_NAME"\t#J1 J2 initialized\n"); 
    return ret; 
}

static void __exit my_relay_exit(void)
{
    misc_deregister(&misc);
}

module_init(my_relay_init);
module_exit(my_relay_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CUMTZD");

其测试程序

#include     <stdio.h>    
#include     <stdlib.h>     
#include     <unistd.h>     
#include     <sys/types.h>  
#include     <sys/stat.h>   
#include     <fcntl.h>      
#include     <errno.h> 

#define DEV_FILE "/dev/6410_relay"

#define J1_OFF  0x00
#define J1_ON   0x01


int main()
{
    int fd_dev=-1;
    char dat[2];
    int cmd;
    printf("Tiny6410 driver Test\n");

    fd_dev = open(DEV_FILE,O_RDWR);
    if(fd_dev<0){
        printf("open device err\n");
        return 0;
    }

    while(1){
        printf("1:J1 OFF 2:J1 ON \n");
        printf("Please input:"); 
        scanf("%d",&cmd);
        switch(cmd){
            case 1:     
                dat[0] = J1_OFF;
                break;
            case 2:
                dat[0] = J1_ON;
                break;            
            default:
                break;
        }
        write(fd_dev,dat,1);
    }
    return 0;
}

标签: mr1继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台