STM32MP157A-FSMP1A单片机移植Linux系统I2C总线驱动

由于I2C总线驱动为Linux内核自带的总线驱动,在一个新的板子上可能由于不同的定义与芯片原厂定义的I2C管脚有所不同,这时就需要开发人员对设备树信息及内核驱动进行更新。

原理图可知,I2C的SCL对应PF14,SDA对应PF15

在Linux内核中,arch/arm/boot/dts/  设备树文件 --> stm32mp157a-fsmp1a.dts,I2C对应的GPIO复用信息 --> stm32mp15-pinctrl.dtsi。

 驱动程序代码

#include <linux/init.h>       // 包含内核初始化相关的头文件
#include <linux/module.h>     // 包含内核模块相关的头文件
#include <linux/of.h>         // 包含设备树操作相关的头文件
#include <linux/gpio.h>       // 包含 GPIO 操作相关的头文件
#include <linux/of_gpio.h>    // 包含设备树 GPIO 相关的头文件
#include <linux/fs.h>         // 包含文件操作相关的头文件
#include <linux/uaccess.h>    // 包含用户空间访问内核空间相关的头文件
#include <linux/device.h>     // 包含设备相关的头文件
#include <linux/i2c.h>   // 包含 I2C 相关的头文件
#include "i2c_test.h"    // 包含自定义头文件//创建设备号
static int major;
//创建类
static struct class *cls;
//创建设备
static struct device *device;
//创建i2c_client
static struct i2c_client *client;
//保存字符设备数据
static char i2c_buf[100];//获取温湿度数据
int get_hum_tem(int reg)
{int ret = 0;char r_buf  = reg;short value;struct i2c_msg r_msg[] ={[0] = {.addr = client->addr,.flags = 0,.len = 1,.buf = &r_buf,},[1] = {.addr = client->addr,.flags = 1,.len = 2,.buf = (u8 *)&value,},};//发送读取温湿度数据的命令ret = i2c_transfer(client->adapter, r_msg, 2);if(ret != 2){printk("i2c_transfer failed\n");return ret;}return value;
} //end of get_hum_temstatic int led_open(struct inode *inode, struct file *file)
{unsigned int cmajor;//保存次设备号cmajor = iminor(inode);//将次设备号保存到file结构体的private_data中file->private_data = (void *)cmajor;printk("led_open\n");return 0;
}static int led_close(struct inode *inode, struct file *file)
{printk("led_close\n");return 0;
}static int led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{unsigned int ret;//从内核空间读取数据到用户空间,如果读取数据的长度大于i2c_buf的长度,按照最大长度读取if(count > sizeof(i2c_buf)){count = sizeof(i2c_buf);}ret = copy_to_user(buf, i2c_buf, count);if(ret < 0){printk("copy_to_user failed\n");return -1;}printk("led_read\n");return 0;
}static int led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{unsigned int ret;//将用户空间的数据拷贝到内核空间,如果传输数据的长度大于i2c_buf的长度,按照最大长度传输if (count > sizeof(i2c_buf)){count = sizeof(i2c_buf);}ret = copy_from_user(i2c_buf, buf, count);if (ret < 0){printk("copy_from_user failed\n");return -1;}printk("led_write\n");return 0;
}static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{int hum = 0, tem = 0;//写入用户空间switch(cmd){case GET_HUM:hum = get_hum_tem(0xE5);copy_to_user((int *)arg, &hum, 4);break;case GET_TEM:tem = get_hum_tem(0xE3);copy_to_user((int *)arg, &tem, 4);break;default:break;}printk("led_ioctl\n");return 0;
}//定义file_operations结构体
struct file_operations fops = {.owner = THIS_MODULE,.open = led_open,.release = led_close,.read = led_read,.write = led_write,.unlocked_ioctl = led_ioctl,
};//编写i2c设备驱动
static int myi2c_probe(struct i2c_client *pdev, const struct i2c_device_id *id)
{printk("myi2c_probe\n");client = pdev;//1.创建设备号major = register_chrdev(0, "myi2c", &fops);if (major < 0){printk("register_chrdev failed\n");return -1;}//2.创建类cls = class_create(THIS_MODULE, "myi2c");if (IS_ERR(cls)){printk("class_create failed\n");unregister_chrdev(major, "myi2c");return -1;}//3.创建设备device = device_create(cls, NULL, MKDEV(major, 0), NULL, "myi2c");if (IS_ERR(device)){printk("device_create failed\n");class_destroy(cls);unregister_chrdev(major, "myi2c");return -1;}return 0;
}static int myi2c_remove(struct i2c_client *pdev)
{printk("myi2c_remove\n");    device_destroy(cls, MKDEV(major, 0));class_destroy(cls);unregister_chrdev(major, "myi2c");return 0;
}static const struct of_device_id myplatform_test_match_table[] = {{ .compatible = "johnson,si7006", },{ /* sentinel */ }
};struct i2c_driver myi2c_driver = {.probe = myi2c_probe,.remove = myi2c_remove,.driver = {.name = "myi2c_slave",.of_match_table = myplatform_test_match_table,},
};//一键注册宏定义
module_i2c_driver(myi2c_driver);
MODULE_LICENSE("GPL");

头文件

#ifndef __I2CTEST_H__
#define __I2CTEST_H__#define GET_HUM _IOR('i', 1, int)
#define GET_TEM _IOR('i', 0, int)#endif

应用程序 --> 实现通过I2C获取温湿度数据

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include "i2c_test.h"int main()
{int hum = 0, tem = 0;float hum1, tem1; // 保存计算完毕后的温湿度数据int fd = 0;//打开设备文件fd = open("/dev/myi2c", O_RDWR);if (fd < 0){printf("open failed\n");return -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 = tem * 175.72 / 65536 - 46.85;printf("hum = %f, tem = %f\n", hum1, tem1);sleep(1);}   //关闭设备文件close(fd);return 0;
}

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

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

相关文章

My first Android application

界面元素组成&#xff1a; 功能代码&#xff1a; /*实现功能&#xff1a;当输入内容后&#xff0c;欢迎文本发生相应改变&#xff0c;并清除掉文本域内容当未输入任何内容时&#xff0c;弹出提示文本以警告用户*/val greetingText findViewById<TextView>(R.id.printer)…

深度学习基础--ResNet网络的讲解,ResNet50的复现(pytorch)以及用复现的ResNet50做鸟类图像分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 如果说最经典的神经网络&#xff0c;ResNet肯定是一个&#xff0c;这篇文章是本人学习ResNet的学习笔记&#xff0c;并且用pytorch复现了ResNet50&…

【DeepSeek】【GPT-Academic】:DeepSeek集成到GPT-Academic(官方+第三方)

目录 1 官方deepseek 1.1 拉取学术GPT项目 1.2 安装依赖 1.3 修改配置文件中的DEEPSEEK_API_KEY 2 第三方API 2.1 修改DEEPSEEK_API_KEY 2.2 修改CUSTOM_API_KEY_PATTERM 2.3 地址重定向 2.4 修改模型参数 2.5 成功调用 2.6 尝试添加一个deepseek-r1参数 3 使用千帆…

用Golang与WebAssembly构建高性能Web应用:详解`syscall/js`包

用Golang与WebAssembly构建高性能Web应用&#xff1a;详解syscall/js包 引言为什么选择syscall/js包&#xff1f;适用场景 syscall/js包概述syscall/js包的核心概念1. js.Global2. js.Value3. js.Func4. js.Null 和 js.Undefined syscall/js包在WebAssembly中的位置 环境配置与…

本地部署轻量级web开发框架Flask并实现无公网ip远程访问开发界面

文章目录 1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 本篇文章主要讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网进行远程访问。 Flask是目前十分流行的web框架&#xff0c;采用Python编程…

ChatGPT背后的理论基础:从预训练到微调的深度解析

友情提示&#xff1a;本文内容由银河易创&#xff08;https://ai.eaigx.com&#xff09;AI创作平台GPT-4o-mini模型生成&#xff0c;仅供参考。请根据具体情况和需求进行适当的调整和验证。 随着人工智能特别是自然语言处理技术的飞速发展&#xff0c;ChatGPT作为一种强大的对话…

2025面试Go真题第一场

前几天参加了一场面试&#xff0c;GoLang 后端工程师&#xff0c;他们直接给了我 10 道题&#xff0c;我留了一个截图。 在看答案之前&#xff0c;你可以先简单做一下&#xff0c;下面我会对每个题目做一个说明。 文章目录 1、golang map 是否并发安全?2、协程泄漏的原因可能是…

网络安全第三次练习

一、实验拓扑 二、实验要求 配置真实DNS服务信息&#xff0c;创建虚拟服务&#xff0c;配置DNS透明代理功能 三、需求分析 1.创建用户并配置认证策略 2.安全策略划分接口 3.ip与策略配置 四、实验步骤 1.划分安全策略接口 2.创建用户并进行策略认证 3.配置安全策略 4.NAT配…

FTP 实验(ENSP模拟器实现)

目录 FTP 概述 FTP实验 FTP的报文交互 FTP 概述 FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;是一种用于在网络上进行文件传输的标准协议。它允许用户在两台计算机之间上传和下载文件。 1、FTP采用客户端-服务器模型&#xff0c;客户端通过…

Elasticsearch:使用经过训练的 ML 模型理解稀疏向量嵌入

作者&#xff1a;来自 Elastic Dai Sugimori 了解稀疏向量嵌入&#xff0c;理解它们的作用/含义&#xff0c;以及如何使用它们实现语义搜索。 Elasticsearch 提供语义搜索功能&#xff0c;允许用户使用自然语言进行查询并检索相关信息。为此&#xff0c;目标文档和查询必须首先…

Java进阶(vue基础)

目录 1.vue简单入门 ?1.1.创建一个vue程序 1.2.使用Component模板(组件&#xff09; 1.3.引入AXOIS ?1.4.vue的Methods&#xff08;方法&#xff09; 和?compoted&#xff08;计算&#xff09; 1.5.插槽slot 1.6.创建自定义事件? 2.Vue脚手架安装? 3.Element-UI的…

密码学基础

第1节 密码学概述 密码是人类在信息活动中的一项伟大发明&#xff0c;是保护秘密信息的工具。它诞生于公元前两千余年的埃及&#xff0c;迄今已有四千多年的历史。在出现年代有可查证记录的科学技术中&#xff0c;密码是历史最为悠久的科学技术之一。 百度百科里对密码的解释&…

Java入门级小案例:网页版简易计算器

网页版简易计算器 目录 网页版简易计算器需求&#xff1a;代码实现&#xff1a;效果显示 需求&#xff1a; 用HTML、CSS、JS进行书写一个具备一定功能的简易计算器。 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta cha…

【Uniapp-Vue3】导入uni-id用户体系

在uniapp官网的uniCloud中下载uni-id用户体系 或者直接进入加载&#xff0c;下载地址&#xff1a;uni-id-pages - DCloud 插件市场 进入以后下载插件&#xff0c;打开HbuilderX 选中项目&#xff0c;点击确定 点击跳过 点击合并 右键uniCloud文件夹下的database文件夹&#x…

Python 入门教程(2)搭建环境 | 2.3、VSCode配置Python开发环境

文章目录 一、VSCode配置Python开发环境1、软件安装2、安装Python插件3、配置Python环境4、包管理5、调试程序 前言 Visual Studio Code&#xff08;简称VSCode&#xff09;以其强大的功能和灵活的扩展性&#xff0c;成为了许多开发者的首选。本文将详细介绍如何在VSCode中配置…

Spring Boot电影评论网站系统设计与实现

随着互联网和娱乐产业的发展&#xff0c;电影评论网站逐渐成为人们分享观影体验、交流影评的重要平台。本文将介绍一个基于Spring Boot框架开发的电影评论网站系统的功能设计与实现方案。 功能模块概述 该电影评论网站系统分为管理员模块和用户模块两大核心部分&#xff0c;以…

RT-Thread+STM32L475VET6——TF 卡文件系统

文章目录 前言一、板载资源二、具体步骤1.打开CubeMX进行USB配置1.1 使用外部高速时钟&#xff0c;并修改时钟树1.2 打开SPI1&#xff0c;参数默认即可(SPI根据自己需求调整&#xff09;1.3 打开串口&#xff0c;参数默认1.4 生成工程 2.配置SPI2.1 打开SPI驱动2.2 声明使用SPI…

LabVIEW形状误差测量系统

在机械制造领域&#xff0c;形状与位置公差&#xff08;GD&T&#xff09;直接影响装配精度与产品寿命。国内中小型机加工企业因形状误差导致的返工率高达12%-18%。传统测量方式存在以下三大痛点&#xff1a; ​ 设备局限&#xff1a;机械式千分表需人工读数&#xff0c;精度…

【c语言】字符函数和字符串函数(1)

一、字符分类函数 c语言中有部分函数是专门做字符分类的&#xff0c;也就是一个字符是属于什么类型的字符&#xff0c;这些函 数的使用要包含一个头文件ctype.h中。 其具体如下图所示&#xff1a; 这些函数的使用方式都类似&#xff0c;下面我们通过一个函数来看其…

【Python LeetCode 专题】动态规划

斐波那契类型70. 爬楼梯746. 使用最小花费爬楼梯198. 打家劫舍740. 删除并获得点数矩阵62. 不同路径方法一:二维 DP方法二:递归(`@cache`)64. 最小路径和63. 不同路径 II120. 三角形最小路径和221. 最大正方形字符串139. 单词拆分5. 最长回文子串516. 最长回文子序列72. 编…