This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TCAN4550EVM:STM32F407/Keil 编译器的 CAN 初始化失败

Guru**** 1078800 points
Other Parts Discussed in Thread: TCAN4550, TCAN4550EVM, TCAN4550-Q1
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1254246/tcan4550evm-can-initialization-failure-with-stm32f407-keil-compiler

器件型号:TCAN4550EVM
主题中讨论的其他器件:TCAN4550、、 TCAN4550-Q1

您好!

在上一篇文章的帮助下、我能够与 TCAN 建立联系。 然后、我尝试将您的代码示例"转换"为用于 ST MCU 的 Keil 代码。 初始化失败。 其他 CAN 器件没有从 TCAN 获取 ACK。 尝试清除所有错误后、我立即收到"正在进行内部多传输模式访问"错误。 我在屏幕截图中记录了从我写入的寄存器读取的值。 你能看到什么问题吗?

我所做的是:

将"0xFFFFFFFFF"写入0x000C (清除 ERR 标志)

将"0"写入0x0830 (禁用中断)

0x0820读取并将该值写回 (清除中断标志)

将"0"写入位4&3、将"1"写入0x1018的位1&0 (启用受保护的寄存器)

0x1018读取、应用屏蔽(~(0xFFFF0C00 | 8))、将"1"设置为位9、8、1、0、并回写 (启用 BRS、FD、CCE、init)

将"1"写入0x1080的位4、2、1、0 (接受全局消息到 FIFO0)

将"5<<25 | 1<<16 | 30<<8 | 7'写到0x101C (Sjw=6、预分频器=2、tseg1=31、tseg2=8)

将"0<<16 | 13<<8 | 4<4 | 3"写入0x100C (预分频器=1、tseg1=15、tseg2=5、Sjw=4)

将"14<<8"写入0x1048 (TDCO=15)

将"0"写入到0x8000至0x87FF 之间的存储器 (清除存储器)

将"0"写入0x1084 (标准滤波器地址= 0x8000)

将"4"写入0x1088 (扩展滤波器地址= 0x8004)

将"0x800C | 5<<16| 0x80000000"写入0x10A0 (RX FIFO0元素=5、地址=0x800C)

将"0x8174 | 0<<16 | 0x80000000"写入0x10B0 (RX FIFO1元素=0、未使用)

将"0x8174"写入0x10AC (RX 缓冲元素=0、未使用)

将"0x8174 | 0<<16"写入0x10F0 (RX 缓冲元件=0、未使用)

将"0x8174 | 2<<24"写入0x10C0 (TX 缓冲元素=2、地址=0x8174)

将"7<<8 | 7<<4 | 7"写入0x10BC (RX 缓冲区大小= 64字节)

将"7"写入0x10C8 (TX 缓冲区大小= 64字节)

将"0"写入0x1018的位4、3、1、0 (禁用保护寄存器)

将"1"写入0x1054 (在 nINT 上启用 RX FIFO0中断)

将"0<<30 |1<<27 | 0x720<<16 | 0x7F9"到0x8000 (标准 id filter:SFT=0 (范围滤波器)、SFT=1 (存储在 FIFO0中)、SID1=0x720、SID2=0x7F9)

将"1<<29 | 0x12345678"写入0x8004并将"2U<<30 | 0x1FFFFFFF"写入0x8008 (XID 滤波器:EFEC=1、id=0x12345678、EFT=2、MASK=0x1FFFFFFF)

将'3U<<30| 1<<27 | 1<<10 | 1<<5'写入0x0800 (器件配置寄存器)

将"2"写入0x0800的第7位和第6位 (正常模式)

将"0xFFFFFFFFF"写入0x1050 (清除所有中断)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Reko:

    将"0"写入0x1084 (标准过滤器地址= 0x8000)

    将不会有标准 ID 滤波器、因为 LSS[7:0](位23:16)被设定为0。  我看到您正在尝试写入单个 SID 滤波器元素、因此0x1084的寄存器不正确。  

    将"4"写入0x1088 (扩展过滤器地址= 0x8004)

    将不会有扩展 ID 滤波器、因为将 LSE[6:0](位6:0)设置为0。  我看到您正在尝试写入单个 SID 滤波器元素、因此0x1084的寄存器不正确。  但是、您已将0x1080中的 ANFE 字段设置为接受所有不匹配的帧、因此如果没有 XID 过滤器、您仍应接收消息。

    您已将0x1080中的 ANFS 和 ANFE 字段设置为接受 RX FIFO 1的所有不匹配帧、因此如果未创建 SID/XID 筛选器元素、您仍应接收该消息。  您的笔记说您已分配0个(或否) RX FIFO 1元素、因此这可能会导致接受不匹配的帧时出现问题、您应更改此设置以将它们存储在 RX FIFO 0或分配 RX FIFO 1元素中。

    但是、在验证您的配置时遇到困难。  您能否确认您要写入配置寄存器的最终十六进制值、而不是您要用于写入这些寄存器的逻辑?  当我尝试验证 RX FIFO 0/1和 RX/TX 缓冲器元件的数量时、我得到的值与您在注释中描述的值不同。  这可能意味着我没有按照您的或和位移描述来获得最终的寄存器配置值、并且无法正确检查您的配置、或者您的寄存器配置出现问题。

    如果您只需提供一个最终寄存器值的列表供我查看、我可以更好地帮助您验证配置。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好。 感谢您找到我的错误。 我应该像您的代码示例一样、将全局滤波器连接到 FIFO 0。 实际上、我曾尝试从样本中复制大多数参数。 但 CAN 功能在纠正后仍然不起作用。
    对于 SID 和 XID 筛选器、我在 POST 中给出了错误的值。 在我的代码中、我放入'

    |1<<16'。 为了避免此类错误、我会添加更多行来确认每次写入操作的写入值和读回值。 初始化完成后、我再次从所有寄存器中读取。 下面的响应通过 COM 从 MCU 发送到 PC、除了我之后添加的注释。 所有值均为十六进制。

    //清除所有 ERR 标志
    写入0x000C:0xFFFFFFFF
    从0x000C 读取:8 //我得到这个错误"内部访问激活",不知道其含义
    //禁用中断
    写入0x0830:0
    从0x0830读取:809628ff //也有问题,因为809628ff 和 REG_BITS_DEVICE_IE_MASK = 0x80000000,应该为0
    //清除中断标志
    0 //读取值已经为0,MCU 通过每次读取报告响应
    写入0x0820:0
    从0x0820读取:0
    //启用保护寄存器
    300
    301
    303 //重试3次,成功
    写入0x1018:303
    从0x1018读取:303
    //启用 BRS&FD,已启用,只需像代码示例那样重新执行,为什么不与最后一步结合?
    写入0x1018:303
    从0x1018读取:303
    //设置全局过滤器
    写入0x1080:3 //拒绝远程帧,将其他帧放入 FIFO 0
    从0x1080读取:3
    //标称位时序和预分频器
    写入0x101C:A011E07 //SJW=6、预分频器=2、tseg1=31、tseg2=8
    从0x101C 读取:a011e07
    //写入数据位时序&预分频器寄存器
    写入0x100C:d43 //prescaler=1、tseg1=15、tseg2=5、Sjw=4
    从0x100C 读取:D43
    //发送器延迟补偿寄存器
    写入0x1048:E00 //TDCO = 15
    从0x1048:E00读取
    //SID 过滤器
    写入0x1084:10000
    从0x1084读取:10000
    //XID 滤波器
    写入0x1088:10004
    从0x1088:10004读取
    //RX FIFO 0
    写入0x10A0:8005000C //将数字设置为5,我需要这么多吗?
    从0x10A0读取:8005000c
    //RX FIFO 1
    写入0x10B0:80000174 //样本不使用 RX FIFO1但仍设置存储器地址
    从0x10B0读取:80000174
    //RX 缓冲器
    写入0x10AC:174 //样本不使用 RX 缓冲区、但仍设置存储器地址
    从0x10AC 读取:174
    //TX FIFO
    写入0x10F0:174 //样本不使用 TX FIFO、但仍设置存储器地址
    从0x10F0读取:174
    //tx 缓冲器
    写入0x10C0:2000174 //缓冲区大小=2
    从0x10C0读取:2000174
    //RX 缓冲器
    写入0x10BC:777
    从0x10BC 读取:777
    //tx 缓冲器
    写入0x10C8:7
    从0x10C8读取:7
    //禁用受保护的寄存器
    303
    写入0x1018:300
    从0x1018读取:300
    //启用 MCAN 中断
    写入0x1054:1
    从0x1054读取:1
    //扩展 ID 过滤器
    10000 //从0x1084读取地址
    写入0x8000:F2007F9 //SFT=0 (范围滤波器)、SFEC=1 (存储在 FIFO0中)、SID1=0x720、SID2=0x7F9
    从0x8000读取:f2007f9
    //扩展 ID 过滤器
    10004 //从0x1088读取地址
    写入0x8004:32345678 //EFEC=1 (存储在 FIFO0中)、ID=0x12345678
    从0x8004读取:32345678
    写入0x8008:9FFFFFFF //EFT=2 (经典滤波器)、MASK=0x1FFFFFFF
    从0x8008读取:9ffffff
    //器件配置寄存器
    c80004a0
    向0x0800写入:C80004A0 //WAKE_CONFIG =双向、CLK_REF = 40MHz、GPIO1 GPO = MCAN INIT1、通过写入强制为1
    从0x0800读取:c80004a0
    //设置模式
    c80004a0
    向0x0800写入:C80004A0 //正常模式
    从0x0800读取:c80004a0
    //清除所有中断
    写入0x1050:FFFFFFFF
    从0x1050读取:0
    //再次读取所有配置
    读取器件 ID1 (0x0000):4e414354
    读取器件 ID2 (0x0004):30353534
    读取错误标志(0x000C):8
    读取中断使能(0x0830):809628ff
    读取中断标志(0x0820):0
    读取 CCCR (0x1018):300
    读取全局过滤器(0x1080):3
    读取任意时序(0x101C):a011e07
    读取数据时序(0x100C):D43
    读取 TDC (0x1048):E00
    读取 sid 滤波器(0x8000):f2007f9
    读取 xID 滤波器(0x8004):32345678
    读取 FIFO 0 (0x800C):0
    读取 TX 缓冲器(0x8174):0
    读取 RX 缓冲区大小(0x10BC):777
    读取 TX 缓冲区大小(0x10C8):7
    读取器件配置(0x0800):c80004a0

    此问题发生在第一步。 "内部访问处于活动状态"错误的说明为"正在进行内部多传输模式访问"。 我不明白它的意思。 我可能是因为接线出现了问题吗? 除了 SPI 线以外、我仅将5V 和 GND 连接到 MCU。 我还没有准备好测试中断、因此 nINT 未连接。 我还应该注意其他引脚吗?
    我的当前代码充满冗余、可能没有帮助、因此我没有上传它们。 SPI 连接现在正常、反馈应可信。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Reko:

    让我们来看看您的配置...

    从0x000C 读:8 //我收到此错误"内部访问激活",不知道其含义

    内部访问激活并不是一个错误、它只是一个状态指示、指出器件正在访问内部存储器位置、例如寄存器或 MRAM 存储器单元。  并非所有状态位都有错误。  看到这个内部访问激活位被置位是正常的。

    //disable 中断
    写入0x0830:0
    从0x0830读取:809628ff //也有问题,因为809628ff 和 REG_BITS_DEVICE_IE_MASK = 0x80000000,应为0[/引号]

    从0x0830读取时设置为1的所有位都是一个只读保留位、其默认值为1、因此您很可能在将0x00000000写入此寄存器后不会读回0x00000000。

    //enable protected register
    300
    301
    303 //重试3次,成功[/报价]

    应该多次写入此寄存器。  第一次写入操作会置位 INIT 位。  然后第二次写入允许 CCE 位被置位。  一旦这两个位被置位、就可以置位该寄存器中的其他"受保护"位、所以第一次应该是3次。  您可以让 CCE 位保持置位、然后为了将来的保护而改变 INIT 位、将未来的写入周期减少到2次写入、但通常 INIT 和 CCE 一起置位、共有3次写入。

    [报价 userid="570517" url="~/support/interface-group/interface/f/interface-forum/1254246/tcan4550evm-can-initialization-failure-with-stm32f407-keil-compiler/4747238 #4747238"]//Nominal Bit Timing 和预分频器
    写入0x101C:A011E07 //SJW=6、预分频器=2、tseg1=31、tseg2=8
    从0x101C 读取:a011e07

    这样会将您的标称位时间设置为500kbps、采样点为80%。  

    //Write to Data Bit Timing & Prescaler 寄存器
    写入0x100C:d43 //prescaler=1、tseg1=15、tseg2=5、Sjw=4
    从0x100C 读取:d43[/报价]

    这样应该会将数据位时间设置为2Mbps、采样点为80%。  但是、对于在数据阶段具有更快比特率切换的 CAN FD、您需要启用发送器延迟补偿(TDC)位23至1。

    //发送器延迟补偿寄存器
    写入0x1048:E00 //TDCO = 15
    从0x1048读取:e00

    通常情况下、TDCO 的值设置为等于数据位域中采样点之前的 tq 数。  此位域不能解释为大于该值的1、因为0是有效数字。  因此、由于采样点前的位周期内有15 tq、所以你需要将 TDCO 设定为0xF (十进制的15)。  总寄存器值将为0x00000F00。  值为0xE 时可用、这可能导致在传输阶段使用75%而不是80%的内部辅助采样点(SSP)。  

    //sid 筛选器
    写入0x1084:10000
    从0x1084读取:10000 [/报价]

    这将在 MRAM 空间中启用起始地址为0x8000的1 SID 滤波器元件。  每个 SID 滤波器元件占用4字节或1字的内存。

    //XID 过滤器
    写入0x1088:10004
    从0x1088读取:10004[/报价]

    这将在 MRAM 空间中启用起始地址为0x8004的1 XID 滤波器元件。  每个 XID 滤波器元件占用8个字节或2个字的存储器。  这看起来是正确的、因为它允许 SID 滤波器所需的1个存储器字。

    //RX FIFO 0
    写入0x10A0:8005000C //将数字设置为5,我需要这么多吗?
    从0x10A0读取:8005000c
    [/quote]

    这将在 MRAM 空间中启用起始地址为0x800C 的5个 RX FIFO 0元素。  这看起来是正确的、因为它允许 XID 滤波器所需的2个字的存储器。  所需的 RX FIFO 元素数量取决于 MCU 检查新消息之间需要保持的未读消息数量。  拥有未使用的 RX FIFO 元素并没有什么坏处、但是如果不够、您可能会在 FIFO 已满时丢失消息。

    //RX FIFO 1
    写入0x10B0:80000174 //样本不使用 RX FIFO1但仍设置存储器地址
    从0x10B0读取:80000174

    这不会启用任何 RX FIFO 1元素、因为 F1s[6:0]设置为0x0。  因此、MRAM 起始地址将被忽略。  您可以将起始地址设置为所需的任何值、只要元素数量设置为0。

    //rx 缓冲区
    写入0x10AC:174 //样本不使用 RX 缓冲区、但仍设置存储器地址
    从0x10AC 读取:174[/报价]

    没有像 RX FIFO 那样为 RX 缓冲区指定特定计数。  您必须通过寄存器0x10BC 的 RBDS[2]字段以及配置中使用的起始地址为 RX 缓冲区分配的数据字节数来跟踪已分配的 RX 缓冲区数量。  向专用 RX 缓冲器元件接收消息的唯一方法是通过滤波器元件。  因此、您需要根据滤波器确定需要多少个专用 RX 缓冲区元素、然后计算 MRAM 配置中的起始地址和结束地址、以免发生存储器分配的重叠。  如果您不打算使用专用 RX 缓冲区、那么起始地址无关紧要。

    //TX FIFO
    写入0x10F0:174 //样本不使用 TX FIFO、但仍设置存储器地址
    从0x10F0读取:174

    这是 TX 事件 FIFO、而不是 TX 发送 FIFO。  该 FIFO 保存成功传输事件的记录、以便 MCU 在需要时进行监控。  但是、如果事件 FIFO 大小位字段设置为0、则会忽略起始地址。

    //tx 缓冲区
    写入0x10C0:2000174 //缓冲区大小=2
    从0x10C0读取:2000174

    这将在 MRAM 空间中的起始地址为0x8174的 TX FIFO 配置中启用2个 TX 缓冲元素。  由于先前的元素未使用、因此该起始地址看起来是正确的、并分配 RX FIFO 0 (90个字)所需的正确字数。

    //rx 缓冲区
    写入0x10BC:777
    从0x10BC 读取:777

    即使仅对消息使用 RX FIFO 0、您也已将所有类型的 RX 缓冲区和 FIFO 元素的数据字段大小设置为64字节。  这是可以的、与未使用的元素类型关联的字段无关紧要。

    //tx 缓冲区
    写入0x10C8:7
    从0x10C8读取:7

    您已将 TX 缓冲区/FIFO 元素的数据字段大小设置为64字节。

    //disable 受保护的寄存器
    303
    写入0x1018:300
    从0x1018读取:300[/报价]

    这将对配置寄存器进行写保护。

    //enable MCAN interrupts
    写入0x1054:1
    从0x1054读取:1

    这将启用将 RX FIFO 0新消息中断反映在中断线路上。

    10000 //从0x1084读取地址
    写入0x8000:F2007F9 //SFT=0 (范围滤波器)、SFEC=1 (存储在 FIFO0中)、SID1=0x720、SID2=0x7F9
    从0x8000读取:f2007f9

    根据您的注释正确配置此元素。

    //extended id filter
    10004 //从0x1088读取地址
    写入0x8004:32345678 //EFEC=1 (存储在 FIFO0中)、ID=0x12345678
    从0x8004读取:32345678
    写入0x8008:9FFFFFFF //EFT=2 (经典滤波器)、MASK=0x1FFFFFFF
    从0x8008读取:9fffffffffff[/quot]

    根据您的注释正确配置此元素。

    //device 配置寄存器
    c80004a0
    向0x0800写入:C80004A0 //WAKE_CONFIG =双向、CLK_REF = 40MHz、GPIO1 GPO = MCAN INIT1、通过写入强制为1
    从0x0800读取:c80004a0
    //设置模式
    c80004a0
    向0x0800写入:C80004A0 //正常模式
    从0x0800读取:c80004a0

    这样会将器件设置为正常模式、并且根据您的注释、配置看起来是正确的。

    如果可能对 TDCO 值进行了稍微的更改、一切看起来都很好。  

    您是否仍无法与这些设置进行通信? 尝试向 TCAN4550发送消息后、是否正在读取状态寄存器和中断寄存器?  是否设置了与配置序列期间读取的初始值不同的任何新位?

    您是否能够在尝试发送或接收消息时监控 CANH 和 CANL 线路的活动?  如果您认为您得到的是 CAN 总线活动、那么您还可以监视错误计数器寄存器(0x1040)和协议状态寄存器(0x1044)、但消息中包含错误。  

    您是否尝试传输消息?  如果是、您要将消息内容写入哪个 MRAM 地址? 对于具有2个元素的 TX FIFO 配置、您需要跟上正确的缓冲区、通过 TX FIFO/队列状态寄存器(0x10C4)用于报文。  但是、您应该能够接收从总线上的另一个器件发送的消息。

    此致、

    乔纳森

    [/quote][/quote][/quote][/quote][/quote][/quote][/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢大家为我完成每个设置步骤。 事实证明问题出在 CAN 电缆上、当 TCAN4550EVM 从其他同事那里交给我时、该电缆已经连接好。 由于我有很多关于编码的问题、所以在您验证我的配置之前、它才成为我的可疑部件。 现在我成功地 确认收到的信息并发送我的信息。

    至于数据比特率设置、我打算 像代码采样那样将采样点设置为75%。 我在评论中犯了一个错误。 我使用的 TSeg1为14、而不是15。 样本使用的'dataTqBeforeSamplePoint'为15 (tseg1 + 1同步位)。  根据代码示例中的注释、写入的值为15-2。

    第二步对我来说仍然有点困惑,虽然你说我的回应是正常的。 根据我从代码采样中了解到的情况、0被写入 TCAN、并且一个返回值( 由屏蔽与)应该等于写入的值。 略有不同。  

    bool
    TCAN4x5x_Device_ConfigureInterruptEnable(TCAN4x5x_Device_Interrupt_Enable *ie)
    {
        AHB_WRITE_32(REG_DEV_IE, ie->word);
    #ifdef TCAN4x5x_DEVICE_VERIFY_CONFIGURATION_WRITES
        // Check to see if the write was successful.
        uint32_t readValue = AHB_READ_32(REG_DEV_IE);       // Read value
        readValue &= REG_BITS_DEVICE_IE_MASK;               // Apply mask to ignore reserved
        if (readValue != (ie->word & REG_BITS_DEVICE_IE_MASK))
            return false;
    #endif
        return true;
    }

    并且我已经保存了关于 FIFO 和缓冲区的问题、直到我的主要问题现在解决了。 该代码示例仅对 RX 使用 FIFO 0并对 TX 使用缓冲区。 RX 缓冲区和 TX FIFO 被禁用。 使用 FIFO 和缓冲区有何区别? RX FIFO 和缓冲器由滤波器分布、那么 TX 呢? 所有发送的消息会先通过缓冲区、然后再通过 TX FIFO 吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    我很高兴听到您的设置正在进行通信。

    很抱歉误解了您的第二步问题。  我忽略了它的"and"价值部分、并且您特别质疑为什么在和之后将位31设置为"1"而不是"0"。  

    //disable 中断
    写入0x0830:0
    从0x0830读取:809628ff //也有问题,因为809628ff 和 REG_BITS_DEVICE_IE_MASK = 0x80000000,应为0[/引号]

    我现在是否正确理解了您的问题?

    如果是、您可能正在使用的演示代码的较早版本具有不正确的掩码值、位31不正确。  这在2020年6月8日 的1.2.2版中进行了更新。

     *  Updated 6/8/2020
     *      - 1.2.2: Corrected incorrect mask value for REG_BITS_DEVICE_IE_MASK (bit 31 is now 0)
     
     
     //The corrected mask was changed to the following value in this code:
     #define REG_BITS_DEVICE_IE_MASK                     0x7F69D700 //! This mask is the bitwise-inverse of the 0x0830 IE register's reserved bits. A reserved bit is read as high always. This masks the reserved bits out.

    并保存了有关 FIFO 和缓冲区的问题,直到我的主要问题解决为止。 该代码示例仅对 RX 使用 FIFO 0并对 TX 使用缓冲区。 RX 缓冲区和 TX FIFO 被禁用。 使用 FIFO 和缓冲区有何区别? RX FIFO 和缓冲器由滤波器分布、那么 TX 呢? 所有发送的消息会先通过缓冲区、然后再通过 TX FIFO 吗?

    您可以使用 RX FIFO 和缓冲区元素的组合、或者只使用一种类型、具体取决于所需的应用结构。 如果有一条特定消息或消息可以过滤到 MCU 可以检索的已知位置、而该地址始终是固定的、则 RX 缓冲区会很有用。  不同类型的消息可以有不同的专用缓冲区,您可以通过这种方式管理消息。

    但是、如果您接收到其他消息、或者只是想按照收到的顺序对它们进行处理、FIFO 方法可能会更有用。  还有两个不同的 FIFO、可以对不同类型的消息进行某种区分。

    如前所述、您可以同时配置 RX FIFO 0、RX FIFO 1和专用的 RX 缓冲区元件、然后根据您的应用需求使用滤波器元件将消息定向到各个位置。

    TX FIFO 或队列以及专用缓冲区元素也是如此。  如果 MCU 只需要发送少量消息、那么专用 TX 缓冲区可能是最简单的方法、因为 MCU 可以简单地将消息写入缓冲区位置、然后设置 TX 缓冲区添加请求寄存器中的相应位来发送消息。  只要这些相同的 TX 缓冲元件成功传输了前一条消息、就可以将其重复用于未来的消息。  MCU 可以通过读取 TX 缓冲区请求挂起寄存器来监控这种情况。

    也可以使用 TX FIFO 或队列。  你不能同时使用 FIFO 和队列、但是你仍然可以拥有 FIFO 或队列的专用 TX 缓冲区。  

    TX FIFO 将按照报文放入 FIFO 的顺序发送报文、而不管报文 ID 是什么。  队列与 FIFO 的区别在于:首先评估报文 ID、然后根据最低的报文 ID 值确定传输优先级、因为根据 CAN 仲裁协议它具有最高优先级、因此假定该报文在器件中应按照优先级进行传输。

    TX FIFO/队列和专用缓冲区在缓冲区数量方面都使用相同的32个 TX 缓冲区元素、但可以将它们分配给这两种类型、从而允许您自定义应用程序。

    TCAN4550-Q1使用由 Bosch 开发的 MCAN CAN FD 控制器 IP、 MCAN 用户手册 应视为 TCAN4550-Q1数据表的补充文档、因为数据表中可能不会包含所有 MCAN 信息。  TCAN4550-Q1中与 MCAN 相关的寄存器已被赋予0x1000的偏移量、否则 IP 本身中没有任何变化。  例如、 在 TCAN4550-Q1器件中、MCAN 用户手册中的控制寄存器的地址为0x18。  本文档更详细地介绍了许多 CAN 配置设置、对您的软件开发有很大好处。

    此致、

    乔纳森

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的详细解释。  它可以帮助我更好地了解编码工作。

    我在网站上只找到了一个代码示例( 新示例具有相同的文件名、因此我没有发现更新)。 是否有其他示例可以帮助 我学习使用中断和 TX FIFO?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    演示代码只有一个版本、因此遗憾的是、我不能让您参考使用 TX FIFO 模式的其他示例。

    通常来说、对于 FIFO、MCU 需要监控 FIFO 状态寄存器以检查填充级别、并输入地址来确定放置下一条应发送的消息的 TX 缓冲器元件。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    可以了、没有更多代码样片可用。 我只是希望他们让我的学习更容易。 如何设置寄存器很难弄清楚、因为有些位接受写入它们的值、有些位通过写入1进行复位、有些位不会被修改。

    目前、我对通过 ISR 接收消息更感兴趣。 该示例使用轮询 并禁用所有中断。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    我懂了。  如果您只是想不到任何具体问题、可以随时通过此论坛寻求支持。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    ISR 仍然不起作用。

    我发现该示例已启用 RX FIFO 0的中断(0x1054设置为1)。 另一个中断启用寄存器0x0830 完全为0、但我看不到任何与消息接收相连的内容。 因此、  虽然只 使用轮询 进行 消息 接收、但我认为中断已启用。 但是、在  通过 万用表传入消息期间、我未检测到 nINT 上没有压降(从3.3V 产生)。 我是否错过了一些操作?

    配置参数与上述相同。 我能够在主函数的 while 循环内接收带代码的消息。 通过测试 ISR、我将它们移走、以防它们在中断发生时立即清除中断。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Reko:

    寄存器0x105C 的值是什么?  您可能需要将启用中断线路0 (EINT0)位0设置为"1"。

    TCAN4550有一个"全局"中断引脚(nINT)、但 MCAN IP 在内核中有两条中断线路、可用于根据优先级或类型分离中断位。  每个 MCAN 中断位可以单独启用、也可以分配给两条 MCAN 中断线路中的任何一条。  这是通过寄存器0x1054和0x1058完成的。

    然后、可通过寄存器0x105C 启用或禁用两条 MCAN 中断使能线路、而默认情况下、这两条线路都是禁用的。  (我不知道为什么...)

    nINT 引脚将表示所有已启用和未屏蔽的中断位、但如果您需要单独的 MCAN 中断引脚、而该中断引脚不包含与电压、温度、SPI 错误、看门狗等相关的其他类型的位、那么您也可以将 GPO2和 GPIO1引脚配置为 MCAN 中断引脚。  

    例如、一些用户更喜欢为 RX 消息提供专用中断、可以根据 MCU ISR 对这些中断进行优先级设置。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您是对的! 设置0x105C 会启用中断。 具有单独的中断很好。 我决定使用 GPO2。

    我对寄存器0x0824和0x1050有一点困惑。 它们具有相同的寄存器映射、我只需关心0x1050。 前一个的含义是什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    地址为0x1000到0x10FF 的寄存器是 MCAN 控制器 IP 的一部分。  寄存器0x1050是 MCAN 相关位域的中断寄存器。

    TI 会添加地址为0x0800至0x08FF 的寄存器、用于实现与 MCAN 无关的器件功能。  寄存器0x0820是非 MCAN 相关位字段的中断寄存器。

    为了使 MCU 能够读取所有器件寄存器、需要读取两个寄存器0x0820和0x1050、这需要两个单独的 SPI 读取事务。

    为了提高 SPI 的效率、使用与寄存器0x0820相邻的地址0x0824创建了寄存器0x1050的只读副本。  通过将长度字段设置为"2"、这允许单个 SPI 读取事务读取所有中断。  这减少了 MCU 读取中断位所需的总时间并提高了效率。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、接收消息时出现了新问题。 我不确定哪种方式更好、继续在这里提问或打开一个新主题。

    该示例对中断时间进行计数并在主函数中解决它们。 仅使用 RX FIFO0。 我使用了 FIFO 0和1。 因此、我尝试简化工作并在 ISR 内完成所有事情。 nINT 和 GPO 的 LED 在正常工作的情况下闪烁、但它们在运行一段时间(非恒定)后可能会一直亮起。 我想这是由我重置中断的方法导致的。

    我使用了 GPO2作为 MCAN 中断并将其输入到我的 MCU。 当 GPO2变为有效状态时、MCU 上的输入引脚设置 ISR。 我在 ISR 开始时复位 MCU 中断、并且在处理 所有中断后复位 TCAN 上的中断(写入0x1050)。 即使在处理旧消息时出现新消息、最终状态也是不活动的、因此下一条新消息将触发 ISR。 我不明白为什么 TCAN 上的中断会卡在活动状态。 有误解吗?

    我试图读取错误状态、并且从0x0820读取的值为0x88、只能唤醒和全局错误。 一种有趣的 现象 是、当发生错误时、从 RX FIFO 读取的值是错误的。 我的 FIFO 0只允许使用特定的 ID、但读取并计算出另一个 ID (在本例中为0x211)。 其他数据也不是预期数据。

    你 在处理 这些 问题方面是否有任何经验?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    在 ISR 中处理所有内容的问题是、当你正在处理一个中断事件并正如你观察到的那样将中断引脚保持在低电平时、它会增加新事件发生的几率。  这意味着您的 MCU 将基本上在 ISR 中保持"停滞"、无法处理任何主循环函数。  这就是为什么演示代码在 ISR 本身内部发挥尽可能小的作用、这样 MCU 就不会卡住。

    如果您读取中断寄存器以确定设置了哪些位、但没有立即清除它们、则可能会在 MCU 清除这些位之前设置其他位、MCU 没有意识到这些位已设置。  因此、您需要在 ISR 结束时的最后一次重新读取中断寄存器、以确定在退出 ISR 之前是否需要清除任何新位。

    你知道哪些中断仍然被设置、并且是否已经比较了 ISR 开始时和结束时的寄存器读取值?  如果清除了所有中断位、则中断引脚应再次被拉高。  如果它保持低电平、仍然设置了位。

    如果您从寄存器0x0820读取0x88的值、则会出现某种类型的 SPI 错误(位3)、并且由于设置了 SPI 错误位、全局错误(位7)被置位。  这可能来自 SPI 驱动器的协议错误、信号完整性错误导致检测到太多或太少的 SPI 时钟周期/位、 数据、从而阻止来自数字内核寄存器或 MRAM 的数据通过处理系统时钟到 SPI 时钟频域交叉的 SPI FIFO。

    您是否始终获得该0x88值?  如果是、我们需要解决这个问题、因为它也会将 nINT 引脚保持在低电平。

    我可以查看消息筛选器中的配置错误、看看如果向我发送您写入 MRAM 的筛选器信息、我是否能找出您认为不应该收到的消息的原因。  

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jonathan:
    我的确理解在你所讨论的 ISR 中执行所有操作所面临的风险。 我这样做是为了控制不同操作的优先级、并在主循环中仅保留不重要的代码。 在我再次演示代码之后、如果我正确理解它、我就会发现潜在的风险。
    当接收到一个新的消息时、ISR 增加计数器、但是它不会立即在 TCAN 上复位中断(通过写入0x1050)。 因此、计数器不会增加、直到主循环处理最后一条消息。 它只处理一条消息、具有一个计数器。 如果在 TCAN 上复位中断前接收到新消息、那么接收到的消息可以正确计数。
    这是我遇到的问题。 起初、我复制了这个策略、虽然我没有使用计数器、而是在 ISR 中执行相应操作。 然后、我发现消息接收变得比同一网络中的另一个 CAN 器件慢一条或多条消息、因为 ISR 仅在多条消息进入 TCAN 时触发一次。
    然后、我添加了一个 while 循环来处理从 RX FIFO 读取的所有消息。  但这种方法也有一个严重的问题。 我不能保证清除的中断等同于正在处理的报文。 如果我清除值为0x1050的中断、如果它们稍后传入、MCU 可能会处理来自 RX FIFO 的更多消息(?我不确定这一点)。 所以我尝试了使用'0xFFFFFF'(不确定它是否有效)来在处理这些消息后清除0x1050中的所有中断。 这可能会在 RX FIFO 中留下未处理的消息、但至少有一个位置(我刚刚处理的位置)可用。 下一条消息将使 MCU 处理 RX FIFO 中的所有其余消息。

    如果我误解了工作原理、请指出我的错误。 如果这种策略遇到了问题、那就不应该是我现在遇到的问题了。 我的意思是 TCAN 的中断引脚 保持有效而不触发 MCU 的 ISR。
    问题不是很频繁。 实际上、它的概率非常低。 在我连接发送循环消息的测试样本之前、一切似乎都正常。 总线负载约为5.5%。 如果我不手动发送更多消息、重现错误可能需要相当长的时间。


    编辑:我增加了 FIFO 缓冲区并同时使用了 FIFO 0和1、这是我不使用像演示代码那样的中断计数器方法的另一个原因。 如果处理了每个 FIFO 中的一条消息、我不知道应该减少多少计数器。  关于 消息过滤器、还有一些奇怪的事情。 我没有在过滤器中设置任何"高优先级消息"、但我 记得 从0x1050看到它。 我在 mcan 用户手册中看到、您告诉我" 读取高优先级消息时、不应写入 FIFO 的确认索引"。 这可能是我的问题的原因。
    读取器件 ID1 (0x0000):4E414354
    读取器件 ID2 (0x0004):30353534
    读取错误标志(0x000C):8
    读取 CCCR (0x1018):300
    读取全局过滤器(0x1080):17
    读取任意时序(0x101C):A011E07
    读取数据时序(0x100C):D43
    读取 TDC (0x1048):E00
    读取 sid 滤波器(0x8000):FF107F9
    读取 xID 滤波器(0x8004):52345678
    读取 FIFO 0 (0x800C):0
    读取 FIFO 1 (0x8174):58DC2C6 (采样在读取期间接收消息)
    读取 TX 缓冲器(0x82DC):0
    读取 RX 缓冲区大小(0x10BC):777
    读取 TX 缓冲区大小(0x10C8):7
    读取 TX 缓冲器地址(0x10C0):20002E8
    读取中断标志(0x0820):0
    读取器件配置(0x0800):C84004A0
    读取中断使能(0x0830):809628FF
    读取中断寄存器(0x1050):0
    读取中断使能(0x1054):11
    读取中断线路选择(0x1058):0
    读取中断线路使能(0x105C):3

    编辑2:在另一天的尝试后,我怀疑这个问题与我 使用 GPO2的方式有关。 我之前认为它是3.3V 输出。 后来、我发现仅当 GPO2连接到 MCU 时、示波器才显示正常结果。 万用表仅检测不到其上的稳定电压。 GPO2上的每个中断都会触发 ISR 两次。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    演示代码只是一个入门参考、旨在帮助用户开始使用器件、并不是实际应用代码的黄金标准参考。  因此、您可以考虑和处理这些类型的场景、这一点很好。

    RX FIFO Get Index、Put Index 和 Fill Level 值应始终是用于确定处理多少条消息以及应首先处理哪个 FIFO 元素的值。  中断位仅用于提醒 MCU 需要处理一条或多条消息。

    我认为、从概念上讲、一旦设置了 RX FIFO 新消息中断位、MCU 就应该读取 RX FIFO 状态寄存器以确定填充级别和获取索引、从而允许它计算哪个 RX FIFO 元素、 或元素、包含需要读取的消息。

    完成后、应该可以清除中断位并继续读取并确认 RX FIFO 中的消息。  在这些消息被处理期间接收到的任何新消息将再次设置新消息中断位、表明有更多消息到达。

    不过、我想我理解您的基本观点、即有几种潜在的情形需要以代码的结构方式进行处理。

    一种情况是、在读取 RX FIFO 状态寄存器之后、前一次读取的消息被清除之前收到的新消息改变了填充级别。  如果中断位已经被清除、ISR 将导致器件重新读取状态寄存器、它将看到相同的 GET 索引、但填充级别更高。  如果中断位还没有被清零、新的报文将会存放到 RX FIFO 中、但 MCU 不知道新的报文已经到达。

    在这种情况下、MCU 应跟踪填充级别中有多少条消息以及有多少条确认、这将增加 Get 索引。  如果填充级别在有时间清除旧消息之前随新 RX 消息增加、MCU 可能可以通过某种内部计数器来检测到这种情况、该计数器会跟踪填充级别相对于 Get Index 的增加或减少情况。  

    如果中断位还没有被清零、新的报文将会存放到 RX FIFO 中、但 MCU 不知道新的报文已经到达。

    您可以在清除 MCU 认为在元素中的所有消息的末尾重新读取 RX FIFO 状态寄存器、以确保填充级别设置为零。  如果是、它应该重复 RX 读取和确认循环、直到 RX FIFO 为空。

    比较获取索引和 Put 索引也是一条可能的消息、用以确定 FIFO 是否已完全清除。

    无论采取哪种方法、我认为验证 RX FIFO 状态会显示 FIFO 在消息接收和处理例程结束时是空的、这应该始终让您知道、在处理现有消息时、是否有新消息到达。

    GPO2引脚在用作中断时是一个开漏引脚、因此它需要一个连接到 VIO 的上拉电阻器(通常为3.3V)。  当器件在测试模式下使用时、它成为驱动的数字输出类型、用于多路复用 MCAN TXD 信号或收发器的 RXD 信号。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Jonathan、您好、感谢您的详细分析。 它 可以帮助我理解工作原理。

    一开始、我几乎排除了硬件问题。 GPO2连接到已上拉至3.3V 的 GPIO。 TCAN 的5V 和 GND 连接至 MCU 板的那些电源。 有一点奇怪的是、3.3V 和 GND 上的 MCU 侧的电压都低了大约0.02V。 可能其结果是、如果随后进行另一个 SPI 写入操作、则通过写入0x1050来复位 TCAN 中断会第二次触发 ISR。 示波器显示起义曲线中的小振动。 如果我在写入0x1050后保持10ms、则不会发生这种情况。 但我认为这不是导致我的电流问题的主要原因。

    我在 ISR 内尝试了几种中断复位策略:

    1. MCU 上复位中断->复位0x1050 (读出的值或0xFFFFFFFF)->循环直到 RX 0中的填充级别为0 ->循环直到 RX 1中的填充级别为0

    2. 在 MCU 上复位中断 ->在 RX 中填充级别为0之前循环 ->在 RX 1中填充级别为0之前循环 ->复位0x1050 (通过读取的值或0xFFFFFFFF)

    3. 循环直到 RX 0中的填充级别为0 ->循环直到 RX 1中的填充级别为0 ->复位0x1050 (通过读取的值或0xFFFFFFFF)-> 复位 MCU 上的中断

    没有可以避免 TCAN 在不触发 ISR 的情况下激活中断的问题、这意味着接收 ISR 永远卡住。

    我将 UDS 消息分配给 RX0、将公共消息分配给 RX1。 常见消息频繁出现。 UD 消息是手动发送的、但会占用更多处理时间。 该问题主要是由传入的 UDS 消息发生的。 常见消息都是大数的、所以我添加了行来监视 RX FIFO0的处理。 根据我得到的信息、UDS 消息的最后处理成功、0x10A4的值为0 (填充级别)。 则问题会发生。 我再次读取这些值、它的值变为0x01010105。 0x1050中的值为0x955。

    对于 GPO2和 nINT 可以在不触发 MCU ISR 的情况下激活的可能性、你有什么建议吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    我不确定在 GPIO 电压电平方面是否能完全跟随您。  我相信您正在使用 TCAN4550EVM、该器件具有一个可调节 LDO、可为 TCAN4550-Q1提供 VIO 电压。  VIO 电压设置数字 IO 信号电平并为晶体振荡器电路供电。  您应该设置 VIO 电压以与 MCU 电平匹配。  您可以在 TCAN4x5x 评估模块用户指南中找到该板的原理图。  3.3V 和5V 电源轨上没有电压极性保护二极管、因此我不知道为什么 MCU 侧会有0.2V 的压降。  另请注意、如果为了使 GPO2引脚启用 LED 而闭合 S4 DIP 开关、则会在 EVM 的 VIO 电源轨上有一个10k 上拉电阻器连接到 GPO2。  如果 DIP 开关打开、将从 GPO2网络上移除该上拉电阻器。

    TCAN4550的优势之一是 SPI 接口、允许器件向没有 CAN 控制器的 MCU 添加一个 CAN 通道、或者在 MCU 中没有足够的 CAN 控制器时作为额外的 CAN 通道。  但是、由于通过 SPI 接口进行通信需要额外的时间、此 SPI 接口确实对可实现的总体消息频率存在一些限制。

    我不知道您的消息传输到 TCAN4550的速度有多快、但听起来处理速度比您处理速度快、这会导致完整的 FIFO 和永久中断。

    您可以尝试通过降低 CAN 报文频率来判断只要新报文到达的速度不够快、无法填充 FIFO、中断就会按照您的预期被清除。

    nINT 引脚是未屏蔽位的寄存器0x0820和0x0824的逻辑或。  寄存器0x0830是寄存器0x0820中位的启用屏蔽寄存器、您可以禁用任何您不关心导致 nINT 引脚上状态改变的中断位。  这是一个全局中断引脚、将反映任何和所有启用的器件中断位。

    寄存器0x0824是寄存器0x1050的只读副本、寄存器0x1054是这些寄存器的启用屏蔽、您可以使用它来禁用任何您不关心的位。

    只要其中一个寄存器中任何已启用的位已设置为"1"、就会设置 nINT 引脚、并且您可以读取这些寄存器以确定哪些位将 nINT 引脚保持在活动状态。

    关于 MCAN 中断、请注意、MCAN 控制器有两条中断线、可用于单独传递中断、允许您将某些中断隔离到另一个引脚、例如 GPO2或 GPIO1 (如果通过寄存器0x0800配置为这样使用)。

    中断线路选择寄存器0x1058允许您选择哪个中断线路(0或1) 用于那个特定的中断信号。  寄存器0x105C 可用于启用或禁用这些中断线路。  

    由于 GPO2和 GPIO1仅用于 MCAN 特定中断、因此只要分配给该线路的中断位被置位、它们就会保持置位。  这意味着这些引脚的引脚状态可能与全局 nINT 引脚不同、并且对于 CAN 消息的 ISR 例程来说可能是一个更好的选择、而不是使用由于任何原因可以设置的全局 nINT 引脚。

    如何配置 VIO 电压和中断?

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你是对的。  TCAN4550-Q1就是我要使用的模块。 比较方便可靠 一旦我烧毁了电压电源线,但事故后它仍然正常工作。

    默认情况下启用 GPO2和 nINT 的 LED。 我再次测量 GPO2上的电压、它是3.3V。 我似乎在上一次测量中犯了一个错误。

    消息频率远不及我相信 TCAN 的通信能力。 也许我的不当解释导致了您的误解。 ISR 错过 GPO2的压降信号后、0x1050中的值将变为0x955、此时也无法再次触发。 一段时间内不会处理消息、因此填充级别已满。 正常工作时、TCAN 足够快、可以将填充级别抑制为1。 顺便说一下、我要使用的网络是500k/2M、总线负载 仅为5%。

    我将 RX FIFO 0&1分配给了 mCAN_int0、并将 GPO2设置为 mCAN_int0。 两个 RX 都可以触发 GPO2上的中断。

    我添加了一些命令来在 ISR 的临界点提供反馈。 我看到 ISR 的最后一个过程是通过将0xFFFFFFFF 写入0x1050正确结束。 填充级别和 Push/Get 索引似乎也是正确的值。

    ...

    0x1050:10
    0x10B4:20101 (Fill level=1、处理消息)
    0x10B4:20200 (填充级别=0、循环中断)
    复位1050


    0x1050:10
    0x10B4:30201 (Fill level=1、处理消息)
    0x10B4:30300 (填充级别=0、循环中断)
    复位1050

    下一个 ISR 永远不会来。

    MCU 侧的外部中断在 ISR 开始时复位、以便在0x1050复位 TCAN 之前很长时间可以再次触发。 我能想到的唯一原因是要么 MCU 的中断没有复位、要么写入0x1050的命令不会复位 TCAN。 您认为第二个假设是可能的吗? 例如、TCAN 收到命令并已开始下拉电压时就会收到一条新消息。

    如果不能直接解决这个问题、或许我应该 找到另一种  解决方法、例如周期性地检查 GPO2上的电压电平和 ISR 的状态。

    可能性更低的另一个问题是我提到过一次的问题。 我设置4个滤波器、其 ID 分配给 RX FIFO0。 其他寄存器  由全局滤波器分配给 RX FIFO1。 发生此错误时、应该进入 RX1的 ID 消息由 RX0代码处理。  

    ......

    0x1050:10 (RX1中的新消息)
    0x10B4:20101 ( 读取0x10B4意味着它处于 RX1的循环中、这是正常的)
    0x10B4:30201
    0x10B4:30300 (填充级别=0、循环中断)
    复位1050


    0x1050:101 (RX0中的新消息和'Timestamp 回绕'、这是什么意思?)
    0x10A4:401 (读取0x10A4表示它处于 RX0的循环中)
    8A 101、4211 (最后一个数字是消息 id=0x211的十六进制值、应转至 RX1)
    0x10A4:0 (fill level=0、循环中断)
    复位1050


    0x1050:10
    0x10B4:302
    0x10B4:401
    0x10B4:0

    ...... (跳转至100ms 后、即 id=0x211的周期)
    0x1050:10
    0x10B4:40301
    0x10B4:401
    0x10B4:0
    复位1050


    0x1050:101 (再次出现"Timestamp wrap"、是否提示该错误的原因?)
    0x10A4:10001 (当下一个异常循环显示"获取/放置索引"  从 RX1->RX0->RX1、4->0->1微连续的模式时)
    8A 101,0211 (获取索引=0、id=211)
    0x10A4:10100 (填充级别=0、循环中断)
    复位1050


    0x1050:10
    0x10B4:20002
    0x10B4:20101
    0x10B4:20200

    复位1050

    ......

    有其他 ID 的正常消息处于活动状态、但每次发生错误时、RX0中仅采用 id=0x211。 我没有准备代码来读取滤波器、因此无法确认滤波器的状况。 我 计划 在第一个问题解决后重现此问题。  您知道它可能在什么条件下发生吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    感谢您的澄清。  可支持的最大总线负载取决于许多因素、但除非 SPI 比特率或处理器非常慢、否则您应该能够轻松支持5%的负载。  通过 SPI 总线使数据进出 TCAN4550是确保 RX/TX 缓冲元件不会填满的限制因素。

    MCU 侧的外部中断在 ISR 开始时复位、以便在0x1050复位 TCAN 之前很长时间可以再次触发。 我能想到的唯一原因是要么 MCU 的中断没有复位、要么写入0x1050的命令不会复位 TCAN。 您认为第二个假设是可能的吗? 例如、TCAN 收到命令并已开始下拉电压时就会收到一条新消息。

    如果不能直接解决这个问题、或许我应该 找到另一种  解决方法、例如周期性地检查 GPO2上的电压电平和 ISR 的状态。

    [/报价]

    在用0xFFFFFFFF 清除寄存器0x1050后、是否可以立即轮询寄存器0x1050、以了解新值是什么并确定是否设置了新位?

    如果可能、您可以在此过程中尝试监控或实际的 GPO2引脚电压、以便我们可以看到它是如何使用连接到 SPI 和 GPO2信号的逻辑分析仪或示波器对寄存器0x1050的读取/写入序列做出响应的?

    使用 MCU 来读取 GPO2引脚电压、使其为高电平或低电平也可能起作用、正如您建议的那样、在立即向寄存器0x1050写入0xFFFFFFFF 后查看其是否为低电平、我们知道这应该清除所有中断并将 GPO2引脚拉至高电平。  如果该值为低电平、则表明退出 ISR 不安全。

    希望我们可以弄清为什么 MCU 没有看到 GPO2、或者为什么它通过一些更直接的观察数据保持在低电平。  但与此同时、还有其他一些想法需要思考。

    尝试在 GPIO1上产生的另一条 MCAN 中断线路上使用 RX FIFO 水印中断位可能会很有意思。  如果应在每个新的 RX 消息时触发 GPO2中断、则理论上不应达到 FIFO 水线位、假设 RX FIFO 足够大、能够产生超出 MCU 应允许达到的高水线位。  然后、如果为 GPIO1线路设置的唯一中断位是水线位、则只有在 MCU 长时间处于低电平时无法对 GPO2中断引脚执行操作时、才应触发水线位。

    您还可以尝试设置某种类型的计时器、如果 MCU 在指定时间内没有收到来自 GPO2的中断、则该计时器会导致 MCU 轮询新消息、类似于看门狗。  然后每次 GPO2触发 ISR 时、这个计时器都会复位、从而在 GPO2线路卡滞时提供一种恢复方法。

    0x1050:101 (RX0中的新消息和"Timestamp wrapper"、这意味着什么?)

    存在一个内部计数器、用于创建时间戳、该时间戳可用于在发送或接收消息时进行跟踪和记录。  在帧接收/传输(SOF)开始时、计数器值被捕获并存储到 Rx 缓冲器/ Rx FIFO (RXTS[15:0])或 Tx 事件 FIFO (TXTS[15:0])元素的时间戳部分。  如果您喜欢使用此功能、有多种不同的计数器配置。  但是时间戳绕回(TSW)位只能向 MCU 指示内部时间戳计数器已经换过来再重新启动。  该计时器相当小、因此不幸的是、TSW 位将被设置得很高。  如果您不使用它、我建议您在0x1054中将其保持屏蔽状态、这样它就不会触发 GPO2或 nINT 中断引脚。  

    您能否与我分享您正在写入4个滤波器元素的滤波器数据字节?  您是否还能告诉我它们存储的顺序、或者每个滤波器的起始存储器地址是什么?  我可以尝试检查可能的错误。

    MCAN 将把消息 ID 与过滤器进行比较、过滤器从存储在最低存储器地址中的第一个过滤器元素开始、它将按顺序检查每个过滤器、直到找到能够传递消息的过滤器、 或者它将耗尽筛选器元素、并根据全局配置设置拒绝或存储消息。  一旦消息被过滤、MCAN 将停止检查其他过滤器。

    如果您有两个可以传递相同邮件 ID 的过滤器,例如经典邮件 ID 掩码和覆盖该 ID 的范围过滤器,则具有最低内存地址的过滤器应始终传递该邮件。  例如、如果您想将特定的消息 ID 0x211存储到 RX FIFO 1中、但又想使用范围滤波器将0x200到0x222 (0x211除外)到 RX FIFO0之间的所有消息 ID 存储起来、 然后、您需要将0x211的传统掩码滤波器存储到地址较低的 MRAM 位置、以便在距离滤波器之前对其进行检查。  更好的设计不会出现滤波器重叠的情况、但我们应验证您的滤波器是否存在某种逻辑问题。

    此致、

    乔纳森

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Jonathan:

    我试图在它复位后立即读取0x1050。 这样做后,第一个问题消失了,因为我提到过的问题。 复位 0x1050后的 SPI 写入操作会第二次触发 ISR、而不会有任何传入消息。 可能是由小电压振动引起的。 将照片传输到我公司的 PC 不方便、因此我在示波器上绘制了一张曲线图。

    两次触发防止了第一个问题(如果时间足够长、可能仍然会发生)、因此我无法 在故障期间确认0x1050中的值。  这本身不是一个大问题。 通常我会在 ISR 结束时复位0x1050、但不会发生该问题。 仍然无法直接解决缺少触发器的问题。 避免它的代价是额外的状态检查是我现在能想到的唯一方法。

    我还对 SPI 写入代码进行了一些修改。 我发现了两种在互联网上写入数据的方式。 一个是传输所有数据,然后等待!忙。 我看到演示代码使用了这种方法。 它也是我使用的方法。 但在我的条件下、我需要在以这种方式发送数据后有效数据进入之前读取一次 DR。 因此、我怀疑它可能不适合我正在使用的 MCU。 今天我尝试了第二种方式,在发送一个字节后读出每个字节(然后忽略它们)。 这比我在逻辑分析仪中看到的第一种方法慢一点。 通过这种方式、我还没有重现第二个问题。 但我不确定问题是否解决了。 它没有给我多少时间尝试。

    我忘记上传滤波器的配置值了。 我按顺序将它们设置为0x7F1->0x7F9、0x720+0x728、0x730+0x738、0x781+0x789。 读取的值正常、但工作正常。 我将在下周出错时尝试读取这些值。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    由于 GPO2引脚是一个开漏引脚、与外部上拉电阻器一起被拉至高电平、它可能容易受到噪声、串扰耦合或网络上其他一些灌入电流的负载的影响。  我会尝试自己看看这个。

    需要为 MCU 调整 SPI 驱动器。  只要 SPI 数据位采用数据表中列出的正确顺序、TCAN4550就不关心您在 MCU 中采取的方法。  因此、请使用最适合您的 MCU 的方法。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Jonathan、您好、我认为第一个问题仍然与 SPI 通信有关。

    我通过循环检查 GPO2状态的愚蠢方法无法解决第一个问题,但它给了我有关问题发生频率的反馈。 我 继续分析反馈的问题。 我 删除了 SPI 通信以外的操作、例如转换数据并将其发送到 PC、 认为它们可能会干扰 SPI。 令我意外的是、MCU 使用更干净的代码更频繁地错过了 GPO2中的中断。 然后、我发现在 SPI 读写之间增加时间(更改 nCS 后的延迟或进行其他操作)会降低出现问题的可能性、这意味着我应该避免连续的 SPI 通信。

    此外、减小 SPI 时钟也会降低该问题的发生频率。 TCAN 支持最高18MHz 时钟速度 、因此我已将其设置为10MHz。 我看到该演示仅使用2M SPI 时钟 、因此我尝试将时钟减少到2.5MHz、 第一个问题变小。 但这会导致寄存器损坏的几率更高、当我使用更快的 SPI 写入方法时通常会发生这种情况。

    到目前为止,我只在 SID 过滤寄存器中发现了损坏(我的网络中没有 xid msg)。

    正常:
    从0x8000读取:FF107F9
    从0x8004:4F200728读取
    从0x8008:4F300738读取
    从0x800C 读取:4F810789

    损坏1:
    从0x8000读取:1CC00000
    从0x8004读取:680000
    从0x8008读取:F021903
    从0x800C 读取:0

    损坏2:

    从0x8000读取:FF107F9
    从0x8004:4F200728读取
    从0x8008:4F300738读取
    从0x800C 读取:8200100

    我将这些问题总结为两个条件:

    10MHz SPI 时钟:GPO2 (或 nINT)激活、不触发 MCU 中断

    2. 较低的  SPI 时钟或较慢的 SPI 通信:寄存器损坏

    由于演示代码使用2M SPI 时钟来支持500k/2M 的波特率、我想它能够 用10M 时钟处理5%总线负载的所有消息。 这就是为什么我通过 SPI 读出所有接收到的消息,虽然只有一小部分被传输到 PC。 也许我应该拒绝来自全局过滤器的消息。 您是否认为 根据您的应用体验阅读所有收到的消息是常见的做法?

    在 SPI 通信之间增加延迟的解决方案目前似乎是最佳的解决方案、但会导致 UART 传输中的字节丢失更多。 由于 这个问题与 TCAN 无关、我已经将其保存下来以备后用(我不知道为什么在我将它们的主要优先级设定为相同之后中断会相互干扰)。 即使没有延迟、示波器也显示了每个读取操作之间超过400ns 的正常高电压电平。 我 不明白它为什么会在延迟时间更长时更稳定。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    听起来可能存在一些信号完整性问题、例如串扰或信号反射可能会导致问题。  这可能是由于您使用的是一个多板配置、我假设使用跳线连接两个板。  没有跳线的单板解决方案的性能可能会更好。

    TCAN4550-Q1将从数字时序角度支持18MHz。  唯一真正的限制是 SPI 时钟必须至少比 OSC1/2引脚上提供的系统时钟小2MHz。  有一个 FIFO 用于处理在 SCLK 上运行的 SPI 数据和在系统时钟(通常为20MHz 或40MHz)下运行的数字内核之间的时钟域交叉。  由于20MHz 是建议的最低系统时钟、因此最大 SPI 时钟为18MHz、并在器件级别验证该频率的时序。

    您是否观察到 SPI 信号本身存在任何信号完整性错误、例如振铃或串扰?  设置时间和保持时间是否适合避免采样错误?  我怀疑 SPI 与 GPO2导线之间可能存在一些耦合、这可能会解释 GPO2触发问题。  电路板之间是否也具有良好的 GND 连接?

    我不能很好地解释为什么您会在某些情况下看到数据损坏、而这些情况在 SPI 时钟速率较慢时似乎也会变得更糟。  这是意料之外的。  您是否曾在寄存器0x0820中报告任何 SPI 错误?  您是否可以监视寄存器0x000C 和0x0820中是否存在与您看到的故障相关的已设置位?

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您的假设完全正确! 我使用电线连接两个板。 也许这是我所有麻烦的原因,但我现在无法验证它。 目前仍在评估 MCU 可为测试设备提供哪些功能、因此 不会 修复连接。 我只希望在实际应用之前、能消除尽可能多的个人错误。

    我已经记录了两个寄存器损坏条件的错误寄存器:

    sid 滤波器:
    从0x8000读取:1CC00000
    从0x8004读取:680000
    从0x8008读取:F021903
    从0x800C 读取:0
    读取错误标志(0x000C):35000A
    读取中断标志(0x0820):88


    sid 滤波器:
    从0x8000读取:FF107F9
    从0x8004:4F200728读取
    从0x8008:4F300738读取
    从0x800C 读取:8200100
    读取错误标志(0x000C):34000A
    读取中断标志(0x0820):4A8

    我看到了 SPI 下溢和溢出。 它们是否支持您对信号完整性故障的假设?

    我还没有想出如何分析这种可能性。 因为它发生在许多传入消息中、所以我不知道如何仅因故障而捕获信号。 我可以说的是、 随着传入的消息减少、函数变得更加稳定。 如果所有循环消息都被拒绝、寄存器损坏和中断故障问题几乎消失(测试时间很长)。

    GND 在两个电路板之间连接、但 电压差很小、因为 GPO2导线两侧存在电压差。 万用表对于非常小的电阻测量不有效、但导线非常短。 通过 MCU 的电流应该不是很大、我认为。 因此、该电压差对我来说有点奇怪。

    和校正的输入和偏移。

    SPI 时钟越低、数据 写入越快(写入数据时不读取每个传输字节的 DR)、寄存器损坏就越严重。

    随着 SPI 时钟频率的提高和 SPI 通信频率的增加(SPI 传输之间的其他操作较少)、中断触发故障变得更加频繁。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    感谢您提供更多信息。  SPI 错误可能来自信号完整性或与时钟相关的问题。  当芯片选择信号为低电平时、此器件计算 SCLK 周期的数量并确保有一个适当的周期数量。  该数字必须是32的倍数、因为器件使用32位字。  此外、字数必须与标头中的"长度"字段匹配。  如果计数的时钟周期太少或太多、您将收到 SPI 错误。

    SPI 是一种边沿驱动协议、因此导致 SCLK 信号出现噪声或干扰的信号完整性较差可能会被视为额外的时钟周期。  片选线路上的噪声也会导致 SPI 事务过早终止。

    实际上、SPI 接口上使用了一个 FIFO 来处理 SPI 到系统时钟频率域交叉。  如果 SPI 或系统(OSC1/2)时钟工作不正常、那么数据也许不能正常通过这个 FIFO、这也将是一个 SPI 错误。

    这种情况的一个示例是 MCU 尝试读取 TCAN4550中的寄存器、但系统时钟未运行。  发生这种情况时、器件没有用于驱动数字内核并将该值返回到 SPI 接口 FIFO 的时钟、从而导致错误。

    TCAN4550的系统时钟可以来自晶体振荡器或单端时钟源、并且该器件使用比较器来检查 OSC2引脚是否"接地"、这会使器件进入单端时钟模式。  检测阈值介于90mv 和150mV 之间、典型值为100mV。  如果晶体电路未优化且 OSC2波形变得过大、最低峰值电压电平降至该检测阈值以下、器件可能会切换到单端时钟模式。  如果发生这种情况、器件会关闭放大器向 OSC1引脚上的晶体提供电流、并期望输入单端时钟。  但是、因为没有时钟、器件没有系统时钟、这会导致 SPI 和 CAN 通信错误。  但是、这种中断是暂时的、因为如果没有电流流入晶体、峰峰值幅度将衰减、并且 OSC2电压将再次上升到检测阈值以上、从而导致器件切换回晶体模式。  遗憾的是、此过程时钟模式切换可能会成为一个重复周期。

    没有任何状态或错误指示符会告诉我们时钟模式何时发生变化。  但是、它通常通过某种形式的 SPI 错误来检测、因为正如我提到过的、SPI 和系统时钟域都必须运行以防止 SPI 错误。  

    如需更多信息、请参阅 TCAN455x 时钟优化和设计指南 应用手册。  

    我没有看到任何与我们的 EVM 时钟相关的错误、但在其他板上看到过这种情况。  不过、晶体或该特定 EVM 上的负载电容器可能存在一些差异、因此这可能是我们需要检查的问题。

    我认为、当您使用 TI EVM 时、导线的信号完整性比与晶体相关的问题更有可能、 但是、您可以尝试将 OSC1和引脚以及晶体之间的0欧姆电阻器替换为较高的值、例如50至100欧姆、这将减少流向晶体的电流并降低 OSC2引脚上的振幅。

    如果该 EVM 存在晶体优化问题、导致您观察到的错误、则应该会解决这些问题。  但是、如果这不是与时钟相关的问题、那么串联电阻器将不会产生影响、但也不会损害性能、因此这绝对值得作为调试工作进行尝试。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    我想把这篇文章添加到我的上一篇文章中。  这就是您可以尝试更改为更高值的电阻器。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Jonathan、您好、感谢您提供这么多详细的说明。

    我的团队中只有一个 TCAN4550EVM-Q1、因此我想立即避免存在任何风险。 但我会记住它们。 我计划首先开发一个 TCAN 的可行应用、其中大多数 CAN 消息都被拒绝。 如果我们之后再购买更多的 TCAN、我会尝试彻底解决这个问题。 或者、当 TCAN 以更稳定的方式连接到 MCU 时、可能会直接解决该问题。

    有一个关于编程的小问题。 正如我说过的、为了避免 SPI 错误、我 计划在 MCU 侧而不是 PC 侧过滤消息。 这意味着我可能 必须频繁更改滤波器设置。 但 我发现 单独编写滤波器不起作用。 更改过滤器设置之前/之后、需要执行哪些操作? 我从演示中复制了初始化过程、不知道它们的用途。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    我从未尝试在应用程序中更改或调整滤波器设置、因此我必须作出一般性回复。

    滤波器元件本身只是存储在 MRAM 中的数据、因此没有任何东西会阻止 MCU 调整这些滤波器元件的内容。  不过、如果在 MCAN 控制器尝试将滤波器元件与传入消息配合使用时更新滤波器元件、这两个事件的时序可能会导致错误或滤波错误消息。  为防止发生这种情况、您应将 INIT 位设置为1、这将在您进行更改时阻止器件参与 CAN 通信。

    在此过程中设置 INIT 位的另一个原因是滤波器元件的数量、这些元件的起始地址通过受保护的寄存器进行设置。  因此、如果您需要改变滤波器元件的数量、为了改变这一点、您需要将 INIT 和 CCE 位设定为1。  

    所有消息元素必须位于连续存储器中、因为 MCAN 控制器将从起始地址的第一个元素开始逐个评估滤波器。  如果消息通过其中一个筛选器、则不会评估其余的筛选器元件。  如果它未传递任何筛选器元素、则将根据全局筛选器配置设置来处理消息。

    对于分配的每个过滤器、您还必须在 MRAM 中存储一个有效的过滤器元素。  换句话说、您不能保留比实际使用更多的筛选器元素、因为 MCAN 控制器将在消息到达时尝试检查这些筛选器。

    因此、如果您需要更改元素数量、还需要确保 MRAM 与寄存器配置相匹配。  这两种是标准 ID 滤波器和扩展 ID 滤波器、因此、如果您需要对这两种滤波器进行调整、则需要管理 MRAM、以免内存部分重叠。  我还建议将滤波器元件放置在所有其他 RX 和 TX 缓冲器配置之后、以便它可以在此过程中保持固定和不变。

    在寄存器配置和 MRAM 中对所有滤波器元件进行调整后、您需要将 INIT 位设回0、以便器件恢复正常操作并参与 CAN 通信。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Jonathan、您好、这与数据完整性无关。 我对全局滤波器寄存器进行了写入、但它的值没有改变。 我想在允许有效写入之前、我需要做一些准备、例如更改配置寄存器中的一些位。 初始化中有许多操作、我不知道需要哪种组合。
    至于中断、由于我只使用 GPO2、我能否删除有关 nINT (0x1054)的代码并且仅配置0x1058?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Reko:

    是的、您需要 先设置控制寄存器0x1018[1:0]= 1中的 INIT 和 CCE 位、然后才能写入全局滤波器配置寄存器。

    我认为您需要写入两个寄存器0x1054和0x1058。  寄存器0x1054是将启用或禁用中断域的中断启用寄存器。  寄存器0x1058是中断线路选择寄存器、用于选择您希望将中断位反映在两条 MCAN 中断线路中的哪条线路上。  默认情况下、为 m_CAN_int0行选择所有 MCAN 中断、可以根据寄存器0x0800的 GPO2_CONFIG 字段将其反映在 GPO2上。

    可以根据寄存器0x0800的 GPIO1_CONFIG 字段将 M_CAN_INT1行反映在 GPIO1上、因此如果您不打算使用此行、可以将寄存器0x1058保留为默认值(0x00000000)、以将所有中断分配给 GPO2。  不过、您仍需要通过配置寄存器0x1054来启用或禁用各个中断。

    此致、

    乔纳森