ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Linux驱动-SPI-MCP2515 写函数(收发操作)

Linux驱动-SPI-MCP2515 写函数(收发操作) Linux驱动-SPI-MCP2515 写函数收发操作文章目录前言一、参考文档二、使用手册分析发送缓冲器-寄存器SRAM 理解流程步骤分析操作的寄存器分析梳理1、设置缓冲器优先级2、从用户空间复制数据到内核缓冲区3、发送缓冲器数据到内核4、启动发送5、验证是否发送成功-等待发送完毕6、清除发送完成标志7、完整发送代码如下总结前言在上个学习内容Linux-SPI-位修改指令-屏蔽字节-修改CANINE寄存器的值-修改工作模式中对 mcp2515 的工作模式进行了修改 从配置模式修改为了环回模式 而这里学习将会继续对 mcp2515 的驱动程序进行完善 加入 mcp2515 的写函数和读函数 从而实现数据的发送和接收这里写函数是什么呢 其实就是文件系统操作里面对外开放的接口那对外释放的接口我们这里实验最终要做什么呢 暂且抛开CAN功能我们利用SPI协议对CAN 进行收发操作 这里的发就是发给CAN。那为什么要进行收发操作呢其实就是模拟收发数据操作不用借助CAN 输出。为什么切换到回环模式回环才能收发呀。一、参考文档RK3568驱动指南第十六篇 SPI-第192章 mcp2515驱动编写完善write和read函数二、使用手册分析发送缓冲器-寄存器MCP2515 有三个发送缓冲器 每个发送缓冲器都具有 14 字节的内存空间 每个发送缓冲器的控制由 TXBnCTRL 寄存器管理 该寄存器决定了何时发送报文以及发送时的报文状态SRAM 理解SRAM静态随机存储器Static‑RAM就是芯片内部一小块高速内存。SRAM 和寄存器是什么关系MCP2515 把内部这一块 SRAM映射成 SPI 可以访问的寄存器地址。你通过 SPI 写寄存器0x31~0x3DTXB0 缓冲区本质就是在读写 MCP2515 内部的 SRAMSRAM 和 Flash闪存区别非常关键类型SRAM (MCP2515 内部内存)Flash (闪存)断电断电数据全部丢失断电数据保留读写速度极快慢MCP2515 用途临时存发送 / 接收 CAN 报文MCP2515没有 Flash上电所有寄存器都是默认值流程步骤分析直接看数据手册 总体上其实有三个步骤的下面会具体分析的。操作的寄存器分析梳理1、设置缓冲器优先级如图分析寄存器所以实际我们需要如何写这个逻辑呢#defineTXB0CTRL0x30//发送缓冲器控制寄存器地址mcp2515_change_regbit(TXB0CTRL,0x03,0x03);// MCP2515修改寄存器位函数voidmcp2515_change_regbit(charreg,charmask,charvalue){intret;charwrite_buf[]{0x05,reg,mask,value};// SPI写缓冲区用于发送修改寄存器位命令retspi_write(spi_dev,write_buf,sizeof(write_buf));// 发送SPI写命令if(ret0){printk(mcp2515_change_regbit error\n);}}2、从用户空间复制数据到内核缓冲区我们的发送操作是写在write 方法里面作为对应用端提供的接口操作的所以 具体方法如下获取用户空间数据到内核// 写设备操作函数ssize_tmcp2515_write(struct file*file,constchar__user*buf,size_t size,loff_t*offset){......intret;inti;// 设置TXB0CTRL寄存器的部分位mcp2515_change_regbit(TXB0CTRL,0x03,0x03);// 从用户空间复制数据到内核缓冲区retcopy_from_user(w_kbuf,buf,size);if(ret){printk(copy_from_user w_kbuf is error\n);return-1;}......returnsize;}3、发送缓冲器数据到内核再看一下使用手册里面的发送缓冲器要求就是说还要继续发送13 个字节数据出去发送字节数据出去其实就是要写到寄存器里面去既然写值那么一定要知道寄存器地址吧。所以还是先看看寄存器具体啥情况看地址分析发送缓冲器控制寄存器 TXBnCTRL 为发送缓冲器的第一个字节 接下来的 5 个字节用来装载标准和扩展标识符以及其他报文仲裁信息。 最后的 8 个字节用于装载等待发送报文的 8 个可能的数据字节 这 13 个字节数据由用户空间所传递 且地址是连续的。也就是说地址连续的那么写寄存器地址就简单了。// 写设备操作函数ssize_tmcp2515_write(struct file*file,constchar__user*buf,size_t size,loff_t*offset){charw_kbuf[13]{0};intret;inti;// 设置TXB0CTRL寄存器的部分位mcp2515_change_regbit(TXB0CTRL,0x03,0x03);// 从用户空间复制数据到内核缓冲区retcopy_from_user(w_kbuf,buf,size);if(ret){printk(copy_from_user w_kbuf is error\n);return-1;}// 将数据写入MCP2515寄存器for(i0;isizeof(w_kbuf);i){mcp2515_write_reg(0x31i,w_kbuf[i]);}.....4、启动发送继续看使用手册继续看寄存器所以 发送一次寄存器数据如下#defineTXB0CTRL0x30//发送缓冲器控制寄存器地址// 设置TXB0CTRL寄存器的部分位启动发送mcp2515_change_regbit(TXB0CTRL,0x08,0x08);//采用位发送数据到寄存器// MCP2515修改寄存器位函数voidmcp2515_change_regbit(charreg,charmask,charvalue){intret;charwrite_buf[]{0x05,reg,mask,value};// SPI写缓冲区用于发送修改寄存器位命令retspi_write(spi_dev,write_buf,sizeof(write_buf));// 发送SPI写命令if(ret0){printk(mcp2515_change_regbit error\n);}}5、验证是否发送成功-等待发送完毕继续看操作使用手册如下所以检查寄存器CANINTF寄存器中TXnIF 位置是否为1 即可。继续查看寄存器 CANINTF地址ox2C 判断的TXnIF 是bit2所以检查寄存器CANINTF 对应的位是不是1如果是1 代表成功。#defineCANINTF0x2c// 等待发送完成while(!(mcp2515_read_reg(CANINTF)(12)));综合代码编写如下// 写设备操作函数ssize_tmcp2515_write(struct file*file,constchar__user*buf,size_t size,loff_t*offset){charw_kbuf[13]{0};intret;inti;// 设置TXB0CTRL寄存器的部分位mcp2515_change_regbit(TXB0CTRL,0x03,0x03);// 从用户空间复制数据到内核缓冲区retcopy_from_user(w_kbuf,buf,size);if(ret){printk(copy_from_user w_kbuf is error\n);return-1;}// 将数据写入MCP2515寄存器for(i0;isizeof(w_kbuf);i){mcp2515_write_reg(0x31i,w_kbuf[i]);}// 设置TXB0CTRL寄存器的部分位启动发送mcp2515_change_regbit(TXB0CTRL,0x08,0x08);// 等待发送完成while(!(mcp2515_read_reg(CANINTF)(12)));......returnsize;}6、清除发送完成标志为什么要进行这步操作继续看操作手册如上的寄存器CANINTF也就是说我已经验证了启动发送报文成功了接下来就是要复位操作一次是MCU 清零所以需要MCU端 代码实现而不是外设自动复位。所以要个这个寄存器复位操作很简单了还是找寄存器地址、复位操作的值、屏蔽字节即可mcp2515_change_regbit(CANINTF,0x04,0x00);7、完整发送代码如下// 写设备操作函数ssize_tmcp2515_write(struct file*file,constchar__user*buf,size_t size,loff_t*offset){charw_kbuf[13]{0};intret;inti;// 设置TXB0CTRL寄存器的部分位mcp2515_change_regbit(TXB0CTRL,0x03,0x03);// 从用户空间复制数据到内核缓冲区retcopy_from_user(w_kbuf,buf,size);if(ret){printk(copy_from_user w_kbuf is error\n);return-1;}// 将数据写入MCP2515寄存器for(i0;isizeof(w_kbuf);i){mcp2515_write_reg(0x31i,w_kbuf[i]);}// 设置TXB0CTRL寄存器的部分位启动发送mcp2515_change_regbit(TXB0CTRL,0x08,0x08);// 等待发送完成while(!(mcp2515_read_reg(CANINTF)(12)));// 清除发送完成标志mcp2515_change_regbit(CANINTF,0x04,0x00);returnsize;}总结写入操作是提供给外部的接口实际操作的是SPI向CAN 发的操作整个过程完全是根据操作手册来的读懂、理解、根据操作手册进行编程 、业务实现 需要自己学会看 看得懂才行。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表