<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CAN寄存器操作]]></title><description><![CDATA[<p dir="auto">部分客户为了适配之前的软件结构，或是想要简化代码复杂度，需要采取纯寄存器操作。其中，由于RAM的寄存器定义在手册中并未体现，因此操作难点主要体现在RAM配置。<br />
这里以HA01为对象做一个简单的示例。</p>
<h1>型号及版本</h1>
<p dir="auto">EVB: HA01 EVB<br />
SDK: 1_4_0<br />
YCT: 2_7_8</p>
<h1>配置</h1>
<h2>控制器初始化</h2>
<p dir="auto">初始化主要包括以下几个方面：<br />
1. 选择CAN时钟源，在CTRL1.CLKSRC进行设置，设置时钟源时CAN需处于DISABLE状态；<br />
2. 通过MCR.MDIS使能CAN模块；<br />
3. 设置RXMGMASK、RX14MASK、RX15MASK和RXFGMASK，默认初始化为全F。以上四个寄存器只有在freeze模式下才配置生效（如果需要使用独立掩码，即MCR.IRMQ=1，则RXIMR也需要初始化为全F）；<br />
4. 初始化RAM，RAM寄存器数量为邮箱数*4，即如果有32个邮箱，则RAM[0]~RAM[127]需要被初始化为0，具体看使用邮箱数量。如果使用了enhance fifo，那么enhance fifo的RAM所在区域都需要初始化；<br />
5. 如果是FD模式，还需要完成以下步骤：<br />
1. 使能MCR.FDEN和CTRL2.BTE；<br />
2. 通过ENCBT和EDCBT配置仲裁段和数据段速率；<br />
3. 通过FDCTRL.MBDSRn配置payload；不同payload下每个邮箱占用的空间不同。<br />
Classic CAN (8B):  仲裁字段(2字) + 数据(2字) = 4 words<br />
CAN FD 16B:        仲裁字段(2字) + 数据(4字) = 6 words<br />
CAN FD 32B:        仲裁字段(2字) + 数据(8字) = 10 words<br />
CAN FD 64B:        仲裁字段(2字) + 数据(16字) = 18 words<br />
4. 使能CTRL2.ISOCANFDEN；<br />
5. 通过FDCTRL.FDRATE使能数据阶段高速率。<br />
6. 设置波特率。通常情况下，可以在CTRL1中设置PRESDIV、PROPSEG、PSEG1、PSEG2和RJW，但当CTRL2.BTE=1或者FD模式下CTRL1中的配置失效，此时需要在CBT或者ENCBT中进行波特率配置，寄存器中的值实际计算时需要加1。<br />
其中，同步跳转宽度设置规则为≤min（Phase_Seg1，4），如果太大会使采样点提前，进而影响通信时序；<br />
7. 通过IMASKn开启对应邮箱的中断。<br />
ps：如果使用了FD、FIFO、Enhance FIFO或DMA等功能时，还需要单独进行相应设置。</p>
<h2>RAM设置</h2>
<p dir="auto">邮箱在RAM中的布局如下：<br />
RAM[offset + 0] = CS 字（控制/状态）<br />
RAM[offset + 1] = ID 字（消息ID）<br />
RAM[offset + 2 .. offset+1+(dataLen/4)] = 数据字<br />
发送数据时，一般步骤如下：<br />
- 先清 IFLAG1：base-&gt;IFLAG1 = 1UL &lt;&lt; mb_idx<br />
- 写数据字：32位大端对齐写入<br />
- 写 ID 字（注意标准/扩展 ID 格式差异）<br />
- 最后写 CS 字（写入 CS 即触发发送）<br />
数据字大端格式：<br />
数据排列: data[0]→[3] 合并为 word[31:0]</p>
<pre><code>uint32_t word = (data[i] &lt;&lt; 24) | (data[i+1] &lt;&lt; 16) | (data[i+2] &lt;&lt;  8 )  |  data[i+3];
[链接文本]([链接地址]([链接地址]([链接地址]([链接地址]([链接地址]([链接地址](链接地址)))))))base-&gt;RAM[offset + 2 + i/4] = word;
</code></pre>
<p dir="auto">CS 构造（按位组合）：<br />
bit[19:16] = DLC (4-bit编码)<br />
bit[21]    = IDE  (1=扩展帧)<br />
bit[22]    = SRR  (扩展帧必须置1)<br />
bit[31]    = EDL  (1=CAN FD帧)<br />
bit[30]    = BRS  (1=使能比特率切换)<br />
bit[27:24] = CODE (0xC=TX数据帧)<br />
注意：发送 CS 字必须最后写入，因为写入 CS 字即触发 FlexCAN 发送操作，数据字和 ID 字必须先准备好。</p>
<h3>发送配置</h3>
<p dir="auto">上面有提到，一个MB占用4个RAM寄存器空间（Normal 模式下），那么以MB1为例，必须进行的步骤如下：<br />
1. 设置ID。<br />
MB1所在区域为RAM[4]~RAM[7]，因此ID需要在RAM[5]中进行设置，若ID为0x32，那么配置如下：</p>
<pre><code>base-&gt;RAM[5] &amp;= ~CAN_ID_STD_MASK;
base-&gt;RAM[5] |= (frame.msgId &lt;&lt; CAN_ID_STD_SHIFT) &amp; CAN_ID_STD_MASK;//STD ID
base-&gt;RAM[5] |= frame.msgId &amp; (CAN_ID_STD_MASK | CAN_ID_EXT_MASK);//EXT ID
</code></pre>
<ol start="2">
<li>写入数据。<br />
一个单位RAM寄存器为32bit，最多可以存储4byte数据，因此MB1的RAM[6]、RAM[7]都是用来存储数据的，配置如下：</li>
</ol>
<pre><code>base-&gt;RAM[6] = (((uint32_t) frame.data[0]) &lt;&lt; 24) | (((uint32_t) frame.data[1]) &lt;&lt; 16) | (((uint32_t) frame.data[2]) &lt;&lt; 8 ) | frame.data[3]; 
base-&gt;RAM[7] = (((uint32_t) frame.data[4]) &lt;&lt; 24) | (((uint32_t) frame.data[5]) &lt;&lt; 16) | (((uint32_t) frame.data[6]) &lt;&lt; 8）| frame.data[7];
</code></pre>
<ol start="3">
<li>设置邮箱状态/激活邮箱<br />
若数据长度为8，那么配置如下：</li>
</ol>
<pre><code>base-&gt;RAM[0] &amp;= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
base-&gt;RAM[0] |= ((uint32_t)8 &lt;&lt; CAN_CS_DLC_SHIFT) &amp; CAN_CS_DLC_MASK; 
base-&gt;RAM[0] |= (FLEXCAN_TX_DATA &lt;&lt; CAN_CS_CODE_SHIFT) &amp; CAN_CS_CODE_MASK;
</code></pre>
<h3>接收配置</h3>
<ol>
<li>清除待处理标志</li>
</ol>
<pre><code>base-&gt;IFLAG1 = 1UL &lt;&lt; mb_idx;
</code></pre>
<ol start="2">
<li>清除仲裁字段</li>
</ol>
<pre><code>base-&gt;RAM[offset+0] = 0;                     
base-&gt;RAM[offset+1] = 0;
</code></pre>
<ol start="3">
<li>写入 ID (标准/扩展格式同发送)<br />
CODE = 0x4 (EMPTY) → 激活接收</li>
</ol>
<pre><code>base-&gt;RAM[offset+0] = cs;       // 写入 CS 激活 MB
base-&gt;IMASK1 |= 1UL &lt;&lt; mb_idx;  // 使能 MB 中断
</code></pre>
<p dir="auto">注意：必须先清除 CS 和 ID 寄存器再写新值，否则可能残留旧数据导致意外匹配。标准 ID 接收时 CS 中的 IDE 位必须为 0。</p>
<h3>接收帧配置步骤</h3>
<ol>
<li>先轮询 IFLAG1，不要直接读 MB的CS</li>
</ol>
<pre><code>if (!(base-&gt;IFLAG1 &amp; (1UL &lt;&lt; mb_idx))) return ERROR;
</code></pre>
<p dir="auto">注意：如果 MB 处于 EMPTY 状态时去读 CS，RX MB 会被锁定（Lock），直到收到新帧或复位。必须先检查 IFLAG1 再读 MB。<br />
2. 检查 CODE：必须是 FULL(0x2) 或 OVERRUN(0x6) 才表示有数据<br />
3. 读取 DLC 并解码为实际数据长度（CAN FD 需要查表）：<br />
DLC 0-8  →  8/12/16/20/24/32/48/64 字节<br />
DLC	  实际数据长度<br />
0-8	  0-8<br />
9	  12<br />
10	  16<br />
11	  20<br />
12	  24<br />
13	  32<br />
14	  48<br />
15	  64<br />
4. 读取数据字并拆分为大端字节序（与发送对应）<br />
5. 读取 TIMER 解锁：</p>
<pre><code>(void)base-&gt;TIMER;  // 读取 TIMER 寄存器解锁 MB
</code></pre>
<p dir="auto">注意：FlexCAN 硬件要求在读取接收到的 MB 后，必须读取 TIMER 寄存器来解锁，否则 MB 会保持锁定状态无法接收新帧。<br />
6. 清除 IFLAG1：</p>
<pre><code>base-&gt;IFLAG1 = 1UL &lt;&lt; mb_idx
</code></pre>
<ol start="7">
<li>重新将CODE设为EMPTY（0x04），保留 IDE 位：</li>
</ol>
<pre><code>rearm_cs = (0x4 &lt;&lt; 24) | (cs &amp; CAN_CS_IDE_MASK);
base-&gt;RAM[offset+0] = rearm_cs;
</code></pre>
<h3>常见问题</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>问题</th>
<th>现象</th>
<th>解决方法</th>
</tr>
</thead>
<tbody>
<tr>
<td>未等 FRZACK 即配置</td>
<td>配置无效</td>
<td>每次修改 MCR 后等待 FRZACK 同步</td>
</tr>
<tr>
<td>未先设 MAXMB 就退出冻结</td>
<td>MB 数量错误</td>
<td>在清除 FRZ/HALT 前设置 MAXMB</td>
</tr>
<tr>
<td>发送时先写 CS 再写数据</td>
<td>发送空数据/错误数据</td>
<td>按清IFLAG→数据→ID→CS 顺序</td>
</tr>
<tr>
<td>接收时直接读 CS 不查 IFLAG</td>
<td>MB 锁定，无法收新帧</td>
<td>先轮询 IFLAG，确认有数据再读</td>
</tr>
<tr>
<td>接收后未读 TIMER</td>
<td>MB 锁定</td>
<td>读取数据后立即 (void)base-&gt;TIMER</td>
</tr>
<tr>
<td>DLC 未解码为实际长度(CAN FD)</td>
<td>数据截断/读越界</td>
<td>使用 DLC→Length 查表转换</td>
</tr>
<tr>
<td>数据字节序不对</td>
<td>数据错乱</td>
<td>大端格式：[0]:MSB, [3]:LSB</td>
</tr>
<tr>
<td>标准 ID 未左移 18 位</td>
<td>ID 不匹配</td>
<td>RAM[ID] = msgId &lt;&lt; 18</td>
</tr>
<tr>
<td>FDCTRL[MBDSR] 未全部设置</td>
<td>部分 MB 负载异常</td>
<td>MBDSR0~3 均需配置为相同值</td>
</tr>
<tr>
<td>SRXDIS=0 导致自收自发</td>
<td>总线出现自己发的帧</td>
<td>非回环模式建议置 SRXDIS=1</td>
</tr>
</tbody>
</table>
<p dir="auto"><a href="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/1298/7af01782-2f04-4ad1-af88-a76fa48f46f2.zip" rel="nofollow ugc">Flexcan_Demo_Register.zip</a></p>
]]></description><link>https://forum.ytmicro.com/topic/2109/can寄存器操作</link><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Jul 2026 18:32:44 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/2109.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 10 Jul 2026 07:04:26 GMT</pubDate><ttl>60</ttl></channel></rss>