当前位置: 首页 > news >正文

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

SPI总线驱动整体上与I2C总线驱动类型,差别主要在设备树和数据传输上,由于SPI是由4根线实现主从机的通信,在设备树上配置时需要对SPI进行设置。

原理图可知,数码管使用的SPI4对应了单片机上的PE11-->SPI4-NSS,PE12-->SPI4-SCK,PE13-->SPI4-MISO,PE14-->SPI4-MOSI

设备树信息

需要注意在SPI4设备树信息中,一定要加spi-max-frequency属性,该属性用于设置spi的主频,如果没有,可能出现无法正常启动spi或启动spi后控制数码管时,数码管显示出现错位现象

驱动源码

#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/cdev.h>       // 包含字符设备相关的头文件
#include <linux/slab.h>       // 包含内存分配相关的头文件
#include <linux/spi/spi.h>    // 包含 SPI 相关的头文件
#include "spi_test.h"    // 包含自定义头文件//创建设备号
static int major;
//创建类
static struct class *cls;
//创建设备
static struct device *device;
//创建SPI设备
static struct spi_device *spi_dev;
//保存字符设备数据
static char spi_buf[128];static int myspi_open(struct inode *inode, struct file *file)
{unsigned int cmajor;//保存次设备号cmajor = iminor(inode);//将次设备号保存到file结构体的private_data中file->private_data = (void *)cmajor;printk("spi_open\n");return 0;
}static int myspi_close(struct inode *inode, struct file *file)
{printk("spi_close\n");return 0;
}static ssize_t myspi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{unsigned int ret;//从内核空间读取数据到用户空间,如果读取数据的长度大于spi_buf的长度,按照最大长度读取if(count > sizeof(spi_buf)){count = sizeof(spi_buf);}ret = copy_to_user(buf, spi_buf, count);if(ret < 0){printk("copy_to_user failed\n");return -1;}printk("spi_read\n");return 0;
}static ssize_t myspi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{unsigned int ret;//将用户空间的数据拷贝到内核空间,如果传输数据的长度大于spi_buf的长度,按照最大长度传输if (count > sizeof(spi_buf)){count = sizeof(spi_buf);}ret = copy_from_user(spi_buf, buf, count);if (ret < 0){printk("copy_from_user failed\n");return -1;}printk("spi_write\n");return 0;
}static int myspi_write_data(const uint8_t cmd, const uint8_t data)
{uint8_t spi_buf1[2] = {cmd, data};int ret = 0;printk("cmd = %x\n", spi_buf1[0]);ret = spi_write(spi_dev, spi_buf1, 2);return ret;
}static long myspi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{uint8_t data;unsigned long ret ;//从用户空间读取数据ret = copy_from_user(&data, (void *)arg, sizeof(data));if (ret < 0){printk("copy_from_user failed\n");return -1;}//根据cmd的值进行不同的操作    switch (cmd){case SET_DAT0:ret = myspi_write_data(0x01, data);break;case SET_DAT1:ret = myspi_write_data(0x02, data);break;case SET_DAT2:ret = myspi_write_data(0x04, data);break;case SET_DAT3:ret = myspi_write_data(0x08, data);break; case SET_DAT4:ret = myspi_write_data(0x0f, data);break;default:break;}if (ret != 0){printk("spi_write failed\n");return -1;}printk("spi_ioctl, data = %x\n", data);return 0;
}//定义file_operations结构体
struct file_operations fops = {.owner = THIS_MODULE,.open = myspi_open,.release = myspi_close,.read = myspi_read,.write = myspi_write,.unlocked_ioctl = myspi_ioctl,
};//编写spi设备驱动
int	myspi_probe(struct spi_device *spi)
{//unsigned char buf[]={0X01,0X6D};//0X01表示写数据,0X6D表示写入的数据//spi_write(spi,buf,sizeof(buf));//给从机发送一个数据,让最左边数码管显示数字5printk("myspi_probe\n");spi_dev = spi;//1.创建设备号major = register_chrdev(0, "myspi", &fops);if (major < 0){printk("register_chrdev failed\n");return -1;}//2.创建类cls = class_create(THIS_MODULE, "myspi");if (IS_ERR(cls)){printk("class_create failed\n");unregister_chrdev(major, "myspi");return -1;}//3.创建设备device = device_create(cls, NULL, MKDEV(major, 0), NULL, "myspi");if (IS_ERR(device)){printk("device_create failed\n");class_destroy(cls);unregister_chrdev(major, "myspi");return -1;}return 0;
}int	myspi_remove(struct spi_device *spi)
{printk("myspi_remove\n");    device_destroy(cls, MKDEV(major, 0));class_destroy(cls);unregister_chrdev(major, "myspi");return 0;
}static const struct of_device_id spi_table[] = {{ .compatible = "johnson,m74hc595", },{ /* sentinel */ },
};struct spi_driver myspi_driver = {.probe = myspi_probe,.remove = myspi_remove,.driver = {.name = "m74hc595",.of_match_table = spi_table,},
};//一键注册宏定义
module_spi_driver(myspi_driver);
MODULE_LICENSE("GPL");  //声明开源许可

头文件

#ifndef __SPITEST_H__
#define __SPITEST_H__#define SET_DAT0 _IOW('s', 0, int)
#define SET_DAT1 _IOW('s', 1, int)
#define SET_DAT2 _IOW('s', 2, int)
#define SET_DAT3 _IOW('s', 3, int)
#define SET_DAT4 _IOW('s', 4, int)#endif

应用程序 --> 实现在数码管上依次显示数字

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include "spi_test.h"const uint8_t num[10] = {0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};int main()
{int fd = 0;int date = 0;//打开设备文件fd = open("/dev/myspi", O_RDWR);if (fd < 0){printf("open myspi failed\n");return -1;}while(1){ioctl(fd, SET_DAT0, &num[date]);sleep(1);ioctl(fd, SET_DAT1, &num[date]);sleep(1);ioctl(fd, SET_DAT2, &num[date]);sleep(1);ioctl(fd, SET_DAT3, &num[date]);sleep(1);ioctl(fd, SET_DAT4, &num[date]);if (++date > 9){date = 0;}sleep(1);}   //关闭设备文件close(fd);return 0;
}

相关文章:

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

SPI总线驱动整体上与I2C总线驱动类型&#xff0c;差别主要在设备树和数据传输上&#xff0c;由于SPI是由4根线实现主从机的通信&#xff0c;在设备树上配置时需要对SPI进行设置。 原理图可知&#xff0c;数码管使用的SPI4对应了单片机上的PE11-->SPI4-NSS,PE12-->SPI4-S…...

系统基础与管理(2025更新中)

‌一、Linux 核心架构与组件‌ ‌内核架构‌ ‌核心职责‌&#xff1a; 管理进程生命周期、内存分配、硬件驱动交互及文件系统操作。 模块化设计支持动态加载硬件驱动&#xff08;如modprobe加载内核模块&#xff09;&#xff0c;提升灵活性和扩展性。 ‌内存管理‌&#xff1a…...

Python--内置函数与推导式(下)

3. 内置函数 数学运算类 函数说明示例​abs​绝对值​abs(-10) → 10​​pow​幂运算​pow(2, 3) → 8​​sum​求和​sum([1,2,3]) → 6​​divmod​返回商和余数​divmod(10, 3) → (3, 1)​ 数据转换类 # 进制转换 print(bin(10)) # 0b1010 print(hex(255)) # 0x…...

可狱可囚的爬虫系列课程 14:10 秒钟编写一个 requests 爬虫

一、前言 当重复性的工作频繁发生时&#xff0c;各种奇奇怪怪提高效率的想法就开始萌芽了。当重复代码的模块化封装已经不能满足要求的时候&#xff0c;更高效的方式就被揭开了神秘的面纱。本文基于这样的想法&#xff0c;来和大家探讨如何 10 秒钟编写一个 requests 爬虫程序。…...

Windows golang安装和环境配置

【1】、golang 1.19 sdk下载 https://download.csdn.net/download/notfindjob/90422529 【2】、安装 【3】、配置 GOPATH目录 【4】、LiteIDE下载安装 https://download.csdn.net/download/notfindjob/90422580 【5】、打开LiteIDE&#xff0c;选择查看->管理GOPATH&…...

IP-------GRE和MGRE

4.GRE和MGRE 1.应用场景 现实场景 居家工作&#xff0c;公司工作&#xff0c;分公司工作----------需要传输交换数据--------NAT---在该场景中需要两次NAT&#xff08;不安全&#xff09; 为了安全有两种手段-----1.物理专线---成本高 2.VPN--虚拟专用网---隧道技术--封装技…...

LabVIEW形状误差测量系统

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

django校园互助平台~源码

博主介绍&#xff1a;✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

Vue进阶之AI智能助手项目(五)——ChatGPT的调用和开发

AI智能助手项目 前端页面Layout布局页面-viewssrc/views/chat/layout/Permission.vuesrc/views/chat/layout/sider/index.vuesrc/views/chat/layout/sider/List.vuesrc/views/chat/layout/sider/Footer.vueComponents 组件Header/index.vueMessage/index.vue前端页面 Layout布…...

Jenkins重启后Maven的Project加载失败

个人博客地址&#xff1a;Jenkins重启后Maven的Project加载失败 | 一张假钞的真实世界 Jenkins重启后发现Maven的项目都没有正常加载。检查Jenkins的启动日志发现以下错误信息&#xff1a; java.io.IOException: Unable to read /home/jenkins/.jenkins/jobs/test-maven/conf…...

【docker】docker pull拉取中不断重复下载问题,解决方案之一,磁盘空间扩容

问题类似这样 存储空间不足 如果 Docker 运行环境的磁盘空间不足&#xff0c;拉取的镜像可能会被自动清理&#xff0c;导致重复下载。可以检查磁盘使用情况&#xff1a; df -h docker system df如果空间不足&#xff0c;可以清理一些不用的容器和镜像&#xff1a; docker sy…...

Ubuntu指令(一)

一、终端操作指令 打开终端&#xff0c;有两种便捷方式&#xff1a; 直接点击系统中的终端按钮&#xff1b;使用快捷键ctrl alt T。 关闭终端&#xff0c;同样有多种选择&#xff1a; 在终端输入exit指令&#xff1b;使用快捷键ctrl d&#xff1b;直接点击终端窗口的关闭…...

nnUNet V2修改网络——加入MultiResBlock模块

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 MultiRes Block 是 MultiResUNet 中核心组件之一,旨在解决传统 U-Net 在处理多尺度医学图像时的局…...

Spring Boot + Vue 接入腾讯云人脸识别API(SDK版本3.1.830)

一、需求分析 这次是基于一个Spring Boot Vue的在线考试系统进行二次开发&#xff0c;添加人脸识别功能以防止学生替考。其他有对应场景的也可按需接入API&#xff0c;方法大同小异。 主要有以下两个步骤&#xff1a; 人脸录入&#xff1a;将某个角色&#xff08;如学生&…...

【SpringSecurity】springboot整合SpringSecurity实现登录校验与权限认证

【SpringSecurity】springboot整合SpringSecurity实现登录校验与权限认证 【一】SpringSecurity框架简介【二】SpringSecurity与shiro【1】SpringSecurity特点【2】shiro特点【3】SpringSecurity和shiro总结 【三】SpringSecurity过滤器【1】SpringSecurity中常见的过滤器【2】…...

【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取

【HarmonyOS Next】鸿蒙应用公钥和证书MD5指纹的获取 一、问题背景 政府的icp备案时&#xff0c;或者某些三方SDK以来的管理后台&#xff0c;都需要配置鸿蒙应用的公钥和证书MD5指纹 二、解决方案 专有名词解释&#xff1a; 华为AppGallery Connect简称 AGC平台&#xff0…...

父组件用的是原生监听,子组件用的是onClick,子组件添加了stopPropagation还是没有阻止传播

父组件用事件监听&#xff0c;子组件用onClick&#xff0c;即使子组件加了stopPropagation还是没有阻止冒泡。父组件可能使用原生的addEventListener来绑定事件&#xff0c;而子组件用的是React的onClick事件。这时候&#xff0c;虽然子组件调用了e.stopPropagation()&#xff…...

ui设计公司兰亭妙微分享:科研单位UI界面设计

科研单位的UI界面设计是一项至关重要的任务&#xff0c;它不仅关乎科研工作的效率&#xff0c;还直接影响到科研人员的用户体验。以下是对科研单位UI界面设计的详细分析&#xff1a; 一、设计目标 科研单位的UI界面设计旨在提升科研工作的效率与便捷性&#xff0c;同时确保科…...

python绘制年平均海表温度、盐度、ph分布图

python绘制年平均海表温度、盐度、ph图 文章目录 python绘制年平均海表温度、盐度、ph分布图前言一、数据准备二、代码编写2.1. python绘制年平均海表温度&#xff08;主要&#xff09;2.2. python绘制年平均海表盐度&#xff08;选看&#xff09;2.3. python绘制年平均海表ph&…...

windows中kafka集群部署示例

注意 kafka包路径不要太长,不然启动时候 这里再单独下个zookeeper做为三个kafka实例broker的注册中心 修改Zookeeper配置文件 脚本内容 call bin/zkServer.cmd 不然的话就进bin目录双击zkServer.cmd 配置Zookeeper的另外一种方式 用Kafka自带的zookeeper 例如我复制一份 …...

Wan2.1 VAE性能调优:针对STM32嵌入式AI的模型轻量化探索

Wan2.1 VAE性能调优&#xff1a;针对STM32嵌入式AI的模型轻量化探索 最近和几个做嵌入式开发的朋友聊天&#xff0c;他们都在琢磨一件事&#xff1a;能不能在像STM32这种资源紧张的小设备上&#xff0c;跑一些有趣的AI功能&#xff0c;比如给图片加个实时滤镜&#xff1f;这想…...

深入解析:使用Apache POI与Hutool高效提取WPS Excel中的嵌入式图片

1. 为什么需要提取Excel中的嵌入式图片&#xff1f; 在日常工作中&#xff0c;我们经常会遇到需要处理包含图片的Excel文件。比如电商平台的产品数据报表里嵌入了商品图片&#xff0c;财务系统中保存了带有签名的报销单&#xff0c;或者数据分析报告里包含了图表截图。这些图片…...

终极语言学习革命:如何通过肌肉记忆训练重塑你的编程与英语能力?

终极语言学习革命&#xff1a;如何通过肌肉记忆训练重塑你的编程与英语能力&#xff1f; 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers …...

Intv_AI_MK11 前端设计辅助:基于 UI/UX 原则的交互方案生成

Intv_AI_MK11 前端设计辅助&#xff1a;基于 UI/UX 原则的交互方案生成 1. 引言&#xff1a;当AI遇见前端设计 想象一下这样的场景&#xff1a;产品经理刚开完需求评审会&#xff0c;设计师正在构思界面原型&#xff0c;前端工程师准备开始编码。这时&#xff0c;一个共同的挑…...

AIGlasses_for_navigation与Matlab联合仿真:机器人视觉导航算法验证环境搭建

AIGlasses_for_navigation与Matlab联合仿真&#xff1a;机器人视觉导航算法验证环境搭建 最近在折腾机器人导航算法&#xff0c;发现一个挺头疼的问题&#xff1a;算法写出来容易&#xff0c;但想验证它在真实世界里的表现&#xff0c;成本太高了。要么得买昂贵的硬件平台&…...

32TOPS算力+工业级宽温适配!SE110S-WA32边缘计算微服务器全解析

随着工业智能化、AIoT产业的深度发展&#xff0c;边缘侧的算力需求迎来爆发式增长。在智慧交通、水利、电力、工地等工业场景中&#xff0c;边缘设备不仅需要强劲的AI推理能力&#xff0c;更要面对高低温、多尘、强电磁干扰、无人值守等严苛的运行环境&#xff0c;同时对功耗、…...

快速上手:LangChain + AgentRun 浏览器沙箱极简集成指南

在技术领域&#xff0c;我们常常被那些闪耀的、可见的成果所吸引。今天&#xff0c;这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力&#xff0c;让我们得以一窥未来的轮廓。然而&#xff0c;作为在企业一线构建、部署和维护复杂系统的实践者&#xff0c;我们深知…...

别再让电机白费电了!手把手教你用MTPA算法在STM32上实现节能控制(附代码)

电机节能控制实战&#xff1a;基于STM32的MTPA算法实现与优化 电机控制系统中的能耗问题一直是工业应用中的痛点。传统控制方法往往忽视了电机内部磁阻转矩的潜力&#xff0c;导致电流利用率低下。本文将带你深入理解MTPA&#xff08;最大转矩电流比&#xff09;算法的核心思想…...

STM32H743串口DMA+空闲中断实战:从MPU配置到HAL库‘锁’的坑,我都帮你踩完了

STM32H743串口DMA空闲中断实战&#xff1a;从MPU配置到HAL库状态机陷阱全解析 第一次将项目从STM32F407迁移到H743平台时&#xff0c;我遭遇了职业生涯中最诡异的调试经历——CubeMX生成的代码明明逻辑正确&#xff0c;串口却像中了邪一样时好时坏。深夜的实验室里&#xff0c;…...

AIAgent分布式部署性能拐点分析:当节点超47个时,Latency突增300%的底层根因与压测调优白皮书

第一章&#xff1a;AIAgent分布式部署性能拐点分析&#xff1a;当节点超47个时&#xff0c;Latency突增300%的底层根因与压测调优白皮书 2026奇点智能技术大会(https://ml-summit.org) 在真实生产级AIAgent集群压测中&#xff0c;当Worker节点规模从47扩展至48时&#xff0c;P…...