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总线驱动类型,差别主要在设备树和数据传输上,由于SPI是由4根线实现主从机的通信,在设备树上配置时需要对SPI进行设置。 原理图可知,数码管使用的SPI4对应了单片机上的PE11-->SPI4-NSS,PE12-->SPI4-S…...
系统基础与管理(2025更新中)
一、Linux 核心架构与组件 内核架构 核心职责: 管理进程生命周期、内存分配、硬件驱动交互及文件系统操作。 模块化设计支持动态加载硬件驱动(如modprobe加载内核模块),提升灵活性和扩展性。 内存管理:…...
Python--内置函数与推导式(下)
3. 内置函数 数学运算类 函数说明示例abs绝对值abs(-10) → 10pow幂运算pow(2, 3) → 8sum求和sum([1,2,3]) → 6divmod返回商和余数divmod(10, 3) → (3, 1) 数据转换类 # 进制转换 print(bin(10)) # 0b1010 print(hex(255)) # 0x…...
可狱可囚的爬虫系列课程 14:10 秒钟编写一个 requests 爬虫
一、前言 当重复性的工作频繁发生时,各种奇奇怪怪提高效率的想法就开始萌芽了。当重复代码的模块化封装已经不能满足要求的时候,更高效的方式就被揭开了神秘的面纱。本文基于这样的想法,来和大家探讨如何 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,选择查看->管理GOPATH&…...
IP-------GRE和MGRE
4.GRE和MGRE 1.应用场景 现实场景 居家工作,公司工作,分公司工作----------需要传输交换数据--------NAT---在该场景中需要两次NAT(不安全) 为了安全有两种手段-----1.物理专线---成本高 2.VPN--虚拟专用网---隧道技术--封装技…...
LabVIEW形状误差测量系统
在机械制造领域,形状与位置公差(GD&T)直接影响装配精度与产品寿命。国内中小型机加工企业因形状误差导致的返工率高达12%-18%。传统测量方式存在以下三大痛点: 设备局限:机械式千分表需人工读数,精度…...
django校园互助平台~源码
博主介绍:✌程序猿徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
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加载失败
个人博客地址:Jenkins重启后Maven的Project加载失败 | 一张假钞的真实世界 Jenkins重启后发现Maven的项目都没有正常加载。检查Jenkins的启动日志发现以下错误信息: java.io.IOException: Unable to read /home/jenkins/.jenkins/jobs/test-maven/conf…...
【docker】docker pull拉取中不断重复下载问题,解决方案之一,磁盘空间扩容
问题类似这样 存储空间不足 如果 Docker 运行环境的磁盘空间不足,拉取的镜像可能会被自动清理,导致重复下载。可以检查磁盘使用情况: df -h docker system df如果空间不足,可以清理一些不用的容器和镜像: docker sy…...
Ubuntu指令(一)
一、终端操作指令 打开终端,有两种便捷方式: 直接点击系统中的终端按钮;使用快捷键ctrl alt T。 关闭终端,同样有多种选择: 在终端输入exit指令;使用快捷键ctrl d;直接点击终端窗口的关闭…...
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的在线考试系统进行二次开发,添加人脸识别功能以防止学生替考。其他有对应场景的也可按需接入API,方法大同小异。 主要有以下两个步骤: 人脸录入:将某个角色(如学生&…...
【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备案时,或者某些三方SDK以来的管理后台,都需要配置鸿蒙应用的公钥和证书MD5指纹 二、解决方案 专有名词解释: 华为AppGallery Connect简称 AGC平台࿰…...
父组件用的是原生监听,子组件用的是onClick,子组件添加了stopPropagation还是没有阻止传播
父组件用事件监听,子组件用onClick,即使子组件加了stopPropagation还是没有阻止冒泡。父组件可能使用原生的addEventListener来绑定事件,而子组件用的是React的onClick事件。这时候,虽然子组件调用了e.stopPropagation()ÿ…...
ui设计公司兰亭妙微分享:科研单位UI界面设计
科研单位的UI界面设计是一项至关重要的任务,它不仅关乎科研工作的效率,还直接影响到科研人员的用户体验。以下是对科研单位UI界面设计的详细分析: 一、设计目标 科研单位的UI界面设计旨在提升科研工作的效率与便捷性,同时确保科…...
python绘制年平均海表温度、盐度、ph分布图
python绘制年平均海表温度、盐度、ph图 文章目录 python绘制年平均海表温度、盐度、ph分布图前言一、数据准备二、代码编写2.1. python绘制年平均海表温度(主要)2.2. python绘制年平均海表盐度(选看)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性能调优:针对STM32嵌入式AI的模型轻量化探索 最近和几个做嵌入式开发的朋友聊天,他们都在琢磨一件事:能不能在像STM32这种资源紧张的小设备上,跑一些有趣的AI功能,比如给图片加个实时滤镜?这想…...
深入解析:使用Apache POI与Hutool高效提取WPS Excel中的嵌入式图片
1. 为什么需要提取Excel中的嵌入式图片? 在日常工作中,我们经常会遇到需要处理包含图片的Excel文件。比如电商平台的产品数据报表里嵌入了商品图片,财务系统中保存了带有签名的报销单,或者数据分析报告里包含了图表截图。这些图片…...
终极语言学习革命:如何通过肌肉记忆训练重塑你的编程与英语能力?
终极语言学习革命:如何通过肌肉记忆训练重塑你的编程与英语能力? 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers …...
Intv_AI_MK11 前端设计辅助:基于 UI/UX 原则的交互方案生成
Intv_AI_MK11 前端设计辅助:基于 UI/UX 原则的交互方案生成 1. 引言:当AI遇见前端设计 想象一下这样的场景:产品经理刚开完需求评审会,设计师正在构思界面原型,前端工程师准备开始编码。这时,一个共同的挑…...
AIGlasses_for_navigation与Matlab联合仿真:机器人视觉导航算法验证环境搭建
AIGlasses_for_navigation与Matlab联合仿真:机器人视觉导航算法验证环境搭建 最近在折腾机器人导航算法,发现一个挺头疼的问题:算法写出来容易,但想验证它在真实世界里的表现,成本太高了。要么得买昂贵的硬件平台&…...
32TOPS算力+工业级宽温适配!SE110S-WA32边缘计算微服务器全解析
随着工业智能化、AIoT产业的深度发展,边缘侧的算力需求迎来爆发式增长。在智慧交通、水利、电力、工地等工业场景中,边缘设备不仅需要强劲的AI推理能力,更要面对高低温、多尘、强电磁干扰、无人值守等严苛的运行环境,同时对功耗、…...
快速上手:LangChain + AgentRun 浏览器沙箱极简集成指南
在技术领域,我们常常被那些闪耀的、可见的成果所吸引。今天,这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力,让我们得以一窥未来的轮廓。然而,作为在企业一线构建、部署和维护复杂系统的实践者,我们深知…...
别再让电机白费电了!手把手教你用MTPA算法在STM32上实现节能控制(附代码)
电机节能控制实战:基于STM32的MTPA算法实现与优化 电机控制系统中的能耗问题一直是工业应用中的痛点。传统控制方法往往忽视了电机内部磁阻转矩的潜力,导致电流利用率低下。本文将带你深入理解MTPA(最大转矩电流比)算法的核心思想…...
STM32H743串口DMA+空闲中断实战:从MPU配置到HAL库‘锁’的坑,我都帮你踩完了
STM32H743串口DMA空闲中断实战:从MPU配置到HAL库状态机陷阱全解析 第一次将项目从STM32F407迁移到H743平台时,我遭遇了职业生涯中最诡异的调试经历——CubeMX生成的代码明明逻辑正确,串口却像中了邪一样时好时坏。深夜的实验室里,…...
AIAgent分布式部署性能拐点分析:当节点超47个时,Latency突增300%的底层根因与压测调优白皮书
第一章:AIAgent分布式部署性能拐点分析:当节点超47个时,Latency突增300%的底层根因与压测调优白皮书 2026奇点智能技术大会(https://ml-summit.org) 在真实生产级AIAgent集群压测中,当Worker节点规模从47扩展至48时,P…...
