linux系统之字符设备驱动——IIC驱动mma8451q

2023-11-13

linux系统之字符设备驱动——IIC子系统驱动mma8451q

1. 原理图

在这里插入图片描述
在这里插入图片描述

2. 驱动程序

mma8451q.c

/*
 * @Author: your name
 * @Date: 2021-02-23 22:16:37
 * @LastEditTime: 2021-02-24 13:57:31
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \6_I2Cmma8451q\mma8451q.c
 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/slab.h>

#include "mma8451q.h"
#define WHO_AM_I 	0x0d
#define NAME 		"mma8451q"	// 设备节点名字

struct mma8451q_dev{
	unsigned int major;
    struct class *class;	// 设备节点目录
    struct device *dev; 	// 设备
	struct i2c_client *client;		// i2c子系统
}mma8451qDevice;

/**
 * 使用i2c子系统读写寄存器
*/
int i2c_write_reg(unsigned char regaddr, char value)
{
	int ret = 0;
	char w_buf[] = {regaddr, value};	// 关键就在这

	struct i2c_msg w_msg = {
		.addr = mma8451qDevice.client->addr,	// 从机设备地址
		.flags = 0,			// 0:写,1:I2C_M_RD读,I2C_M_TEN:10位从机地址
		.len = 2,			// 消息的长度
		.buf = w_buf,		// 消息的首地址
	};

	ret = i2c_transfer(mma8451qDevice.client->adapter, &w_msg, 1);		// 有几个起始位,就有几个消息
	if(ret != 1)
	{
		printk("sned i2c msg error!\n");
		return -EAGAIN;
	}
	return 0;
}
int i2c_read_reg(unsigned char regaddr)
{
	int ret = 0;
	char value;
	char r_buf[] = {regaddr};
	struct i2c_msg r_msg[] = {
		[0] = {
			.addr = mma8451qDevice.client->addr,
			.flags = 0,
			.len = 1,
			.buf = r_buf,
		},
		[1] = {
			.addr = mma8451qDevice.client->addr,
			.flags = I2C_M_RD,
			.len = 1,
			.buf = &value,
		},
	};

	ret = i2c_transfer(mma8451qDevice.client->adapter, r_msg, 2);
	if(ret != 2)
	{
		printk("recvive i2c msg error!\n");
		return -EAGAIN;
	}
	return value;
}
int mma8451q_open (struct inode *inode, struct file *file)
{
	printk("mma8451q_open OK!\n");
	return 0;
}
int mma8451q_close (struct inode *inode, struct file *file)
{
	printk("mma8451q_close OK!\n");
	return 0;
}
ssize_t mma8451q_read (struct file *file, char __user *ubuf, size_t size, loff_t *loff)
{
	int ret = 0;
	char x_H, x_L, y_H, y_L, z_H, z_L;
	short x, y, z;
	struct mma8451q_accData{
		short x_acc;
		short y_acc;
		short z_acc;
	}acc_data;
	if(size > sizeof(struct mma8451q_accData))
		size = sizeof(struct mma8451q_accData);

	x_H = i2c_read_reg(0x01);
	x_L = i2c_read_reg(0x02);
	x = x_H;
	x = x << 8 | x_L;
	acc_data.x_acc = x >> 2;

	y_H = i2c_read_reg(0x01);
	y_L = i2c_read_reg(0x02);
	y = y_H;
	y = y << 8 | y_L;
	acc_data.y_acc = y >> 2;

	z_H = i2c_read_reg(0x01);
	z_L = i2c_read_reg(0x02);
	z = z_H;
	z = z << 8 | z_L;
	acc_data.z_acc = z >> 2;
	
	ret = copy_to_user(ubuf, &acc_data, size);
	if(ret)
	{
		printk("copy data to user error\n");
		return -EINVAL;
	}
	return size;
}
const struct file_operations fops = 
{
	.open = mma8451q_open,
    .release = mma8451q_close,
	.read = mma8451q_read,
};
int mma8451q_probe(struct i2c_client *cli, const struct i2c_device_id *id)
{
	int ret = -1;
	mma8451qDevice.client = cli;

	printk("mma8451q_probe started\n");

	// 1. 注册字符设备驱动
	mma8451qDevice.major = register_chrdev(mma8451qDevice.major, NAME, &fops);
	if(mma8451qDevice.major < 0)
	{
		printk("register_chrdev Error!\n");
		goto ERR1;
	}
	// 2. 创建设备驱动目录
    mma8451qDevice.class = class_create(THIS_MODULE, "cmma8451qdev");
	if(IS_ERR(mma8451qDevice.class)){
		printk("class_create Error!\n");
		goto ERR2;
	}
    // 3. 创建设备驱动节点
    mma8451qDevice.dev = device_create(mma8451qDevice.class, NULL, MKDEV(mma8451qDevice.major, 0), NULL, NAME);
	if(IS_ERR(mma8451qDevice.dev)){
		printk("device_create Error!\n");
		ret = PTR_ERR(mma8451qDevice.dev);
		goto ERR3;
	}

	// mmq8451q设备的初始化
	ret = i2c_read_reg(WHO_AM_I);
	printk("WHO_AM_I(0x1a) = %#x\n", ret);
	printk("mma8451q_probe OK!\n");

	i2c_write_reg(0x2A, 0X01);		// 激活设备
	i2c_write_reg(0x2B, 0X02);		// 高精度模式
	return 0;

ERR3:
	class_destroy(mma8451qDevice.class);
ERR2:
	unregister_chrdev(mma8451qDevice.major, NAME);
ERR1:
	return ret;
}
int mma8451q_remove(struct i2c_client *cli)
{
	device_destroy(mma8451qDevice.class, MKDEV(mma8451qDevice.major, 0));
    // 3. 销毁设备驱动目录
	class_destroy(mma8451qDevice.class);
    // 4. 注销字符设备驱动
    unregister_chrdev(mma8451qDevice.major, NAME);

	printk("mma8451q_remove OK!\n");
	return 0;
}

struct i2c_device_id mma8451q_id_table[] = {
	{"mma8451q", 0},
	{},
};
struct i2c_driver mma8451q_driver = {
	.probe = mma8451q_probe,
	.remove = mma8451q_remove,
	.driver = {
		.name = "mma8451q",
	},
	.id_table = mma8451q_id_table,
};

static int __init mma8451q_Init(void)
{
	return i2c_add_driver(&mma8451q_driver);
}
static void __exit mma8451q_Exit(void)
{
	i2c_del_driver(&mma8451q_driver);
}

module_init(mma8451q_Init);
module_exit(mma8451q_Exit);
MODULE_LICENSE("GPL");

  1. 应用程序 main.c
/*
 * @Author: your name
 * @Date: 2021-02-23 20:09:13
 * @LastEditTime: 2021-02-24 14:55:45
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \2-led\main.c
 */


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

struct mma8451qData
{
    short acc_x;
    short acc_y;
    short acc_z;
}acc_data;
#define g 9.8
float GetAccelerated(short acc)  
{
    return 4*g*acc/32768;
}
int main(int argc, char const *argv[])
{
    int fd = open("/dev/mma8451q", O_RDWR);
    if(fd < 0)
    {
         perror("open");
         return -1;  
    }

    while(1)
    {
        read(fd, &acc_data, sizeof(struct mma8451qData));
        printf("%.4f\t%.4f,\t%.4f\r\n", GetAccelerated(acc_data.acc_x), GetAccelerated(acc_data.acc_y), GetAccelerated(acc_data.acc_z));
        usleep(100000);
    }
    close(fd);

    return 0;
}

3. 下载调试

在这里插入图片描述
在这里插入图片描述
这两个地方需要添加,才可以正常运行。
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux系统之字符设备驱动——IIC驱动mma8451q 的相关文章

  • 让Redis突破内存大小的限制

    Redis虽然可以实现持久化存储 也是基于数据内存模型的基础之上 单机内存大小限制着Redis存储的数据量 有没有一种替代方案呢 本文介绍一款笔者使用的采用New BSD License 许可协议的软件 SSDB 官网地址 http ssd
  • ubuntu16.04安装cmake-3.8.1最靠谱的方法(ubuntu下安装指定版本cmke)

    1 问题描述 2 cmake安装五种方法 法一 下载cmake二进制安装包 配置路径 亲测有效 法二 cmake源码编译 注意和法一区别 法三 apt安装 法四 在原基础上升级版本 法五 ppa安装 1 问题描述 在配置OpenMVS时 报
  • ld 链接程序出错定位

    工具链相关问题 一般可 verbose 下 看看具体什么地方出问题 设置 LDFLAGS Wl verbose 例如 链接一堆 o文件 只有以下错误信息 ld final link failed Bad value 就可以加入 Wl ver
  • linux进程间通信---本地socket套接字(一)---一个server对应一个client

    先给自己打个广告 本人的微信公众号正式上线了 搜索 张笑生的地盘 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 想要获取完整源码的 关注公众号后回复 socket1 即
  • Linux gdm问题解决解决

    修改 etc inittab 改变runlevel为5 例如 root QRedHat etc cat etc inittab id 5 initdefault 修改GDM的配置文件 etc X11 gdm gdm conf 将 xdmcp
  • Linux入坑教程

    服务器安装所需环境 Linux 一 安装基础环境 1 1 JDK 1 2 Mysql 1 3 FastDFS 1 4 Redis 1 5 GIT 1 6 Node 二 Basic commands 基础命令 2 1 查询命令 2 1 1 查
  • ssh免密登录,各种权限设置都无效的解决办法!

    如果失败 有可能是以下原因 1 权限问题 这个还得试试 有可能你的权限真的不对 ssh目录 以及 home 当前用户 需要700权限 参考以下操作调整 sudo chmod 700 ssh sudo chmod 700 home 当前用户
  • linux设置系统时间

    我们一般使用 date s 命令来修改系统时间 比如将系统时间设定成20066年10月19日的命令如下 date s 10 19 2006 将系统时间设定成下午1点12分0秒的命令如下 date s 13 12 00 注意 这里说的是系统时
  • 臻识车牌识别摄像头对接

    一 臻识车牌识别摄像头 1 非常有用的官方代码 内部有TCP HTTP等协议 2 官方常见问题 3 官方下载专区 二 http对接例子 1 自己使用java mock 模拟后台服务 你会用到的配置文件 java jar moco runne
  • Linux sh命令

    sh a c C e E f h i I k m n p r s t T u v x argument a Export all variables assigned to c Pass the string argument to the
  • linux系统之字符设备驱动——IIC驱动mma8451q

    linux系统之字符设备驱动 IIC子系统驱动mma8451q 1 原理图 2 驱动程序 mma8451q c Author your name Date 2021 02 23 22 16 37 LastEditTime 2021 02 2
  • docker教程:从头基于空镜像scratch创建一个新的Docker镜像

    从头基于空镜像scratch创建一个新的Docker镜像 我们在使用dockerfile构建镜像时 一种方式是使用预制镜像 这样可以省很多工作量 但问题是镜像会变得特别大 尤其是安装一些应用程序所需的依赖后 镜像的尺寸会更大 如果我们的需求
  • CentOS8 MySQL 主主模式+keepalived高可用环境搭建非docker版

    概述 采用了MySQL KeepAlived实现MySQL高可用 旨在当主机发生宕机等异常情况时 使用备机的MySQL服务 以此保证系统服务的高可用 这套环境的搭建过程中 需要注意的事项如下 1 MySQL是否数据同步 在大批量数据写入的情
  • Linux系统图形界面,字符界面切换快捷键。启动图形界面服务。

    Ctrl Alt F3 启动字符界面 Ctrl Alt F7 启动图形界面 启动图形界面服务 cd etc init d service lightdm restart
  • Fedora 启动顺序

    http hi baidu com wwwkljoel item 29620217882a585b2b3e2244 The start of the Fedora fedora 系统加电或复位后 中央处理器将内存中的所有数据清零 并对内存进
  • makeinfo: command not found解决方法

    sudo apt get install texinfo
  • 【自用】深度学习工作站安装ubuntu 18.04 LTS系统

    工作站配置 自己组装的 主板 华硕Z790P PCIE插槽间距大 可以装双显卡 CPU i5 13600KF 内存 32 G 显卡 GTX 2080 Ti 魔改版 22G 存储 1T SSD 8T机械硬盘 系统 ubuntu 18 04 L
  • Windows挂载Linux网络共享文件夹

    Windows挂载Linux网络共享文件夹 创建Linux网络共享文件夹 用共享工具samba Ubuntu安装samba sudo apt install samba 配置Windows访问共享文件夹的账户 smbpasswd a riv
  • Fedora 10網卡消失的問題

    http itgroup blueshop com tw towns hc n convew i 6000 今天看到肉鬆Selinux的問題 想說來測試處理一下 將以備份出來的Fedora 10 VM拿出來用 啟動系統後 出現了一個怪問題
  • Linux进程间通信--使用命名管道

    Linux进程间通信 使用命名管道 一 什么是命名管道 命名管道也被称为FIFO文件 它是一种特殊类型的文件 它在文件系统中以文件名的形式存在 但是它的行为却和之前所讲的没有名字的管道 匿名管道 类似 由于Linux中所有的事物都可被视为文

随机推荐

  • php自动验证,ThinkPHP 自动验证及验证规则详解

    ThinkPHP 自动验证 ThinkPHP 内置了数据对象的自动验证功能来完成模型的业务规则验证 自动验证是基于数据对象的 而大多情况下数据对象是基于 POST表单 不是绝对的 创建的 基本的自动验证功能包括 必须字段 email邮箱格式
  • 使用 ChatGPT、Stable Diffusion、React 和 NodeJS 构建网站画廊

    TLDR 在本文中 您将学习如何构建一个 Web 应用程序 该应用程序使用 ChatGPT 和 Stable Diffusion 为您提供的任何网站描述生成徽标和合适的域名 介绍 人工智能正在接管世界 这些技术每天都在震撼着我们的世界 Ch
  • 家里用服务器放在哪个位置,路由器摆放在家中哪个位置好 路由器摆放位置【详解】...

    路由器摆放在家中哪个位置好 路由器的摆放位置其实非常讲究的 这里就给大家讲解下相关知识 一起来看看 其实wifi所发射的信号 也就是无线电波 向手机和收音机发射出的电磁波是一样的 但是呢wifi的信号相当的短 一般常见的话只有12公分左右
  • Windows Server 系列 - User logon name(pre-Windows 2000) 和 User logon name 的区别

    一 在Active Directory中一直疑惑User logon name pre Windows 2000 和 User logon name这两个字段的区别 详细如下 AD UI界面展示名称 AD 后端属性名称 User logon
  • 使用Composition API和setup语法糖重构Vue组件

    Vue3 引入了Composition API 它是一种更灵活的方式来组织和复用组件的逻辑 而不是依赖于传统的选项式API 如data methods computed等 Composition API的核心是一个名为setup的函数 它可
  • 如何在github上重命名或修改文件夹

    在github上整理流程的时候 有一个文件夹命名不合适 想返回去改 但是在网页上没有找到重命名文件夹的选项 经过一番折腾之后 我是这么做的 1 首先在服务器上找到公匙 公匙在 ssh目录下 以 pub结尾的文件 将其复制 2 在github
  • markdown基本用法

    标题 和 都可以用于表示标题 一级标题 二级标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 标题的前后都要空一行 号后应当加一个空格 和 应当顶格书写 建议使用 来表示标题 字体 斜体 斜体 加粗 粗体 斜体 加粗 斜体
  • OpenCV中的人脸活体检测和身份认证如何实现?OpenCV人脸识别

    本文将介绍如何在OpenCV中实现人脸活体检测和身份认证 结合人脸检测 关键点定位和深度学习模型 我们可以有效地检测和区分真实人脸和照片 视频等非真实生物特征 以实现可靠的身份认证和活体检测 人脸检测和关键点定位 使用OpenCV提供的人脸
  • [STM32学习笔记(一)] 如何安装keil5 MDK版本并安装C51

    文章目录 1 注意事项 2 安装流程 2 1 获取Keil5安装包 2 2 安装keil5 2 3破解keil5 MDK 2 4 安装STM32芯片包 3 在安装了mdk的基础上安装c51 1 注意事项 安装路径必须全部是英文 如果已经安装
  • 突破前端反调试:阻止页面无限不断debugger

    不知道你们有没有遇到过上图这样 有时候想调试网站 一打开开发者工具立即 debugger 而且跳过了还是会继续 或者是有时候在调试网页时 突然就给你来一个 debugger 接着就是反复来回 debugger 了 贼烦 那今天分享个教程 教
  • Spock1

    文章目录 背景 扩展 BDD Behavior driven development行为驱动测试 依赖 Demo Spock深入 结构 setup与given assert 异常断言 Mock 创建对象 注入对象 调用频率约束 目标约束 方
  • Nacos-2.1.1安装配置+集群

    Nacos安装配置 集群 nacos 2 1 1安装配置 集群 Linux 一 环境准备 二 Nacos安装 运行 单机 三 替换nacos内置数据源 四 nacos集群配置 nacos 2 1 1安装配置 集群 Linux 本篇博客用于记
  • linux 启动盘zhi,Linux制作启动盘之dd命令详解

    1 dd命令简介 dd在linux中是 一个非常强大的工具 常用于复制大量数据 测试读写性能 清空硬盘数据 不可恢复 由于dd 命令允许以二进制方式读写 所以特别适合在原始设备上输入 输出 dd命令用于复制文件并对原文件的内容进行转换和格式
  • Windows 通过CMD窗口利用mybatis-generator连接Oracle快速生成代码

    环境说明 Windows10 JDK8 ojdbc6 11 2 0 4 jar mybatis generator core 1 3 7 jar 1 在C盘新建autoMybatis文件夹 文件夹中新建generator xml文件 并将o
  • bzoj3309 DZY Loves Math

    题目链接 bzoj3309 题目大意 对于正整数n 定义f n 为n所含质因子的最大幂指数 给定正整数a b 求 ai 1 bj 1f gcd i j sum i 1 a sum j 1 b f gcd i j T lt 10000 1 l
  • Android系统中设置TextView的行间距

    Android系统中TextView默认显示中文时会比较紧凑 不是很美观 为了让每行保持一定的行间距 可以设置属性android lineSpacingExtra或android lineSpacingMultiplier 1 设置行间距
  • Echarts中X轴label间隔显示=>interval

    项目中我们经常都会遇到大量数据 需要我们的echarts来展示 但是我们的X轴的label是长度是有限的 在大量数据的传递下必然出现label重叠 这个时候我们就要用到interval如图 通过设置xAxis中的axisLabel inte
  • OpenMP和OpenACC

    OpenMP OpenMP是CPU的并行编程模型 它使用编译器指令来识别并行区域 omp set num threads n streams 用来指定要用到的CPU线程数 类似于设置环境变量 pragma omp parrallel 标记代
  • 使用openMVS对样例数据进行重建

    openMVS根据github上的步骤进行编译 注意 如果没有GPU 用不了CUDA的话 那么需要在openMVS目录下找到CmakeLists txt文件 把CUDA设置为OFF SET OpenMVS USE CUDA OFF CACH
  • linux系统之字符设备驱动——IIC驱动mma8451q

    linux系统之字符设备驱动 IIC子系统驱动mma8451q 1 原理图 2 驱动程序 mma8451q c Author your name Date 2021 02 23 22 16 37 LastEditTime 2021 02 2