RK3568驱动指南|第十六篇 SPI-第190章 配置模式下寄存器的配置

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。

【公众号】迅为电子

【粉丝群】258811263(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十六篇 SPI_全新升级)_基于RK3568


第190章 配置模式下寄存器的配置

在前面两个章节中编写了复位函数以及读寄存器函数,向MCP2515发送SPI复位指令之后就会进入配置模式下,只有在配置模式才可以修改以下寄存器:

·CNF1、CNF2 和 CNF3:用于配置波特率

·TXRTSCTRL:用于控制发送请求引脚

·验收过滤寄存器:用于设置验收过滤器

·验收屏蔽寄存器:用于设置验收屏蔽

当然除了上述寄存器只能在配置模式下进行修改之外,在配置模式也是可以对其他寄存器进行修改的,而为了SPI转CAN MCP2515芯片正常工作,需要在配置模式配置以下寄存器:

CNF1、CNF2 和 CNF3:用于配置波特率

RXB0CTRL:接收缓冲器0控制寄存器

CANINTE:中断使能寄存器

接下来对每个寄存器的具体配置原理进行讲解。

190.1 CNF1、CNF2和CNF3寄存器配置

CAN总线上的所有器件都必须使用相同的比特率,而CNF1、CNF2和CNF3三个寄存器就是用来配置CAN总线波特率的,更具体的说明为CNF1、CNF2和CNF3三个寄存器通过对位时间各个段的配置,进而设置CAN总线的波特率。

而位时间(Bit Time)是指一个二进制位在总线上传输所需的时间,它又由4段组成,每段由称为Time Quantum(Tq,时间单位)的最小时间单位构成。如下图所示:

位时间的4个段分别是:

(1)同步段(Synchronization Segment,Sync_Seg)

·用于同步接收器的时钟到传输器的时钟。

·持续1个Tq。

(2)传播时间段(Propagation Time Segment,Prop_Seg)

·用于补偿信号在总线上传输的时间延迟。

·可配置为1到8个Tq。

(3)相位缓冲段 1(Phase Buffer Segment 1,Phase_Seg1)

·用于补偿相位错误和支持重同步跳转。

·可配置为1到8个Tq。

(4)相位缓冲段2(Phase Buffer Segment 2,Phase_Seg2)

·用于补偿相位错误和支持重同步跳转。

·可配置为1到8个Tq。

每个 CAN 报文的二进制数据都通过这些位时间段进行传输。位时间的配置对于 CAN 总线的正确通信至关重要,它影响总线的传输速率、同步和误差处理能力,在数据手册中给出了TQ计算公式,TQ = 2 x (BRP + 1)/FOSC,其中FOSC为MCP2515外设晶振频率8MHZ,BRP为cnf1寄存器设置的预分频系数,可以任意设置,确保最后的TQ为整数即可,这里设置为0x01,然后对TQ进行计算得到TQ=500ns,这时候已经可以确定最小单位TQ的值为500ns,然后指定can的波特率为125K,然后相除就可以得到位时间8000ns/500ns=16个TQ,而在MCP2515的数据手册中要求时间段的设定必须满足以下要求:

(1)传播段 + 相位缓冲段 PS1 >= 相位缓冲段 PS2

(2)传播段 + 相位缓冲段 PS1 >= TDELAY (TDELAY 典型值为 1-2 TQ)

(3)相位缓冲段 PS2 > 同步跳转宽度 SJW(SJW 最大值为 4 TQ,一般取1 TQ即可满足要求)

最终确定各个段的值位:同步段1个TQ,传播段2个TQ,相位缓冲段PS1 7个TQ,相位缓冲段PS2 6个TQ,然后来根据各个段的值确定cnf1、cnf2、cnf3的取值。

CNF1寄存器内容如下图所示:

其中bit7-6为SJW同步跳转宽度位,根据数据手册的描述设置位1TQ即可满足要求,而bit5-0表示波特率预分频比位,上面计算的时候已经确定值为1,所以conf1的值已经确定为0x01。

CONF2寄存器内容如下图所示:

bit7为相位缓冲PS2段的时间长度位,这里设置为1,由CNF3寄存器决定。

bit6设置为0采样点配置位,这里设置为0,表示进行一次采样。

Bit5-bit3表示相位缓冲段PS1的长度,相位缓冲段PS1为7个TQ,所以Bit5-bit3应为6,换算为二进制为110,

Bit2-bit0表示传播段长度,传播段长度位2个TQ,所以Bit5-bit3应为1,换算为二进制就为001。

综上CNF2的值为10110001,换算成16进制就为0xB1。

CONF3寄存器内容如下图所示:

其中bit2-0表示相位缓冲段PS2长度,相位缓冲段为6个TQ,所以bit2-0值应为5,转换为二进制为101。而其他位设置为0即可,综上CNF3要设置的值为0x05。

190.2 RXB0CTRL寄存器配置

除了要配置CNF1、CNF2、CNF3三个CAN波特率配置寄存器之外,还需要对RXB0CTRL接收缓冲器0控制寄存器进行配置,RXB0CTRL寄存器内容如下图所示:

需要将bit6-5设置为11,表示接收所有的报文,其他位都设置为0即可,所以该寄存器要设置的二进制值为01100000,换算成16进制就为0x60。

190.3 CANINTE寄存器配置

最后还需要对CANINTE------中断使能寄存器进行配置,CANINTE寄存器内容如下所示:

可以得到写指令的指令格式为00000010,同样的可以编写写寄存器对应的函数,具体内容如下所示:

cpp 复制代码
void mcp2515_write_reg(char reg, char value) {
    int ret;
    char write_buf[] = {0x02, reg, value};  // SPI写缓冲区,用于发送写寄存器命令

    ret = spi_write(spi_dev, write_buf, sizeof(write_buf));  // 发送SPI写命令
    if (ret < 0) {
        printk("mcp2515_write_reg error\n");
    }
}

通过调用mcp2515_write_reg写寄存器函数就可以对上述三个小节讲解的寄存器进行修改了,具体内容如下所示:

cpp 复制代码
#define CNF1 0x2a                    // 寄存器定义
#define CNF2 0x29
#define CNF3 0x28
#define RXB0CTRL 0x2b
#define CANINTE 0x60
 
mcp2515_write_reg(CNF1, 0x01);  // 写入寄存器配置值
mcp2515_write_reg(CNF2, 0xb1);
mcp2515_write_reg(CNF3, 0x05);
mcp2515_write_reg(RXB0CTRL , 0x60);
mcp2515_write_reg(CANINTE , 0x05);

至此,关于配置模式中寄存器的配置就完成了,在下个小节中将会讲解一种常用的寄存器值修改方法位修改指令和屏蔽字节。

190.5 位修改指令和屏蔽字节

位修改指令(Modify Bit instruction)是一种指令或操作,允许用户在处理器或芯片的寄存器中修改单个位(bit),而不影响寄存器中的其他位。

屏蔽字节(Mask Byte):屏蔽处理器或芯片寄存器中特定位的字节值。屏蔽字节决定了在执行位修改指令时哪些位会被修改,哪些位会保持不变。通过在位修改指令中使用屏蔽字节,可以精确地指定要修改的寄存器位,而不会影响其他位的内容。

MCP2515支持位修改指令和屏蔽字节,MCP2515的SPI指令表如下所示:

位修改指令格式如下所示:

CS片选信号拉低之后依次向MCP2515发送位修改命令字节、寄存器地址、屏蔽字节以及数据字节。

屏蔽字节确定允许修改寄存器中的哪一位。屏蔽字节中的"1"表示允许对寄存器中的相应位进行修改;而"0"则禁止修改。数据字节确定寄存器位修改的最终结果。如果屏蔽字节 相应位置为"1",数据字节中的"1"表示将寄存器对 应位设置为1,而"0"将对该位清零,如下图所示:

然后来编写位修改指令的函数,具体内容如下所示:

cpp 复制代码
// MCP2515修改寄存器位函数
void mcp2515_change_regbit(char reg, char mask, char value) {
    int ret;
    char write_buf[] = { 0x05, reg, mask, value };  // SPI写缓冲区,用于发送修改寄存器位命令

    ret = spi_write(spi_dev, write_buf, sizeof(write_buf));  // 发送SPI写命令
    if (ret < 0) {
        printk("mcp2515_change_regbit error\n");
    }
}

在190.2章节中使用的是spi_write函数对RXB0CTRL寄存器全部的只进行的修改,在学习位修改指令之后就可以单独对要操作的位就行修改可以内容由

cpp 复制代码
#define RXB0CTRL 0x60
 
mcp2515_write_reg(RXB0CTRL , 0x60);

修改为

cpp 复制代码
mcp2515_change_regbit(RXB0CTRL, 0x64, 0x60);

至此,对于位修改的讲解就完成了,由于本章节只是对寄存器进行的讲解和配置,并不能得到具体的实验结果,所以本章不再进行实验,接下来的章节将继续对mcp2505驱动程序进行完善。

相关推荐
内核程序员kevin2 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
zy张起灵4 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
朝九晚五ฺ6 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream7 小时前
Linux的桌面
linux
xiaozhiwise7 小时前
Makefile 之 自动化变量
linux
意疏9 小时前
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
linux·docker
BLEACH-heiqiyihu9 小时前
RedHat7—Linux中kickstart自动安装脚本制作
linux·运维·服务器
一只爱撸猫的程序猿9 小时前
一个简单的Linux 服务器性能优化案例
linux·mysql·nginx
lantiandianzi11 小时前
基于单片机的多功能跑步机控制系统
单片机·嵌入式硬件