驱动开发11 编写iic驱动-读取温湿度数据

头文件 head.h

#ifndef __HEAD_H__
#define __HEAD_H__
#define GET_HUM _IOR('m', 1, int)
#define GET_TEM _IOR('m', 0, int)
#endif

应用程序 si7006.c

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

int main(int argc, char const *argv[])
{
    char buf[128]={0};
    unsigned short hum,tem;
    float hum1,tem1;
    int fd = open("/dev/si7006",O_RDWR);
    if(fd < 0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        //读取温湿度数据
        ioctl(fd,GET_HUM,&hum);
        ioctl(fd,GET_TEM,&tem);
        //进行字节序转换
        hum = ntohs(hum);
        tem = ntohs(tem);
        //数据转换
        hum1 = (float)hum*125/65536-6;
        tem1 = (float)tem*175.72/65536-46.85;
        printf("hum = %f    tem = %f\n",hum1,tem1);
        sleep(1);
    }
    close(fd);
    return 0;
}

驱动程序 iic.c

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

struct i2c_client *client1;
unsigned int major;
struct class *cls;
struct device *dev;
//封装读取温湿度数据的函数
short read_hum_tem_value(char reg)
{
    short value; //保存读到的温湿度数据
    char r_buf[] = {reg};
    //消息结构体的封装
    struct i2c_msg r_msg[] = {
        [0] = {
            .addr = client1->addr,
            .flags = 0,
            .len = sizeof(r_buf),
            .buf = r_buf,
        },
        [1] = {
            .addr =client1->addr,
            .flags = 1,
            .len = 2,
            .buf = (char *)&value,
        },
    };
    //发送消息
    int ret = i2c_transfer(client1->adapter,r_msg,2);
    if(ret != 2)
    {
        printk("消息传输失败\n");
        return -1;
    }
    return value;
}
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)
{
    short hum,tem;
    int ret;
    switch ((cmd))
    {
    case GET_HUM:
        hum = read_hum_tem_value(0xE5);
        ret = copy_to_user((void *)arg,&hum,2);
        if(ret)
        {
            printk("coyp_to_user err %d\n",__LINE__);
        }
        break;
    case GET_TEM:
        tem = read_hum_tem_value(0xE5);
        ret = copy_to_user((void *)arg,&tem,2);
        if(ret)
        {
            printk("coyp_to_user err %d\n",__LINE__);
        }
        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 i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    client1 = client;
    int ret;
    //float hum1,tem1;
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    //字符设备驱动的注册
    major = register_chrdev(0,"si7006",&fops);
    if(major < 0)
    {
        printk("字符设备驱动注册失败\n");
        ret = major;
        goto out1;
    }
    printk("字符设备驱动注册成功\n");
    //向上提交目录
    cls = class_create(THIS_MODULE,"si7006");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret = -PTR_ERR(cls);
        goto out2;
    }
    printk("向上提交目录成功\n");
    //向上提交设备节点信息
    dev = device_create(cls,NULL,MKDEV(major,0),NULL,"si7006");
    if(IS_ERR(dev))
    {
        printk("向上提交设备节点失败\n");
        ret = -PTR_ERR(dev);
        goto out3;
    }
    printk("向上提交设备节点成功\n");
    return 0;
out3:
    class_destroy(cls);
out2:
    unregister_chrdev(major,"si7006");
out1:
    return ret;
}
int i2c_remove(struct i2c_client *client)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    //设备信息的注销
    device_destroy(cls,MKDEV(major,0));
    //设备节点的销毁
    class_destroy(cls);
    //驱动的注销
    unregister_chrdev(major,"si7006");
    return 0;
}
//定义设备树匹配的表
struct of_device_id oftable[]={
    {.compatible="hqyj,si7006",},
    {},
};
struct i2c_driver i2c_drv={
    .probe=i2c_probe,
    .remove=i2c_remove,
    .driver={
        .name="si7006",
        .of_match_table=oftable,
    },
};
module_i2c_driver(i2c_drv);
MODULE_LICENSE("GPL");

效果演示

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高效学习工具之AnkiMobile新手入门指南(ios端,包括ipad、ihpone设备)————创建、使用、备份、设置参数、相关资料

文章目录 0 背景0.1 闭环学习0.2 什么是anki0.3 anki践行者经验分享 1 开始使用1.1 导入1.2 创建空白组1.3 创建卡片1.3.1 利用anki创建卡片的两种方法1.3.2 复习材料分类 1.4 筛选&#xff08;做减法&#xff0c;拆分学习&#xff08;做子卡牌集合&#xff09;&#xff09;&am…

4.1 继承

思维导图&#xff1a; 第4章 面向对象(下) 学习目标: 了解面向对象中的继承特性&#xff0c;掌握继承的概念与特点。掌握方法的重写&#xff0c;能够在子类中重写父类方法。掌握super关键字&#xff0c;明白如何在类中使用super访问父类成员。理解final关键字的作用&#xff0…

微信小程序如何使用地球半径计算两组经纬度点之间的距离(自身位置与接口返回位置)【上】

目录 1.配置位置权限 2.获取当前自身经纬度 3. 请求接口拿到返回经纬 4. 循环取每一项的经纬 5.如何判断是否打开了定位权限 6.进行距离计算操作 7.运行效果 8.完整代码 首先在使用小程序时&#xff0c;请求的接口一定要去配置合法域名&#xff0c;才能够进行接下来…

缓存击穿只会逻辑过期 OR 互斥锁?深入思考 == 鹤立鸡群

网上但凡看得见的文章&#xff0c;大部分在说缓存穿透时都是无脑分布式锁 / 逻辑过期&#xff0c;分布式锁一点问题都没有么&#xff1f;逻辑过期一点问题都没有么&#xff1f;还能不能再进一步优化&#xff1f; 在聊聊缓存击穿的双重判定锁之前&#xff0c;我们将按照循循渐进…

双十一首日捷报 | 德施曼率先破亿,再度蝉联智能锁品类第一

10月31日晚8:00&#xff0c;各大平台迎来了双十一第一波现货开售。其中&#xff0c;在智能锁类目中德施曼势头最为迅猛&#xff0c;此前&#xff0c;德施曼凭借“全民换锁季”主题活动&#xff0c;在预售期间就已经全面引爆消费者换锁热潮&#xff0c;随着此次现货开售&#xf…

cut 命令

cut [选项参数] filename #默认分隔符是制表符 选项参数&#xff1a; -d delimiter 分隔符 -f field 场地、领域&#xff08;第几列&#xff09; 命令使用&#xff1a; cut -d " " -f 1 cut.txt #空格为分隔符截取第1列cut -d " " -f 2,3 cut.txt #截…

百度上传自己个人简介攻略,个人介绍百度百科怎么做?

个人介绍要展示在百度百科上该怎么操作&#xff0c;我们都清楚百度百科词条是需要申请才能拥有的&#xff0c;但是没有百度上传自己个人简介的攻略&#xff0c;很多人是不知从何下手的。下面洛希爱做百科网带着大家一起来了解。 一、了解百度百科词条的创建规则 1. 词条名称规…

jdk官网下载(详细步骤)

jdk全部版本下载网址 Java Archive | Oraclehttps://www.oracle.com/java/technologies/downloads/archive/ 下载之前先建立oracle账号(免费创建)&#xff0c;不用特意去搜&#xff0c;你点击下载jdk的时候会自动弹出来&#xff0c;自己建立一个账号就能下载了 找到自己要下载…

【产品体验】OA办公系统

一、演示地址 http://admin.dianshixinxi.com:90/index 二、办公管理功能 1.我的待办&#xff1a;当前登录用户&#xff0c;办理任务 2.通知公告&#xff1a;通知与公告&#xff0c;已发布通知公告会显示在首页 3.自定义表单&#xff1a;自定义表单&#xff0c;托拉拽的形式…

iZotope RX 10(音频修复和增强工具)

iZotope RX 10是一款音频修复和增强软件&#xff0c;主要特点包括&#xff1a; 声音修复&#xff1a;iZotope RX 10可以去除不良噪音、杂音、吱吱声等&#xff0c;使音频变得更加清晰干净。音频增强&#xff1a;iZotope RX 10支持对音频进行音量调节、均衡器、压缩器、限制器等…

IDEA 使用技巧

文章目录 语言支持简化编写 有问题&#xff0c;可暂时跳过 个人常用快捷键插件主题插件功能插件 碰到过的问题 除了一些在Linux上用vim开发的大佬&#xff0c;idea算是很友好的集成开发工具了&#xff0c;功能全面&#xff0c;使用也很广泛。 记录一下我的 IDEA 使用技巧&#…

解密人工智能:KNN | K-均值 | 降维算法 | 梯度Boosting算法 | AdaBoosting算法

文章目录 一、机器学习算法简介1.1 机器学习算法包含的两个步骤1.2 机器学习算法的分类 二、KNN三、K-均值四、降维算法五、梯度Boosting算法和AdaBoosting算法六、结语 一、机器学习算法简介 机器学习算法是一种基于数据和经验的算法&#xff0c;通过对大量数据的学习和分析&…

虹科示波器 | 汽车免拆检修 | 2013款大众途观车发动机加速无力

一、故障现象 一辆2013款大众途观车&#xff0c;搭载CGM发动机&#xff0c;累计行驶里程约为12.6万km。车主进厂反映&#xff0c;发动机加速无力。 二、故障诊断 接车后试车&#xff0c;发动机怠速运转正常&#xff1b;原地将加速踏板踩到底&#xff0c;发动机转速最高只能达到…

AQS面试题总结

一&#xff1a;线程等待唤醒的实现方法 二&#xff1a; 介绍一下LockSupport 三&#xff1a;AQS是什么 AQS使用一个volatile的int类型的成员变量来表示同步状态&#xff0c;通过内置的FIFO队列完成资源获取排队工作&#xff0c;将每条要去抢占资源的线程封装成一个NODE节点来…

抛开八股——实际业务下如何设计缓存与数据库一致性解决方案

前言 对于缓存与数据库一致性的八股文也是老生常谈了&#xff0c;但是所谓没有最好的方案&#xff0c;只有最合适的方案&#xff0c;如果我们一味的去硬啃八股文&#xff0c;很容易就丧失了对于业务的基本分析能力&#xff0c;更别说针对业务来设计出合理合适的解决方案&#x…

Flutter笔记:完全基于Flutter绘图技术绘制一个精美的Dash图标(下)

Flutter笔记 完全基于Flutter绘图技术绘制一个精美的Dart吉祥物Dash 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/arti…

2015年亚太杯APMCM数学建模大赛A题海上丝绸之路发展战略的影响求解全过程文档及程序

2015年亚太杯APMCM数学建模大赛 A题 海上丝绸之路发展战略的影响 原题再现 一带一路不是实体或机制&#xff0c;而是合作与发展的理念和主张。凭借现有有效的区域合作平台&#xff0c;依托中国与有关国家现有的双边和多边机制&#xff0c;利用古丝绸之路的历史象征&#xff0…

如何看待将本增效?

如何看待将本增效&#xff1f; 么是降本增效&#xff1f;就是公司里&#xff0c;增进收益的动作要多做&#xff0c;无效的动作要少做&#xff0c;甚至不做。什么叫有效&#xff1f;回到公司的经营目标上去&#xff0c;企业的管理就是目标管理。降本&#xff0c;需要卓越运营&a…

reese84

网址:https://beta.makeabooking.flyscoot.com/ 这个基本上会在航空网站上出现&#xff0c;国内的我也没见过&#xff0c;然后这个是我很早很早之前的老友分享的&#xff0c;然后昨天花时间去看了一下&#xff0c;之前经常听其他大佬说&#xff0c;但是我也出来没遇见过。 感觉…

损坏的视频不能观看,还能修复吗?

3-1 在日常的生活或者工作中&#xff0c;特别是做摄像工作的人&#xff0c;有一定的概率会遇到损坏的视频文件&#xff0c;比如相机突然断电、无人机炸机等&#xff0c;都有可能导致保存的视频文件损坏。 如果遇到这种情况&#xff0c;该如何修复这种损坏的视频文件&#xff…