<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>协议 on RinChord的小本本</title>
        <link>https://blog.rinchord.top/tags/%E5%8D%8F%E8%AE%AE/</link>
        <description>Recent content in 协议 on RinChord的小本本</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Sat, 14 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.rinchord.top/tags/%E5%8D%8F%E8%AE%AE/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>I2S协议理解</title>
        <link>https://blog.rinchord.top/p/i2s%E5%8D%8F%E8%AE%AE%E7%90%86%E8%A7%A3/</link>
        <pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.rinchord.top/p/i2s%E5%8D%8F%E8%AE%AE%E7%90%86%E8%A7%A3/</guid>
        <description>


  &lt;blockquote&gt;
    &lt;p&gt;参考资料：&lt;br&gt;
&lt;a class=&#34;link&#34; href=&#34;https://docs.espressif.com/projects/esp-idf/zh_CN/v5.4/esp32/api-reference/peripherals/i2s.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;文档 (中文)&lt;/a&gt;&lt;/p&gt;

  &lt;/blockquote&gt;

&lt;h1 id=&#34;i2s协议&#34;&gt;I2S协议
&lt;/h1&gt;


  &lt;blockquote&gt;
    &lt;p&gt;I2S（Inter-IC Sound，集成电路内置音频总线）是一种同步串行通信协议&lt;br&gt;
通常用于在两个数字音频设备之间传输音频数RGBL&lt;/p&gt;

  &lt;/blockquote&gt;

&lt;h2 id=&#34;简介&#34;&gt;简介
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;I2S各模式下所需管脚数量（ESP32）&lt;/strong&gt;&lt;br&gt;
参考来源：https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-reference/peripherals/i2s.html&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;标准模式&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCLK&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;主时钟线。该信号线可选，具体取决于从机，主要用于向 I2S 从机提供参考时钟。&lt;/li&gt;
&lt;li&gt;通常为256×Fs或512×Fs，用于内部PLL锁相&lt;/li&gt;
&lt;li&gt;如果从机设备能通过 BCLK（位时钟）自适应时钟，或自带高精度晶振，或低精度应用，则无需主机提供 MCLK&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BCLK/SCLK&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;位时钟线，用于数据线的位时钟（BCLK - Bit Clock）。也称为串行时钟线（Serial Clock）。&lt;/li&gt;
&lt;li&gt;每次脉冲传输一位数据，决定数据速率&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LRCK / WS&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;字（声道）选择线。通常用于识别声道（除 PDM 模式外）。&lt;/li&gt;
&lt;li&gt;当 LRCK 为“0”时，传输左声道数据；当为“1”时，传输右声道数据。&lt;/li&gt;
&lt;li&gt;其频率等于音频的采样率（如 44.1kHz），用于标识一个完整数据帧的开始&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DIN&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;串行数据&lt;strong&gt;输入&lt;/strong&gt;线。如果 DIN 和 DOUT 被配置到相同的 GPIO，数据将在内部回环。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DOUT&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;串行数据&lt;strong&gt;输出&lt;/strong&gt;线。如果 DIN 和 DOUT 被配置到相同的 GPIO，数据将在内部回环。&lt;/li&gt;
&lt;li&gt;传输音频采样值&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PDM 通信模式&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLK&lt;/strong&gt;：PDM 时钟线。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DIN/DOUT&lt;/strong&gt;：串行数据输入/输出线。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每个 I2S 控制器都具备以下功能，可由 I2S 驱动进行配置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可用作系统主机或从机&lt;/li&gt;
&lt;li&gt;可用作发射器或接收器&lt;/li&gt;
&lt;li&gt;DMA 控制器支持流数据采样，CPU 无需单独复制每个采样数据&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;术语解释&#34;&gt;术语解释
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;采样率&lt;/strong&gt;：单声道每秒采样数据数量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SCLK&lt;/strong&gt;：源时钟频率，即时钟源的频率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCLK&lt;/strong&gt;：主时钟频率，BCLK 由其产生。MCLK 信号通常作为参考时钟，用于同步 I2S 主机和从机之间的 BCLK 和 WS。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BCLK&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;位时钟频率，一个 BCLK 时钟周期代表数据管脚上的一个数据位。&lt;/li&gt;
&lt;li&gt;通过 i2s_std_slot_config_t::slot_bit_width 配置的通道位宽即为一个声道中的 BCLK 时钟周期数量，&lt;/li&gt;
&lt;li&gt;因此一个声道中可以有 8/16/24/32 个 BCLK 时钟周期。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LRCK / WS&lt;/strong&gt;：左/右时钟或字选择时钟。在非 PDM 模式下，其频率等于采样率。&lt;/li&gt;
&lt;/ul&gt;



  &lt;blockquote class=&#34;alert alert-tip&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      💡
      
        通常，MCLK 应该同时是 采样率 和 BCLK 的倍数。
      
    &lt;/p&gt;
    
  &lt;/blockquote&gt;

&lt;h2 id=&#34;通信模式&#34;&gt;通信模式
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;标准模式&lt;/strong&gt;&lt;br&gt;
标准模式中有且仅有左右两个声道，驱动中将声道称为 slot。这些声道可以支持 8/16/24/32 位宽的采样数据&lt;br&gt;
声道可用的通信格式有 Philips 格式\ MSB 格式\ PCM 帧同步&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Philips 格式&lt;/strong&gt;&lt;br&gt;
数据信号与 WS 信号相比有一个位的位移。WS 信号的占空比为 50%。&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/wavedrom%20%281%29-1.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wavedrom.png&#34;
	
	
&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MSB 格式&lt;/strong&gt;&lt;br&gt;
与 Philips 格式基本相同，但其数据没有位移。&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/i2s%E5%8D%8F%E8%AE%AE%E7%90%86%E8%A7%A3/wavedrom-1.png&#34;
	width=&#34;680&#34;
	height=&#34;226&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wavedrom.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;300&#34;
		data-flex-basis=&#34;722px&#34;
	
&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PCM 帧同步&lt;/strong&gt;&lt;br&gt;
数据有一个位的位移，同时 WS 信号变成脉冲，持续一个 BCLK 周期。&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/i2s%E5%8D%8F%E8%AE%AE%E7%90%86%E8%A7%A3/wavedrom.png&#34;
	width=&#34;720&#34;
	height=&#34;226&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wavedrom.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;318&#34;
		data-flex-basis=&#34;764px&#34;
	
&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;PDM模式&lt;/strong&gt;&lt;br&gt;
PDM（Pulse-density Modulation，脉冲密度调制）通过采样的方式将模拟信号数字化为 1 位精度的数字信号。&lt;br&gt;
它以脉冲密度的方式呈现模拟信号的大小，即密度越高，对应的模拟信号值越大。&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/wavedrom%20%281%29.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;wavedrom (1).png&#34;
	
	
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;PDM转换PCM&lt;/strong&gt;&lt;br&gt;
PDM (脉冲密度调制)格式的数据通常可以经过以下几个步骤转换为 PCM (脉冲编码调制)格式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;低通滤波：用于还原模拟信号波形。一般采用 FIR 滤波器；&lt;/li&gt;
&lt;li&gt;下采样：用于将 PDM 的过采样率降低到期望的 PCM 采样率。下采样可以用简单的抽值法实现；&lt;/li&gt;
&lt;li&gt;高通滤波：用于去除信号的直流部分；&lt;/li&gt;
&lt;li&gt;放大：用于调整转换后的 PCM 数据的増益。一般由转换后的 PCM 信号乘以一个系数得到最终 PCM 信号。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



  &lt;blockquote class=&#34;alert alert-tip&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      💡
      
        &lt;br&gt;
      
    &lt;/p&gt;
    &lt;p&gt;无论原始 PDM 格式还是 PCM 格式，PDM 模式下的一个数据单元总是 16 比特的位宽。&lt;br&gt;
例如，用原始 PDM 格式发送数据，那么您数组中的数据应该像这样排列：CH0 0x1234，CH1 0x5678，CH0 0x9abc，CH1 0xdef0。RX 方向同理。&lt;/p&gt;
  &lt;/blockquote&gt;

&lt;h2 id=&#34;通道状态&#34;&gt;通道状态
&lt;/h2&gt;&lt;p&gt;I2S通道有三种状态，分别为 &lt;strong&gt;registered&lt;/strong&gt;（已注册）、 &lt;strong&gt;ready&lt;/strong&gt;（&lt;strong&gt;准备就绪&lt;/strong&gt;） 和 running（运行中），它们的关系如下图所示：&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/i2s%E5%8D%8F%E8%AE%AE%E7%90%86%E8%A7%A3/i2s_state_machine.png&#34;
	width=&#34;714&#34;
	height=&#34;530&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;i2s_state_machine.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;134&#34;
		data-flex-basis=&#34;323px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;// TODO&lt;/p&gt;
&lt;h2 id=&#34;example&#34;&gt;EXAMPLE
&lt;/h2&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-reference/peripherals/i2s.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.espressif.com/projects/esp-idf/zh_CN/stable/esp32/api-reference/peripherals/i2s.html&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>简单了解CAN</title>
        <link>https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/</link>
        <pubDate>Tue, 13 Jan 2026 00:00:00 +0000</pubDate>
        
        <guid>https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/</guid>
        <description>


  &lt;blockquote&gt;
    &lt;p&gt;参考内容&lt;br&gt;
&lt;a class=&#34;link&#34; href=&#34;https://www.analog.com/cn/glossary/can.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.analog.com/cn/glossary/can.html&lt;/a&gt;&lt;br&gt;
&lt;a class=&#34;link&#34; href=&#34;https://www.analog.com/cn/technical-articles/understanding-can-transceiver-how-validate-multinode-can-system-performance.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.analog.com/cn/technical-articles/understanding-can-transceiver-how-validate-multinode-can-system-performance.html&lt;/a&gt;&lt;br&gt;
&lt;a class=&#34;link&#34; href=&#34;https://blog.steven53.top/p/stm32-0x0b/#%E4%BD%8D%E6%97%B6%E5%BA%8F&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://blog.steven53.top/p/stm32-0x0b/#%E4%BD%8D%E6%97%B6%E5%BA%8F&lt;/a&gt;&lt;/p&gt;

  &lt;/blockquote&gt;

&lt;h1 id=&#34;can&#34;&gt;CAN
&lt;/h1&gt;&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/7ee4eb34f0c14dd57179d60572ec867d.png&#34;
	width=&#34;817&#34;
	height=&#34;282&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;7ee4eb34f0c14dd57179d60572ec867d.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;289&#34;
		data-flex-basis=&#34;695px&#34;
	
&gt;&lt;br&gt;
&lt;strong&gt;介绍&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;两根通信线: CANH 和 CANL, 使用差分信号进行通信，抗干扰，无需时钟线&lt;/li&gt;
&lt;li&gt;总线上挂载多设备，异步通信，冲突时通过报文ID进行仲裁&lt;/li&gt;
&lt;li&gt;在2.0协议帧下，可以传输 0 ~ 8 Byte&lt;/li&gt;
&lt;li&gt;广播式通信、请求-响应式通信&lt;/li&gt;
&lt;li&gt;应答机制、CRC校验机制&lt;/li&gt;
&lt;li&gt;can2.0 最高速率 1Mbit/s&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;名词解释：&lt;br&gt;
差分线:&lt;br&gt;
&lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Differential_signalling&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://en.wikipedia.org/wiki/Differential_signalling&lt;/a&gt;&lt;br&gt;
两根等长且平行的线，它们同一时刻的电压差描述了 1 bit 的数字信号&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;抗干扰能力强。干扰噪声一般会等值、同时的被加载到两根信号线上，而其差值为0，即，噪声对信号的逻辑意义不产生影响。&lt;/li&gt;
&lt;li&gt;有效抑制电磁干扰（EMI）。由于两根线靠得很近且信号幅值相等，这两根线与地线之间的耦合电磁场的幅值也相等，同时他们的信号极性相反，其电磁场将相互抵消。因此对外界的电磁干扰也小。&lt;/li&gt;
&lt;li&gt;时序定位准确。差分信号的接收端是两根线上的信号幅值之差发生正负跳变的点，作为判断逻辑0/1跳变的点的。而普通单端信号以阈值电压作为信号逻辑0/1的跳变点，受阈值电压与信号幅值电压之比的影响较大，不适合低幅度的信号。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;协议硬件要求&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;总线起点                         总线终点
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAN_H ──┬───────────────────────┬──
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        120Ω                    120Ω
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CAN_L ──┴───────────────────────┴──
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;使用特性阻抗为 120Ω 双绞线分别连接所有设备的 CANH 和 CANL&lt;/li&gt;
&lt;li&gt;在总线最远的两个点放置两个 120R 阻抗匹配电容，
&lt;ul&gt;
&lt;li&gt;实际测得总线电阻约 60R&lt;/li&gt;
&lt;li&gt;中间其他节点不装总线电阻&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;协议细节&#34;&gt;协议细节
&lt;/h2&gt;&lt;h3 id=&#34;基本bit&#34;&gt;&lt;strong&gt;基本bit&lt;/strong&gt;
&lt;/h3&gt;&lt;p&gt;如果 CANH-CANL 电压大于 1.5V，CAN接收器将其视为逻辑 0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;这意味着收发器主动产生了两根总线上的压差&lt;br&gt;
如果 CANH-CANL 电压小于 200mV, CAN接收器将其视为逻辑 1&lt;/li&gt;
&lt;li&gt;这意味着收发器释放了总线，让总线处于默认电压&lt;br&gt;
接收器根据接收到的逻辑在 TXD 和 RXD 上回送数据&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;节点A发送：1  1  0  1&lt;br&gt;
节点B发送：1  0  0  1&lt;br&gt;
总线结果 ：1  0  0  1&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以理解为一种线与操作，只要有某个收发器在总线上产生了0，整个总线就体现为0&lt;/li&gt;
&lt;li&gt;如果某设备试图发送1，但是读到了0，这意味着总线上有其他设备正在发送报文，将停止发送&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;数据帧结构&#34;&gt;&lt;strong&gt;数据帧结构&lt;/strong&gt;
&lt;/h3&gt;&lt;p&gt;can有两种数据帧，一种是基本帧，一种是扩展帧，此外还有过载帧和错误帧&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基本帧&lt;/strong&gt;&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/can1.png&#34;
	width=&#34;826&#34;
	height=&#34;185&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;drawio&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;446&#34;
		data-flex-basis=&#34;1071px&#34;
	
&gt;&lt;br&gt;
&lt;strong&gt;SOF&lt;/strong&gt;（1位）: 帧起始位, 固定为显性 0。&lt;br&gt;
&lt;strong&gt;CAN ID&lt;/strong&gt;（11位）: 报文标识符，发送时高位在前, 数值越小，仲裁优先级越高。&lt;br&gt;
&lt;strong&gt;RTR&lt;/strong&gt;（1位）: 0：数据帧。1：远程帧，请求其他节点发送数据。&lt;br&gt;
&lt;strong&gt;IDE&lt;/strong&gt;（1位）: 0：11位标准帧。1：表示采用扩展帧结构。&lt;br&gt;
&lt;strong&gt;r0&lt;/strong&gt;（1位）:保留位，经典CAN标准帧中通常为 0。&lt;br&gt;
&lt;strong&gt;DLC&lt;/strong&gt;（4位）: 表示数据长度。经典CAN数据长度为0～8字节。&lt;br&gt;
&lt;strong&gt;Data&lt;/strong&gt;（0～64位）: 实际负载数据，即0～8字节。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CRC&lt;/strong&gt;（15位）: 用于检测报文在传输中是否出错。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CRC界定符&lt;/strong&gt;（1位）: 固定为1。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;ACK&lt;/strong&gt;（1位）: 发送节点发送隐性 1。正确接收报文的节点将其覆盖为显性 0，表示确认收到。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACK界定符&lt;/strong&gt;（1位）: 固定为1。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;EOF&lt;/strong&gt;（7位）:帧结束，7*1。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IFS&lt;/strong&gt; 帧间隔&lt;br&gt;
正常情况下，IFS至少包含连续 3*1。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3位结束后：
&lt;ul&gt;
&lt;li&gt;没有节点发送：总线继续保持隐性，称为总线空闲。&lt;/li&gt;
&lt;li&gt;有节点发送：发送显性SOF，开始下一帧。&lt;/li&gt;
&lt;li&gt;多个节点同时发送：进入仲裁。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;扩展帧&lt;/strong&gt;&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/efccac50fe0579b30c1492e02aba612d.png&#34;
	width=&#34;838&#34;
	height=&#34;112&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;efccac50fe0579b30c1492e02aba612d.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;748&#34;
		data-flex-basis=&#34;1795px&#34;
	
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;扩展帧与基本帧结构基本一样，只有少量区别：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SRR位固定为1&lt;/li&gt;
&lt;li&gt;IDE为1，代表扩展帧&lt;/li&gt;
&lt;li&gt;18位扩展ID&lt;/li&gt;
&lt;li&gt;RTR：0：扩展数据帧。1：扩展远程帧。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因为SRR固定为1，这导致前11位ID相同的基本帧和扩展帧中，基本帧会赢得仲裁。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;错误帧&lt;/strong&gt;&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/b34334629c975b2c6c0b50eca3dc3089.png&#34;
	width=&#34;354&#34;
	height=&#34;236&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;b34334629c975b2c6c0b50eca3dc3089.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;150&#34;
		data-flex-basis=&#34;360px&#34;
	
&gt;&lt;br&gt;
CAN采取 bit stuffing 模式，即：总线上不允许出现连续6个相同位&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果出现6个相同位，将在第六位前插入一个相反位。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;主动/被动错误标志不采用bit stuffing, 所以其他can设备将轻易地发现此错误&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果其他设备刚好在某设备发送完错误标志后开始连续发送，错误标志段可能最长为12bit&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;错误状态转换&lt;/strong&gt; (Error State Transition)： CAN控制器硬件内部有三个状态，由两个计数器：发送错误计数器 (TEC, Transmit Error Counter) 和 接收错误计数器 (REC, Receive Error Counter) 决定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主动错误状态 (Error Active)：正常状态，发错误帧用 6个0。&lt;/li&gt;
&lt;li&gt;被动错误状态 (Error Passive)：错误较多，发错误帧用 6个1。&lt;/li&gt;
&lt;li&gt;总线关闭状态 (Bus Off)：错误过多，硬件直接断开与总线的物理连接，不再发送任何数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&#34;仲裁&#34;&gt;&lt;strong&gt;仲裁&lt;/strong&gt;
&lt;/h3&gt;&lt;p&gt;如果某个节点正在发信，其他节点在该时刻不可以发信&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;仲裁行为只会出现在 两个节点恰好同时开始发信 的前提下&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;前面提到：总线上如果有多个设备一起发信，只要有一个设备发 0 ，总线电平都是 0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对于该节点而言，只会有三种情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;总线为0，自己发1&lt;/li&gt;
&lt;li&gt;总线为0，自己发0
&lt;ul&gt;
&lt;li&gt;总线上可能会有其他试图发 1 的设备，但是被当前设备覆盖成 0 了&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;总线为1，自己发1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;节点会一边发一边读总线，在第二种情况和第三种情况下，发的东西和读到的东西是一样的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;此时，仲裁通过&lt;/li&gt;
&lt;li&gt;如果节点没有通过仲裁，因为can协议帧的头就是 canID, 这意味着赢了它的那个节点ID一定比它大。
&lt;ul&gt;
&lt;li&gt;根据协议，当前节点需要停止发送。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;综上所述，can仲裁并不需要什么额外步骤，接收方可以持续监听，这就很高效。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;



  &lt;blockquote&gt;
    &lt;p&gt;举例：两节点ID分别为 9(1001) 和 10(1010)&lt;br&gt;
假设两节点同时发送数据。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一个时间段，两者同步发送&lt;code&gt;1&lt;/code&gt;，总线为&lt;code&gt;1&lt;/code&gt;，均继续发送。&lt;/li&gt;
&lt;li&gt;第二个时间段:&lt;/li&gt;
&lt;li&gt;两者同步发送&lt;code&gt;0&lt;/code&gt;，总线为&lt;code&gt;0&lt;/code&gt;，均继续发送。&lt;/li&gt;
&lt;li&gt;9发送&lt;code&gt;0&lt;/code&gt;，10发送&lt;code&gt;1&lt;/code&gt;，总线状态&lt;code&gt;0&lt;/code&gt;: 9继续发送，10看到总线状态与自己发送的不一致，于是中断之后所有发送。仲裁完成。9之后继续正常发送&lt;/li&gt;
&lt;/ul&gt;

  &lt;/blockquote&gt;

&lt;h2 id=&#34;时序同步&#34;&gt;时序同步
&lt;/h2&gt;&lt;p&gt;can是没有时钟线的，但是一条总线上的所有节点必须要保证时钟同步才能确保信息的正常收发&lt;br&gt;
晶振也是不准的，我们需要一套更有效的校准手段&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/36c2ddf61f570fbabd39c9bbab2cce7b.png&#34;
	width=&#34;1024&#34;
	height=&#34;345&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;36c2ddf61f570fbabd39c9bbab2cce7b.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;296&#34;
		data-flex-basis=&#34;712px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;我们把每Bit的时间进行进一步细分，使用Tq单位描述其&lt;/p&gt;
$$\Large T_{\text{bit}} = T_{SS} + T_{PTS} + T_{PBS1} + T_{PBS2}$$&lt;p&gt;名词解释：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$T_{\text{bit}}$：位时间 (Bit Time)。传送1个比特的总时间。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$T_{SS}$：同步段 (Synchronization Segment)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;取值：固定为 $1 \times T_q$。&lt;/li&gt;
&lt;li&gt;边沿跳变应该发生在这一段时间里&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$T_{PTS}$：传播时间段 (Propagation Time Segment)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;取值：1~8$T_q$&lt;/li&gt;
&lt;li&gt;用于补偿信号在物理导线上传播的物理延迟。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$T_{PBS1}$：相位缓冲段1 (Phase Buffer Segment 1)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;取值：1~8$T_q$&lt;/li&gt;
&lt;li&gt;用来做同步调整的“缓冲区1”，可以被拉长。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$T_{PBS2}$：相位缓冲段2 (Phase Buffer Segment 2)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;取值：1~8$T_q$&lt;/li&gt;
&lt;li&gt;用来做同步调整的“缓冲区2”，可以被缩短。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;执行流程&#34;&gt;&lt;strong&gt;执行流程&lt;/strong&gt;
&lt;/h3&gt;&lt;p&gt;CAN通过每个电平跳变边沿来同步各节点时钟，带有自校准功能&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;硬同步&lt;/strong&gt;（帧开始时同步）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;开始发送，发送方开始计时，在SS时间段中将数据线驱动为逻辑低电平&lt;/li&gt;
&lt;li&gt;在检测到SOF (Start Of Frame)下降沿时，接收方同步开始从SS段计时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;再同步&lt;/strong&gt;（逻辑电平跳变边沿不在SS段时再同步）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;除了帧开始时的第一个下降沿，后续每个数据位都可以进行再同步&lt;/li&gt;
&lt;li&gt;如果逻辑跳变发生在SS段前或后，则对应增加PBS1或者减少PBS2&lt;/li&gt;
&lt;li&gt;SJW：最大补偿的Tq数，用于防止单次补偿过度&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/a8bb677dea0acc6e17198c5ad289f45b.png&#34;
	width=&#34;1024&#34;
	height=&#34;791&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;a8bb677dea0acc6e17198c5ad289f45b.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;129&#34;
		data-flex-basis=&#34;310px&#34;
	
&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;stm32的can外设&#34;&gt;stm32的can外设
&lt;/h2&gt;&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/d23395b9d78483003af5ca726cd1efd1.png&#34;
	width=&#34;1024&#34;
	height=&#34;560&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;d23395b9d78483003af5ca726cd1efd1.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;182&#34;
		data-flex-basis=&#34;438px&#34;
	
&gt;&lt;/p&gt;
&lt;h3 id=&#34;发送&#34;&gt;发送
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;can外设有三个发送缓存（邮箱）&lt;/li&gt;
&lt;li&gt;can外设自动在总线空闲时从三个邮箱中选择一个进行发送&lt;/li&gt;
&lt;li&gt;可以配置优先级 &lt;code&gt;TXFP&lt;/code&gt; (TX Fifo Priority)
&lt;ul&gt;
&lt;li&gt;1: 先请求先发送&lt;/li&gt;
&lt;li&gt;0: 按报文ID优先级发送&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;可以配置 &lt;code&gt;NART&lt;/code&gt; (Not Allow ReTransmit)=1 禁止发送失败后自动重传&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;状态转移图：&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/9cd3a17560b7a0629796f5af3183e23e.png&#34;
	width=&#34;1024&#34;
	height=&#34;682&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;9cd3a17560b7a0629796f5af3183e23e.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;150&#34;
		data-flex-basis=&#34;360px&#34;
	
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RQCP：发送请求已经完成&lt;/li&gt;
&lt;li&gt;TXOK：发送成功&lt;/li&gt;
&lt;li&gt;TME：发送邮箱空&lt;/li&gt;
&lt;li&gt;ABRQ：终止发送&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;接收&#34;&gt;接收
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;can外设有两个三级接收FIFO缓存&lt;/li&gt;
&lt;li&gt;收发控制器接收到报文，将其送入过滤器匹配&lt;/li&gt;
&lt;li&gt;如果报文符合过滤条件，则会被放入过滤器指定的一个FIFO&lt;/li&gt;
&lt;li&gt;配置RFLM (Recieve Fifo Lock Mode)：如果FIFO已满，有新的报文到达，可以
&lt;ul&gt;
&lt;li&gt;1: FIFO上锁，新到来的报文被丢弃&lt;/li&gt;
&lt;li&gt;0: FIFO未上锁，丢弃队列中末尾（最晚到达）的报文，再放入新的报文&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;状态转移图：&lt;br&gt;
&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/fbb241feeefc0acdc9c87838d904b59b.png&#34;
	width=&#34;1024&#34;
	height=&#34;870&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;fbb241feeefc0acdc9c87838d904b59b.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;117&#34;
		data-flex-basis=&#34;282px&#34;
	
&gt;&lt;/p&gt;
&lt;h3 id=&#34;过滤器&#34;&gt;过滤器
&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3can/500b5e309c2aa18b38458ad35d41f359.png&#34;
	width=&#34;1309&#34;
	height=&#34;1143&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;500b5e309c2aa18b38458ad35d41f359.png&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;114&#34;
		data-flex-basis=&#34;274px&#34;
	
&gt;&lt;br&gt;
每一个过滤器有两个32位的寄存器，和以下几个过滤器配置位&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FSCx&lt;/strong&gt;(Filter Bank Scale)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0: 每个过滤器使用4个16位寄存器，仅支持标准CAN地址长度 （将32位的寄存器拆成两个16位的使用，能更好的利用资源）&lt;/li&gt;
&lt;li&gt;1: 每个过滤器使用2个32位寄存器，支持标准和扩展CAN地址长度&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FBMx&lt;/strong&gt;(Filter Bank Mode):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0: 掩码模式 将新收到的报文ID和过滤器中的ID进行比较，但是仅比较Mask中为1的位（类似IP地址掩码）&lt;/li&gt;
&lt;li&gt;1: 列表模式 将新收到的报文ID和过滤器中的ID进行比较，一个过滤器允许两个特定的报文ID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FACT&lt;/strong&gt;(Filter ACTive): 过滤器使能开关&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FFA&lt;/strong&gt;(Filter Fifo Assignment): 通过过滤器的报文进入哪一个FIFO&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;掩码机制&lt;/strong&gt;&lt;br&gt;
配置为掩码模式时，过滤器将输入的报文ID和寄存器中的ID进行比较，但是仅比较二进制下，Mask中为1的位，其它位无论是什么都可以。&lt;br&gt;
用公式来描述，满足以下公式的数据包，可以通过过滤器 &lt;code&gt;CAN_ID &amp;amp; MASK == FILTER_ID &amp;amp; MASK&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;基于 AND 运算逻辑，我的理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mask：我们关心的位需要写1， 不关心的位需要写0&lt;/li&gt;
&lt;li&gt;Filter： 需要填写我们关心的位，其余位全部填充 0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们要接收 0x100 到 0x1FF：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最小值 0x100 = 0b0001 0000 0000&lt;/li&gt;
&lt;li&gt;最大值 0x1FF = 0b0001 1111 1111&lt;/li&gt;
&lt;li&gt;规律：前 4 位（高 4 位）必须固定为 0001，后 8 位（低 8 位）无所谓。&lt;/li&gt;
&lt;li&gt;所以：
&lt;ul&gt;
&lt;li&gt;Filter 设为：0b0001 0000 0000（即 0x100）&lt;/li&gt;
&lt;li&gt;Mask 设为：0b1111 0000 0000（即 0xF00。前 4 位是 1 表示必须匹配，后 8 位是 0 表示忽略）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
