控制LED灯,蜂鸣器,风扇,马达

head.h

#ifndef __HEAD_H__
#define __HEAD_H__

typedef struct{
    unsigned int moder;
    unsigned int otyper;
    unsigned int ospeedr;
    unsigned int pupdr;
    unsigned int idr;
    unsigned int odr;
}gpio_t;

#define RCC 0x50000A28 
#define GPIOB 0x50003000
#define GPIOE 0x50006000
#define GPIOF 0x50007000

#define ON _IOW('l',1,int*)
#define OFF _IOW('l',0,int*)


#endif

led.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"

// 存储主设备号
int major;

// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;

// 存储虚拟空间地址
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
int *vir_rcc;

// 封装操作方法函数
int led_open(struct inode *inode, struct file *file)
{
    return 0;
}
long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    // 存放从用户空间传过来的数据
    int buf;
    int ret = copy_from_user(&buf, (void *)arg, 4);
    if (ret)
    {
        printk("拷贝用户空间传过来的数据失败\n");
        return -EIO;
    }
    switch (cmd)
    {
    case OFF: // 关灯
        switch (buf)
        {
        case 1: // led1
            vir_led1->odr &= (~(0x1 << 10));
            break;
        case 2: // led2
            vir_led2->odr &= (~(0x1 << 10));
            break;
        case 3: // led3
            vir_led3->odr &= (~(0x1 << 8));
            break;
        }
        break;
    case ON: // 开灯
        switch (buf)
        {
        case 1: // led1
            vir_led1->odr |= (0x1 << 10);
            break;
        case 2: // led2
            vir_led2->odr |= (0x1 << 10);
            break;
        case 3: // led3
            vir_led3->odr |= (0x1 << 8);
            break;
        }
        break;
    default:
        break;
    }
    return 0;
}
int led_close(struct inode *inode, struct file *file)
{
    return 0;
}

// 声明操作方法结构体变量并初始化
struct file_operations fops =
    {
        .open = led_open,
        .unlocked_ioctl = led_ioctl,
        .release = led_close,
};

static int __init led_init(void)
{
    int i;

    // 注册字符设备驱动
    major = register_chrdev(0, "led", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return -EIO;
    }
    printk("注册字符设备驱动成功\n");

    // 自动生成设备节点
    // 向上提交目录
    cls = class_create(THIS_MODULE, "led");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");

    // 向上提交设备信息
    for (i = 0; i < 3; i++)
    {
        dev = device_create(cls, NULL, MKDEV(major, i), NULL, "led%d", i);
        if (IS_ERR(dev))
        {
            printk("向上提交设备信息失败\n");
            return -PTR_ERR(dev);
        }
    }
    printk("向上提交设备信息成功\n");

    // 物理地址映射
    vir_led1 = ioremap(GPIOE, sizeof(gpio_t));
    if (vir_led1 == NULL)
    {
        printk("led1相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    vir_led2 = ioremap(GPIOF, sizeof(gpio_t));
    if (vir_led2 == NULL)
    {
        printk("led2相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    vir_led3 = vir_led1;
    vir_rcc = ioremap(RCC, 4);
    if (vir_rcc == NULL)
    {
        printk("rcc相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    printk("寄存器物理地址映射成功\n");

    // 寄存器初始化
    // rcc寄存器使能
    (*vir_rcc) |= (0x3 << 4);
    // 设置为输出
    // led1
    vir_led1->moder &= (~(0x3 << 20));
    vir_led1->moder |= (0x1 << 20);
    // led2
    vir_led2->moder &= (~(0x3 << 20));
    vir_led2->moder |= (0x1 << 20);
    // led3
    vir_led3->moder &= (~(0x3 << 16));
    vir_led3->moder |= (0x1 << 16);
    // 默认为灯灭
    vir_led1->odr &= (~(0x1 << 10)); // led1
    vir_led2->odr &= (~(0x1 << 10)); // led2
    vir_led3->odr &= (~(0x1 << 8));  // led3
    printk("寄存器初始化成功\n");
    printk("LED灯设备安装成功\n");

    return 0;
}

static void __exit led_exit(void)
{
    int i;
    // 字符设备驱动注销
    unregister_chrdev(major, "led");
    // 销毁设备节点信息
    for (i = 0; i < 3; i++)
    {
        device_destroy(cls, MKDEV(major, i));
    }
    // 销毁目录
    class_destroy(cls);
    // 取消物理地址映射
    iounmap(vir_led1);
    iounmap(vir_led2);
    iounmap(vir_rcc);
    printk("取消地址映射成功\n");
    printk("LED灯设备安装成功\n");
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

breeze.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"

// 存储主设备号
int major;

// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;

// 存储虚拟空间地址
gpio_t *vir_breeze;
int *vir_rcc;

// 封装操作方法函数
int breeze_open(struct inode *inode, struct file *file)
{
    return 0;
}
long breeze_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd)
    {
    case OFF:
        vir_breeze->odr &= (~(0x1 << 6));
        break;
    case ON:
        vir_breeze->odr |= (0x1 << 6);
        break;
    }
    return 0;
}
int breeze_close(struct inode *inode, struct file *file)
{
    return 0;
}

// 声明操作方法结构体变量并初始化
struct file_operations fops =
    {
        .open = breeze_open,
        .unlocked_ioctl = breeze_ioctl,
        .release = breeze_close,
};

static int __init breeze_init(void)
{
    // 注册字符设备驱动
    major = register_chrdev(0, "breeze", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return -EIO;
    }
    printk("注册字符设备驱动成功\n");

    // 自动生成设备节点
    // 向上提交目录
    cls = class_create(THIS_MODULE, "breeze");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");

    // 向上提交设备信息
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "breeze0");
    if (IS_ERR(dev))
    {
        printk("向上提交设备信息失败\n");
        return -PTR_ERR(dev);
    }
    printk("向上提交设备信息成功\n");

    // 物理地址映射
    vir_breeze = ioremap(GPIOB, sizeof(gpio_t));
    if (vir_breeze == NULL)
    {
        printk("breeze相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    vir_rcc = ioremap(RCC, 4);
    if (vir_rcc == NULL)
    {
        printk("rcc相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    printk("寄存器物理地址映射成功\n");

    // 寄存器初始化
    // rcc寄存器使能
    (*vir_rcc) |= (0x1 << 1);
    // 设置为输出
    vir_breeze->moder &= (~(0x3 << 12));
    vir_breeze->moder |= (0x1 << 12);

    // 默认蜂鸣器不响
    vir_breeze->odr &= (~(0x1 << 6));
    printk("寄存器初始化成功\n");
    printk("蜂鸣器设备安装成功\n");

    return 0;
}

static void __exit breeze_exit(void)
{
    // 字符设备驱动注销
    unregister_chrdev(major, "breeze");
    // 销毁设备节点信息
    device_destroy(cls, MKDEV(major, 0));
    // 销毁目录
    class_destroy(cls);
    // 取消物理地址映射
    iounmap(vir_breeze);
    iounmap(vir_rcc);
    printk("取消地址映射成功\n");
    printk("蜂鸣器设备安装成功\n");
}

module_init(breeze_init);
module_exit(breeze_exit);
MODULE_LICENSE("GPL");

fan.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"


// 存储主设备号
int major;

// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;

// 存储虚拟空间地址
gpio_t *vir_fan;
int *vir_rcc;

// 封装操作方法函数
int fan_open(struct inode *inode, struct file *file)
{
    return 0;
}
long fan_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd)
    {
    case OFF:
        vir_fan->odr &= (~(0x1 << 9));
        break;
    case ON:
        vir_fan->odr |= (0x1 << 9);
        break;
    }
    return 0;
}
int fan_close(struct inode *inode, struct file *file)
{
    return 0;
}

// 声明操作方法结构体变量并初始化
struct file_operations fops =
    {
        .open = fan_open,
        .unlocked_ioctl = fan_ioctl,
        .release = fan_close,
};

static int __init fan_init(void)
{
    // 注册字符设备驱动
    major = register_chrdev(0, "fan", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return -EIO;
    }
    printk("注册字符设备驱动成功\n");

    // 自动生成设备节点
    // 向上提交目录
    cls = class_create(THIS_MODULE, "fan");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");

    // 向上提交设备信息
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "fan0");
    if (IS_ERR(dev))
    {
        printk("向上提交设备信息失败\n");
        return -PTR_ERR(dev);
    }
    printk("向上提交设备信息成功\n");

    // 物理地址映射
    vir_fan = ioremap(GPIOE, sizeof(gpio_t));
    if (vir_fan == NULL)
    {
        printk("fan相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    vir_rcc = ioremap(RCC, 4);
    if (vir_rcc == NULL)
    {
        printk("rcc相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    printk("寄存器物理地址映射成功\n");

    // 寄存器初始化
    // rcc寄存器使能
    (*vir_rcc) |= (0x1 << 4);
    // 设置为输出
    vir_fan->moder &= (~(0x3 << 18));
    vir_fan->moder |= (0x1 << 18);

    // 默认蜂鸣器不响
    vir_fan->odr &= (~(0x1 << 9));
    printk("寄存器初始化成功\n");
    printk("风扇设备安装成功\n");

    return 0;
}

static void __exit fan_exit(void)
{
    // 字符设备驱动注销
    unregister_chrdev(major, "fan");
    // 销毁设备节点信息
    device_destroy(cls, MKDEV(major, 0));
    // 销毁目录
    class_destroy(cls);
    // 取消物理地址映射
    iounmap(vir_fan);
    iounmap(vir_rcc);
    printk("取消地址映射成功\n");
    printk("风扇设备卸载成功\n");
}

module_init(fan_init);
module_exit(fan_exit);
MODULE_LICENSE("GPL");

motor.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/io.h>
#include "head.h"

// 存储主设备号
int major;

// 存放class_create与device_create函数创建的空间首地址
struct class *cls;
struct device *dev;

// 存储虚拟空间地址
gpio_t *vir_motor;
int *vir_rcc;

// 封装操作方法函数
int motor_open(struct inode *inode, struct file *file)
{
    return 0;
}
long motor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd)
    {
    case OFF:
        vir_motor->odr &= (~(0x1 << 6));
        break;
    case ON:
        vir_motor->odr |= (0x1 << 6);
        break;
    }
    return 0;
}
int motor_close(struct inode *inode, struct file *file)
{
    return 0;
}

// 声明操作方法结构体变量并初始化
struct file_operations fops =
    {
        .open = motor_open,
        .unlocked_ioctl = motor_ioctl,
        .release = motor_close,
};

static int __init motor_init(void)
{
    // 注册字符设备驱动
    major = register_chrdev(0, "motor", &fops);
    if (major < 0)
    {
        printk("注册字符设备驱动失败\n");
        return -EIO;
    }
    printk("注册字符设备驱动成功\n");

    // 自动生成设备节点
    // 向上提交目录
    cls = class_create(THIS_MODULE, "motor");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");

    // 向上提交设备信息
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, "motor0");
    if (IS_ERR(dev))
    {
        printk("向上提交设备信息失败\n");
        return -PTR_ERR(dev);
    }
    printk("向上提交设备信息成功\n");

    // 物理地址映射
    vir_motor = ioremap(GPIOF, sizeof(gpio_t));
    if (vir_motor == NULL)
    {
        printk("motor相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    vir_rcc = ioremap(RCC, 4);
    if (vir_rcc == NULL)
    {
        printk("rcc相关寄存器物理地址映射失败\n");
        return -EIO;
    }
    printk("寄存器物理地址映射成功\n");

    // 寄存器初始化
    // rcc寄存器使能
    (*vir_rcc) |= (0x1 << 5);
    // 设置为输出
    vir_motor->moder &= (~(0x3 << 12));
    vir_motor->moder |= (0x1 << 12);

    // 默认蜂鸣器不响
    vir_motor->odr &= (~(0x1 << 6));
    printk("寄存器初始化成功\n");
    printk("马达设备安装成功\n");

    return 0;
}

static void __exit motor_exit(void)
{
    // 字符设备驱动注销
    unregister_chrdev(major, "motor");
    // 销毁设备节点信息
    device_destroy(cls, MKDEV(major, 0));
    // 销毁目录
    class_destroy(cls);
    // 取消物理地址映射
    iounmap(vir_motor);
    iounmap(vir_rcc);
    printk("马达设备卸载成功\n");
}

module_init(motor_init);
module_exit(motor_exit);
MODULE_LICENSE("GPL");

test.c

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "head.h"

// LED灯控制函数
void led_func(void)
{
    int num, l;
    int fd = open("/dev/led0", O_RDWR);
    if (fd < 0)
    {
        printf("打开文件失败\n");
        return;
    }

    printf("控制第几盏灯,1(led1) 2(led2) 3(led3) >");
    scanf("%d", &num);
    printf("0(关灯) 1(开灯) >");
    scanf("%d", &l);
    if (l == 0)
    {
        ioctl(fd, OFF, &num);
    }
    else if (l == 1)
    {
        ioctl(fd, ON, &num);
    }

    close(fd);
}

// 蜂鸣器控制函数
void breeze_func(void)
{
    int l;
    int fd = open("/dev/breeze0", O_RDWR);
    if (fd < 0)
    {
        printf("打开文件失败\n");
        return;
    }

    printf("0(关闭) 1(启动) >");
    scanf("%d", &l);
    if (l == 0)
    {
        ioctl(fd, OFF);
    }
    else if (l == 1)
    {
        ioctl(fd, ON);
    }

    close(fd);
}

// 风扇控制函数
void fan_func(void)
{
    int l;
    int fd = open("/dev/fan0", O_RDWR);
    if (fd < 0)
    {
        printf("打开文件失败\n");
        return;
    }

    printf("0(关闭) 1(启动) >");
    scanf("%d", &l);
    if (l == 0)
    {
        ioctl(fd, OFF);
    }
    else if (l == 1)
    {
        ioctl(fd, ON);
    }

    close(fd);
}

// 马达控制函数
void motor_func(void)
{
    int l;
    int fd = open("/dev/motor0", O_RDWR);
    if (fd < 0)
    {
        printf("打开文件失败\n");
        return;
    }

    printf("0(关闭) 1(启动) >");
    scanf("%d", &l);
    if (l == 0)
    {
        ioctl(fd, OFF);
    }
    else if (l == 1)
    {
        ioctl(fd, ON);
    }

    close(fd);
}

int main(int argc, const char *argv[])
{
    int dev;
    while (1)
    {
        printf("请输入要控制的设备 1(LED灯) 2(蜂鸣器) 3(风扇) 4(马达) >");
        scanf("%d", &dev);
        switch (dev)
        {
        case 1:
            led_func();
            break;
        case 2:
            breeze_func();
            break;
        case 3:
            fan_func();
            break;
        case 4:
            motor_func();
            break;
        default:
            printf("输入错误\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值