Linux驱动-SPI-mcp2515 复位函数
Linux驱动-SPI-mcp2515 复位函数文章目录前言一、参考文档二、读懂原理图和操作手册原理图分析Can 模块GPIO/CAN/485 Interfcae 原理图数据手册分析器件概述工作模式SPI接口三、设备树配置四、SPI 复位函数编写1、复位函数编写定义一个SPI设备指针定义复位指令SPI设备指针 赋值MCP2515 SPI软件复位函数对比两种复位操作-写入函数2、带复位函数完整驱动编写总结前言这里只简单写一个复位函数为什么要写复位函数是通过外设数据手册来的所以要先搞懂数据手册通过数据手册来分析驱动业务流程然后一步一步进行外设的驱动的业务 无外乎读写外设寄存器进行控制。一、参考文档Linux驱动-初步认识SPILinux驱动-SPI外设代码框架编写Linux驱动-SPI-框架中添加字符设备Linux 驱动-I2C输入子系统相关知识点二、读懂原理图和操作手册原理图分析Can 模块mcp2515 模块有很多功能的spi 转can,spi 转485. 如下 spi 如何转换的呢 就是通过ic 芯片进行转换了一次而已。我们直接看一下spi 转can 的原理图。看U1 部分左边不就是SPI 相关的内容吗 pin 脚标记的16 、15/14/13/12 这些就是SPI 的四根线右边看 RXCAN 、TXCAN 输出的就是can 信号。目标就是你要看懂原理图这个太基本了。 或者通过相关资料来读懂原理图。这里有特别容易忽略的问题就是IC 的原理图和实际的物理要对应上千万不要搞错。GPIO/CAN/485 Interfcae 原理图如如下红丝标记的J1 原理图要和实际的对上这样才能正确接线。数据手册分析收据手册本身要读懂要搞明白机制每一块的内容都特别重要下面初步看一下目录有哪些内容本身就是一个说明使用书器件概述工作模式所以驱动连接外设后在驱动第一步就是复位 进入配置模式。SPI接口这里特别重要数据手册里面都说了支持00 和 11 两种模式所以在实际设备树配置的时候要配置好不然无法通信。同时要关注一下数据手册里面有误发送数据介绍说明默认优先高位。三、设备树配置我们看看我们之前的设备树基本配置、必备配置 参考 Linux驱动-SPI外设代码框架编写spi0{statusokay;pinctrl-0spi0m1_cs0spi0m1_pins;pinctrl-1spi0m1_cs0spi0m1_pins_hs;mcp2515:mcp25150{compatiblemy-mcp2515;reg0;spi-max-frequency10000000;statusokay;};};说一下 设备树配置外设时候针对SPI 关注几个点compatible 匹配外设驱动reg 片选信号spi-max-frequency : 始终频率 也就是传输速度去手册里面找。10MHzspi-cpha; spi-cpol; 极性和相位外设默认是0,0 支持的就是0,0 或者 1,1 。 就按默认的来匹配不要配置这两个属性。spi-lsb-first; 低位优先传输默认是高位优先传输所有不要配置这个属性。spi-cs-high 片选极性高电平有效。 mcp2515 默认是低电平有效所有不要写这个属性。两点特别注意你自己要学会看懂操作手册如果有特别的说明 那么对应的就要在设备树上体现如果没有特别体现就用默认同时不要写不必要的属性。四、SPI 复位函数编写1、复位函数编写定义一个SPI设备指针staticstruct spi_device*g_mcp2515_spiNULL;定义复位指令#defineMCP2515_CMD_RESET0xC0// 复位指令 1100 0000SPI设备指针 赋值在mcp2515_probe回调函数中赋值// MCP2515设备初始化函数staticintmcp2515_probe(struct spi_device*spi){intret;printk(This is mcp2515 probe\n);// 保存spi设备指针g_mcp2515_spispi;// 【上电首先执行MCP2515软件复位】retmcp2515_hw_reset(spi);if(ret){printk(mcp2515 hw reset fail!\n);returnret;}// // 后续可以在这里继续添加寄存器初始化代码return0;}MCP2515 SPI软件复位函数/* MCP2515 SPI软件复位函数 */staticintmcp2515_hw_reset(struct spi_device*spi){u8 cmdMCP2515_CMD_RESET;intret;if(!spi){printk(mcp2515 spi dev is NULL!\n);return-EINVAL;}// 发送单字节复位命令retspi_write(spi,cmd,sizeof(cmd));if(ret0){printk(mcp2515 reset cmd send failed, ret:%d\n,ret);returnret;}printk(mcp2515 send reset command(0xC0) success\n);msleep(10);// 等待MCP2515内部复位完成参考数据手册要求return0;}对比两种复位操作-写入函数如上是一种写操作写了复位如下给出另外一种方案// MCP2515芯片复位函数voidmcp2515_reset(void){intret;charwrite_buf[]{0xc0};// 复位指令0x11000000即0xc0retspi_write(spi_dev,write_buf,sizeof(write_buf));// 发送复位命令if(ret0){printk(spi_write is error\n);// 打印错误信息}}这两种实现方案的底层逻辑其实是一摸一样的一个是标准写法一个是极简写法推荐第一套写法。其实 这里最核心特别注意的一点是如何声明的问题charvsu8char write_buf[]{0xc0}在 ARM 平台可能是有符号 char规范驱动代码统一使用内核linux/types.h的u8无符号字节类型避免符号扩展带来的隐性问题。2、带复位函数完整驱动编写#includelinux/init.h#includelinux/module.h#includelinux/spi/spi.h#includelinux/fs.h#includelinux/kdev_t.h#includelinux/cdev.h#includelinux/uaccess.h#includelinux/delay.h// 新增msleep 头文件staticdev_t dev_num;staticintmajor;staticintminor;staticstruct cdev mcp2515_cdev;structclass*mcp2515_class;struct device*mcp2515_device;staticstruct spi_device*g_spi_dev;// 新增全局保存spi设备指针/* MCP2515 SPI复位函数 */staticintmcp2515_reset(void){intret;uchar cmd0xC0;// MCP2515 复位指令 11000000 0xC0if(!g_spi_dev){printk(mcp2515_reset: spi dev pointer is NULL!\n);return-ENODEV;}retspi_write(g_spi_dev,cmd,sizeof(cmd));if(ret0){printk(mcp2515_reset spi_write failed, ret%d\n,ret);returnret;}msleep(10);// MCP2515复位后等待芯片稳定手册建议延时printk(mcp2515 send reset cmd success\n);return0;}/*打开设备函数*/staticintmcp2515_open(struct inode*inode,struct file*file){printk(This is mcp2515_open \n);return0;}staticssize_tmcp2515_read(struct file*file,char__user*buf,size_t size,loff_t*off){printk(This is mcp2515_cdev read\r\n);return0;}/*向设备写入数据函数*/staticssize_tmcp2515_write(struct file*file,constchar__user*buf,size_t size,loff_t*off){printk(This is mcp2515_cdev_write\r\n);return0;}staticintmcp2515_release(struct inode*inode,struct file*file){printk(This is chrdev_release\r\n);return0;}staticstruct file_operations mcp2515_fops{.ownerTHIS_MODULE,.openmcp2515_open,.readmcp2515_read,.writemcp2515_write,.releasemcp2515_release,};// MCP2515 设备初始化函数staticintmcp2515_probe(struct spi_device*spi){printk(This is mcp2515 probe\n);g_spi_devspi;// 保存spi设备指针mcp2515_reset();// ✅ 进入probe后执行芯片复位return0;}// MCP2515 设备移除函数staticintmcp2515_remove(struct spi_device*spi){printk(This is mcp2515 mcp2515_remove\n);g_spi_devNULL;// 移除时清空全局指针防止野指针return0;}// MCP2515 设备匹配表用于设备树匹配staticconststruct of_device_id mcp2515_of_match_table[]{{.compatiblemy-mcp2515},{/* sentinel */}};// MCP2515 设备 ID 匹配表用于总线匹配staticconststruct spi_device_id mcp2515_id_table[]{{mcp2515,0},{/* sentinel */}};// MCP2515 SPI 驱动结构体staticstruct spi_driver spi_mcp2515{.probemcp2515_probe,.removemcp2515_remove,.driver{.namemcp2515,.ownerTHIS_MODULE,.of_match_tablemcp2515_of_match_table,},.id_tablemcp2515_id_table,};// 驱动初始化函数staticint__init mcp2515_init(void){intret;retalloc_chrdev_region(dev_num,0,1,mcp2515);if(ret0){printk(alloc_chrdev_region is error\n);gotoerr_out;}printk(alloc_chrdev_region is ok\n);majorMAJOR(dev_num);minorMINOR(dev_num);printk(major is %d\n,major);printk(minor is %d\n,minor);cdev_init(mcp2515_cdev,mcp2515_fops);mcp2515_cdev.ownerTHIS_MODULE;retcdev_add(mcp2515_cdev,dev_num,1);if(ret0){printk(cdev_add is error\n);gotoerr_unreg_devnum;}printk(cdev_add is ok\n);mcp2515_classclass_create(THIS_MODULE,spi_to_can);if(IS_ERR(mcp2515_class)){retPTR_ERR(mcp2515_class);printk(class_create failed!\n);gotoerr_cdev_del;}mcp2515_devicedevice_create(mcp2515_class,NULL,dev_num,NULL,mcp2515);if(IS_ERR(mcp2515_device)){retPTR_ERR(mcp2515_device);printk(device_create failed!\n);gotoerr_class_destroy;}// 注册 SPI 驱动retspi_register_driver(spi_mcp2515);if(ret0){printk(spi_register_driver error\n);gotoerr_dev_destroy;}printk(mcp2515 module load complete\n);return0;// 错误回滚分支新增防止资源泄漏oopserr_dev_destroy:device_destroy(mcp2515_class,dev_num);err_class_destroy:class_destroy(mcp2515_class);err_cdev_del:cdev_del(mcp2515_cdev);err_unreg_devnum:unregister_chrdev_region(dev_num,1);err_out:returnret;}// 驱动退出函数staticvoid__exit mcp2515_exit(void){spi_unregister_driver(spi_mcp2515);device_destroy(mcp2515_class,dev_num);class_destroy(mcp2515_class);cdev_del(mcp2515_cdev);unregister_chrdev_region(dev_num,1);printk(module exit \n);}module_init(mcp2515_init);module_exit(mcp2515_exit);MODULE_LICENSE(GPL);总结本篇内容核心知识点会看使用手册、原理图、通过原理图接线设备树的配置相关技能必须根据使用手册来针对性配置复位函数通过spi 的 相关方法spi_write进行写操作

相关新闻

数学建模竞赛资源包深度解析:从VRP模型构建到代码实现与论文撰写

数学建模竞赛资源包深度解析:从VRP模型构建到代码实现与论文撰写

1. 项目概述:一份数学建模竞赛的“硬核”资源包如果你正在准备MathorCup、国赛、美赛这类数学建模竞赛,或者你是一位指导老师,正在为团队寻找高质量的参考资料,那么你肯定对“解题思路”、“完整代码”、“获奖论文”这些关键词极…

2026/10/9 14:47:49 阅读更多 →
数学建模竞赛解题:从思路到Python代码的完整实现指南

数学建模竞赛解题:从思路到Python代码的完整实现指南

1. 项目概述:从“可运行代码”到“解题思路”的实战转化最近在辅导学生准备数维杯这类数学建模竞赛时,我发现一个普遍现象:很多同学拿到题目后,第一反应不是去分析问题、建立模型,而是满世界寻找“可运行代码”。尤其是…

2026/9/28 18:24:34 阅读更多 →
OSS ChatGPT UI v4:从通用聊天到AI集成开发环境的部署与实战

OSS ChatGPT UI v4:从通用聊天到AI集成开发环境的部署与实战

如果你还在用官方 ChatGPT 网页版,每次打开都是一个空白的聊天窗口,需要手动切换模型、重新粘贴提示词、或者为不同项目创建重复的对话……那么,你正在浪费大量本可用于深度思考的时间。这不是 ChatGPT 不好用,而是它的交互设计本…

2026/10/4 4:46:26 阅读更多 →

最新新闻

管道缺陷检测数据集实战:格式转换、训练优化与避坑指南

管道缺陷检测数据集实战:格式转换、训练优化与避坑指南

简介:面向管道缺陷检测任务的目标检测数据集,共收录超过900张标注图片,适用于工业安全检测、设备巡检等场景,可支撑YOLO系列模型训练与研究。数据已统一处理为YOLO格式,并附带数据增强、类别定义文件及可视化脚本&…

2026/10/9 14:47:17 阅读更多 →
B站视频AI分拣工具:本地化处理字幕与弹幕的Obsidian知识工作流

B站视频AI分拣工具:本地化处理字幕与弹幕的Obsidian知识工作流

1. 这不是收藏夹,是待处理的“视频原料库”你点开B站收藏夹那一刻,心里想的真是“以后慢慢看”吗?我翻过自己三年来的收藏记录——237个视频,平均每个收藏夹里塞着48条,其中62%的视频播放量不足50次,31%甚至…

2026/10/9 14:47:17 阅读更多 →
DeepSeek批量请求与异步调用实战:把2000条文本处理从40分钟压缩到3分半

DeepSeek批量请求与异步调用实战:把2000条文本处理从40分钟压缩到3分半

简介:面向希望充分发挥 DeepSeek 性能的开发者与数据工作者,本资源是一份以批量请求与异步调用为主线的实战型 PDF 文档,共 21 页,内容覆盖环境准备、API 密钥获取、批量请求构建与发送、响应解析、错误处理与重试机制&#xff0c…

2026/10/9 14:47:17 阅读更多 →
逆向跨谱神经网络:解决多频时间序列建模难题

逆向跨谱神经网络:解决多频时间序列建模难题

1. 这不是“换个名字的LSTM”:逆向跨谱神经网络到底在解决什么问题?你有没有遇到过这样的场景:工厂里几十台设备同时采集温度、压力、振动、电流四类信号,采样频率各不相同——有的每秒1000次,有的每分钟才录一次&…

2026/10/9 14:47:17 阅读更多 →
二手HP Z系列工作站BIOS设置指南:从进BIOS到虚拟化与刷写避坑

二手HP Z系列工作站BIOS设置指南:从进BIOS到虚拟化与刷写避坑

简介:HP工作站BIOS设置说明文档,以Z200机型为例,系统梳理了BIOS各菜单的功能与操作方法,适用于Z228、Z440、Z230、Z640、Z840、Z800、Z620、Z420、Z820等多款HP工作站主板,适合负责工作站部署维护的技术人员、硬件维修…

2026/10/9 14:47:17 阅读更多 →
Hexo博客SEO:利用IndexNow与GSC实现自动提交,加速收录

Hexo博客SEO:利用IndexNow与GSC实现自动提交,加速收录

Hexo博客搭到第12期,我终于把“收录”这件事认真对待起来。前两周我的日常就是:发完新文章,打开Google Search Console,点URL检查,再点“请求编入索引”,然后等。等完Google还要去Bing那边手工提交一次&…

2026/10/9 14:46:16 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →