通过ioctl函数选择不同硬件的控制,LED 蜂鸣器 马达 风扇

通过ioctl函数选择不同硬件的控制,LED 蜂鸣器 马达 风扇

实验现象

在这里插入图片描述

head.h

#ifndef __HEAD_H__
#define __HEAD_H__ 
typedef struct{volatile unsigned int MODER;   // 0x00volatile unsigned int OTYPER;  // 0x04volatile unsigned int OSPEEDR; // 0x08volatile unsigned int PUPDR;   // 0x0Cvolatile unsigned int IDR;     // 0x10volatile unsigned int ODR;     // 0x14volatile unsigned int BSRR;    // 0x18volatile unsigned int LCKR;    // 0x1C volatile unsigned int AFRL;    // 0x20 volatile unsigned int AFRH;    // 0x24volatile unsigned int BRR;     // 0x28volatile unsigned int res;volatile unsigned int SECCFGR; // 0x30
}gpio_t;
#define PHY_LED1_ADDR 0X50006000
#define PHY_LED2_ADDR    0X50007000
#define PHY_LED3_ADDR 0X50006000
#define PHY_RCC_ADDR    0X50000A28
#define GPIOB 0X50003000
#define GPIOE 0X50006000
#define GPIOF 0X50007000#define LED_ON _IOW('l',1,int)  //开灯
#define LED_OFF _IOW('l',0,int)//关灯
#define FAN_ON _IO('f',1)  //开风扇
#define FAN_OFF _IO('f',0)  //关风扇
#define MOTOR_ON _IO('m',1)  //开马达
#define MOTOR_OFF _IO('m',0)  //关马达
#define BEE_ON _IO('b',1)  //开蜂鸣器
#define BEE_OFF _IO('b',0)  //管蜂鸣器#endif 

test.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include "head.h"int main(int argc, char const *argv[])
{int a, b;char buf[128] = {0};char ch[128] = {0}; // 判断控制哪个硬件printf("请输入要控制的硬件:LED(LED) fan(风扇) motor(马达) bee(蜂鸣器)>>>");scanf("%s",ch);getchar(); // 接收垃圾字符if (!strcmp(ch,"LED")){int fd = open("/dev/led0", O_RDWR);if (fd < 0){printf("打开led设备文件失败\n");exit(-1);}while (1){// 从终端读取printf("请选择要实现的功能\n");printf("0(关灯) 1(开灯)>>>");scanf("%d", &a);printf("请输入要控制的灯\n");printf("1(LED1) 2(LED2) 3(LED3)>>>");scanf("%d", &b);if (a == 1) // 开灯{ioctl(fd, LED_ON, &b);}else if (a == 0) // 关灯{ioctl(fd, LED_OFF, &b);}}close(fd);}else if(!strcmp(ch,"fan")){int fd_fan = open("/dev/fan",O_RDWR);if(fd_fan < 0){printf("打开fan设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入要实现的功能\n");printf("0(关闭风扇) 1(开启风扇)>>>");scanf("%d",&a);if(a == 1){ioctl(fd_fan,FAN_ON);}else if(a == 0){ioctl(fd_fan,FAN_OFF);}}close(fd_fan);}else if(!strcmp(ch,"motor")){int fd_motor = open("/dev/motor",O_RDWR);if(fd_motor < 0){printf("打开motor设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入要实现的功能\n");printf("0(关闭马达) 1(开启马达)>>>");scanf("%d",&a);if(a == 1){ioctl(fd_motor,MOTOR_ON);}else if(a == 0){ioctl(fd_motor,MOTOR_OFF);}}close(fd_motor);}else if(!strcmp(ch,"bee")){int fd_bee = open("/dev/bee",O_RDWR);if(fd_bee < 0){printf("打开bee设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入要实现的功能\n");printf("0(关闭蜂鸣器) 1(开启蜂鸣器)>>>");scanf("%d",&a);if(a == 1){ioctl(fd_bee,BEE_ON);}else if(a == 0){ioctl(fd_bee,BEE_OFF);}}close(fd_bee);}elseprintf("输入有误!\n");return 0;
}

led.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"struct class *cls;
struct device *dev;
int major;
char kbuf[128] = {0};
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int which;//通过拷贝函数获取ioctl第三个参数对应空间的数值int ret=copy_from_user(&which,(void *)arg,4);if(ret){printk("拷贝用户空间数据失败\n");return -EIO;}//进行功能控制switch (cmd){case LED_ON: // 开灯switch (which){case 1: // LED1vir_led1->ODR |= (0x1 << 10);break;case 2: // LED2vir_led2->ODR |= (0x1 << 10);break;case 3: // LED3vir_led3->ODR |= (0x1 << 8);break;}break;case LED_OFF: // 关灯switch (which){case 1:vir_led1->ODR &= (~(0X1 << 10));break;case 2:vir_led2->ODR &= (~(0X1 << 10));break;case 3:vir_led3->ODR &= (~(0X1 << 8));break;}break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};int all_led_init(void)
{// 寄存器地址的映射vir_led1 = ioremap(PHY_LED1_ADDR, sizeof(gpio_t));if (vir_led1 == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_led2 = ioremap(PHY_LED2_ADDR, sizeof(gpio_t));if (vir_led2 == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_led3 = vir_led1;vir_rcc = ioremap(PHY_RCC_ADDR, 4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (3 << 4);// led1vir_led1->MODER &= (~(3 << 20));vir_led1->MODER |= (1 << 20);vir_led1->ODR &= (~(1 << 10));// led2vir_led2->MODER &= (~(3 << 20));vir_led2->MODER |= (1 << 20);vir_led2->ODR &= (~(1 << 10));// led3vir_led3->MODER &= (~(3 << 16));vir_led1->MODER |= (1 << 16);vir_led1->ODR &= (~(1 << 8));printk("寄存器初始化成功\n");return 0;
}static int __init mycdev_init(void)
{int i;// 字符设备驱动注册major = register_chrdev(0, "mychrdev", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "mychrdev");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}// 向上提交设备节点信息// 为三盏灯创建三个设备文件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);}}// 寄存器映射以及初始化all_led_init();return 0;
}
static void __exit mycdev_exit(void)
{int i;// 取消地址映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_rcc);// 销毁设备节点信息for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录信息class_destroy(cls);// 注销字符设备驱动unregister_chrdev(major, "mychrdev");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

fan.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"struct class *cls;
struct device *dev;
gpio_t *vir_gpioe;
int major;
char kbuf[128] = {0};
unsigned int *vir_rcc;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case FAN_ON: // 开风扇vir_gpioe->ODR |= (0x1 << 9);break;case FAN_OFF: // 关风扇vir_gpioe->ODR &= (~(0X1 << 9));break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};
int all_fan_init(void)
{// 寄存器地址的映射vir_gpioe = ioremap(GPIOE, sizeof(gpio_t));if (vir_gpioe == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_rcc = ioremap(PHY_RCC_ADDR,4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (0x3 << 4);// fanvir_gpioe->MODER &= (~(0x3 << 18));vir_gpioe->MODER |= (0x1 << 18);vir_gpioe->ODR &= (~(0x1 << 9));printk("寄存器初始化成功\n");return 0;
}
static int __init mycdev_init(void)
{// 字符设备驱动注册major = register_chrdev(0, "fan", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "fan");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}// 向上提交设备节点信息// 创建设备文件dev = device_create(cls, NULL, MKDEV(major,0), NULL, "fan");if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}// 寄存器映射以及初始化all_fan_init();return 0;
}
static void __exit mycdev_exit(void)
{iounmap(vir_gpioe);iounmap(vir_rcc);device_destroy(cls,MKDEV(major,0));class_destroy(cls);unregister_chrdev(major,"fan");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

motor.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"struct class *cls;
struct device *dev;
gpio_t *vir_gpiof;
int major;
char kbuf[128] = {0};
unsigned int *vir_rcc;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case MOTOR_ON: // 开马达vir_gpiof->ODR |= (0x1 << 6);break;case MOTOR_OFF: // 关马达vir_gpiof->ODR &= (~(0X1 << 6));break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};
int all_motor_init(void)
{// 寄存器地址的映射vir_gpiof = ioremap(GPIOB, sizeof(gpio_t));if (vir_gpiof == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_rcc = ioremap(PHY_RCC_ADDR,4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (0x3 << 4);// fanvir_gpiof->MODER &= (~(0x3 << 12));vir_gpiof->MODER |= (0x1 << 12);vir_gpiof->ODR &= (~(0x1 << 6));printk("寄存器初始化成功\n");return 0;
}
static int __init mycdev_init(void)
{// 字符设备驱动注册major = register_chrdev(0, "bee", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "bee");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}// 向上提交设备节点信息// 创建设备文件dev = device_create(cls, NULL, MKDEV(major,0), NULL, "bee");if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}// 寄存器映射以及初始化all_motor_init();return 0;
}
static void __exit mycdev_exit(void)
{iounmap(vir_gpiof);iounmap(vir_rcc);device_destroy(cls,MKDEV(major,0));class_destroy(cls);unregister_chrdev(major,"bee");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

bee.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"struct class *cls;
struct device *dev;
gpio_t *vir_gpiob;
int major;
char kbuf[128] = {0};
unsigned int *vir_rcc;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case BEE_ON: // 开马达vir_gpiob->ODR |= (0x1 << 6);break;case BEE_OFF: // 关马达vir_gpiob->ODR &= (~(0X1 << 6));break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};
int all_motor_init(void)
{// 寄存器地址的映射vir_gpiob = ioremap(GPIOB, sizeof(gpio_t));if (vir_gpiob == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_rcc = ioremap(PHY_RCC_ADDR,4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (0x1 << 1);// fanvir_gpiob->MODER &= (~(0x3 << 12));vir_gpiob->MODER |= (0x1 << 12);vir_gpiob->ODR &= (~(0x1 << 6));printk("寄存器初始化成功\n");return 0;
}
static int __init mycdev_init(void)
{// 字符设备驱动注册major = register_chrdev(0, "bee", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "bee");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}// 向上提交设备节点信息// 创建设备文件dev = device_create(cls, NULL, MKDEV(major,0), NULL, "bee");if (IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}// 寄存器映射以及初始化all_motor_init();return 0;
}
static void __exit mycdev_exit(void)
{iounmap(vir_gpiob);iounmap(vir_rcc);device_destroy(cls,MKDEV(major,0));class_destroy(cls);unregister_chrdev(major,"bee");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/9256.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity Editor扩展 实现一个Excel读表窗口

设计 Unity Editor窗口类 public class ExcelEditorWindow : EditorWindow {[MenuItem( "Frameworks/读表配置界面", false, 10 )]private static void Open(){Rect wr new Rect( 0, 0, 500, 500 );ExcelEditorWindow window ( ExcelEditorWindow ) EditorWindow.…

React hooks文档笔记(二) 添加交互性

添加交互性 1. 事件传播1.1 停止传播1.2 阻止默认事件 2. [Hook] useState 状态3. 渲染和提交3.1 触发渲染3.2 React渲染组件3.3 提交对 DOM 的更改3.4 浏览器绘制 4. 渲染快照状态队列例子 5. 更新state中的对象 1. 事件传播 js的事件流&#xff1a; 事件捕获&#xff1a;从…

【DBA课程-笔记】MongoDB入门到云上开发

课程目的&#xff1a;成为专业MongoDB的DBA nosql第一&#xff1a;MongoDB 一、讲师&#xff1a; 二、课程目录 第1章&#xff1a;MongoDB数据库入门 第2章&#xff1a;MongoDB数据数据查询与分析 第3章&#xff1a;MongoDB数据库核心知识 第4章&#xff1a;MongoDB数据库管…

MySQL索引

文章目录 MySQL索引1 索引1.1 索引的概念1.2 索引的作用1.3 创建索引的原则依据 2 索引的分类和创建2.1 普通索引2.1.1 直接创建索引2.1.2 修改表方式创建2.1.3 创建表的时候指定索引 2.2 唯一索引2.2.1 直接创建唯一索引2.2.2 修改表方式创建唯一索引2.2.3 创建表的时候指定唯…

SQlite3 编译

参考博客&#xff1a;https://blog.csdn.net/flowerspring/article/details/121268403 1.下载C源码以及def文件https://www.sqlite.org/download.html 2. 下载完成之后解压 sqlite-amalgamation获取C源码&#xff0c;解压sqlite-dll-win32-xx获取里面的def文件。 3.新建sqlite…

MySQL的面试题讲解看完肯定对你有帮助!!

一、理论方面 1.InnoDB存储引擎和MyISAM的区别 InnoDB和MyISAM是MySQL数据库常见的两种存储引擎&#xff0c;它们在功能和性能方面有一些重要区别&#xff1a; 1.事务支持&#xff1a;InnoDB是一个支持事务处理的存储引擎&#xff0c;它使用了ACID&#xff08;原子性、一致性、…

SciencePub学术 | 数据处理类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 数据处理类重点SCI&EI征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 数据处理类重点SCIE&EI 【期刊简介】IF&#xff1a;3.5-4.0&#xff0c;JCR2区&#xff0c;中科院4区&#xff1b; 【出版社】…

SpringBoot+WebSocket+Session共享

前言 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端 一、为什么需要WebSocket HTTP 是基于请求响应式的&#xff0c;即通信只能由客户端发起&#xff0c;服务端做出响应&#xff0c;无状态&…

kafka入门,节点服役和退役(新增节点和删除节点)(十二)

1、节点服役 1、克隆准备其中一台节点 2、如果新节点的kafka有被log和datas文件夹要删除 3、修改/etc/hosts 配置新节点映射 1.1 执行负载均衡操作 vim topics-to-move.json{"topic": "主题名称"} {"topics": [{"topic": "fi…

web测试需要注意几个非常重要的测试点

微软语言标准&#xff1a; 全角字符和半角字符都要使用一个空格分开 英文和数字直接要有空页面分辨率&#xff1a; 通常是计算机的默认分辨率&#xff0c;但是还是会有一些老式电脑存在1024*768的情况 浏览器的兼容性&#xff1a; 目前市场上的主流浏览器&#xff1a;IE8.0-…

如何在Mac终端上,用十六进制查看某个硬盘(使用dd和hexdump,所以其他系统也可以使用这个方法)

首先需要强调&#xff1a;这种方法不能保证所有的硬盘都可以查看&#xff0c;有些硬盘由于一些原因会显示“Resource busy”&#xff0c;比如说时间机器的硬盘&#xff0c;内置硬盘等。 准备&#xff1a; 当然是一台 Mac&#xff1b;hexdump程序dd程序 方法如下&#xff1a;…

QT或VS2015报错:Error: C2661: QColor::ct::ct: 没有重载函数接受 5 个参数解决方案

安装了QT5.14.2 MSCV2015配置并同时在QT或VS2015测试并运行都提示没有重载函数接受 5 个参数。 同时还会出现C2134错误&#xff1a;QMetaObject::SuperData::operator const QMetaObject *: 调用不会生成常数表达式的错误 搜索了网络上的结果都让换其它版本&#xff0c;没有…