<?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/categories/%E7%94%B5%E6%8E%A7%E7%BB%84%E7%9F%A5%E8%AF%86/</link>
        <description>Recent content in 电控组知识 on RinChord的小本本</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Tue, 13 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.rinchord.top/categories/%E7%94%B5%E6%8E%A7%E7%BB%84%E7%9F%A5%E8%AF%86/index.xml" rel="self" type="application/rss+xml" /><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>
        <item>
        <title>简单了解PID</title>
        <link>https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3pid/</link>
        <pubDate>Sun, 10 Nov 2024 00:00:00 +0000</pubDate>
        
        <guid>https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3pid/</guid>
        <description>


  &lt;blockquote&gt;
    &lt;p&gt;参考内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.bilibili.com/video/BV1G9zdYQEr3&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.bilibili.com/video/BV1G9zdYQEr3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://zh.wikipedia.org/wiki/%e7%a9%8d%e5%88%86%e9%a3%bd%e5%92%8c&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;积分饱和 - 维基百科，自由的百科全书&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  &lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;PID基本理论公式&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
$$
out(t)=K_p*error(t)+K_i*\int^{t}_{0}error(t)dt+K_d*\frac{derror(t)}{dt}
$$&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%A3pid/Y6dedMEd0zuAkJbBigXtDrCY.png&#34;
	width=&#34;1290&#34;
	height=&#34;447&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;image-20251010195316893&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;288&#34;
		data-flex-basis=&#34;692px&#34;
	
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;比例项&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;比例项的输出仅取决于当前时刻的误差，$K_p$越大，第一部分的值越大，系统响应越快，==稳态误差==越小，但==超调==也会增加。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;稳态误差&lt;/strong&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，则$K_p$比例也是0，给被控对象的输入就是0，此时，被控对象可能会自发地向一个方向偏移而产生误差&lt;/p&gt;
&lt;p&gt;这个误差会让$K_p$开始负反馈调控，当调控输出力度与自发偏移力度一致时，系统将达到稳态 (如：电机的输出与电机的摩擦达到一致)。&lt;/p&gt;



  &lt;blockquote class=&#34;alert alert-tip&#34;&gt;
    &lt;p class=&#34;alert-heading&#34;&gt;
      💡
      
        Tip
      
    &lt;/p&gt;
    &lt;p&gt;思考： 系统认为当前的输出可以让被控设备达到稳态，但实际上被控设备存在一些未知的阻力。&lt;/p&gt;
&lt;p&gt;系统想要设备更靠近目标状态一些，但问题是设备上有阻力，当前误差所带来的驱动力太小的话是没办法克服阻力的。&lt;/p&gt;
&lt;p&gt;所以，当驱动力=阻力时，设备就没办法继续向目标状态靠近，而是进入稳态了  在这种情况下的K_p提供了对抗摩擦力的输出&lt;/p&gt;
  &lt;/blockquote&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;给系统输入0，系统自发偏移的方向就是稳态误差的方向。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3pid/WMWg2ngpJclG8QNZOczFKRs-.png&#34;
	width=&#34;889&#34;
	height=&#34;580&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;image-20251010202023517&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;153&#34;
		data-flex-basis=&#34;367px&#34;
	
&gt;&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;p&gt;积分的本质是&lt;code&gt;累加&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$K_i$会不断累加过去的误差（包括正误差和负误差),将之作为当前的输出。&lt;/p&gt;
&lt;p&gt;这意味着$K_i$的输出是具有滞后性的，在系统输入目标改变一段时间后，输出才会到达目标值。（图一）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;$K_i$会消除稳态误差的原因是：如果系统无法达到目标值，它所提供的输出会越来越大，&lt;strong&gt;直到&lt;/strong&gt;系统达到目标值为止。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在$K_p$和$K_i$联合运作时，先是$K_p$快速地提高输出，然后在稳态误差的作用下停止输出，此后$K_i$再依靠不断累计的输出将被控设备运动到位。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3pid/SnCMU5iqa1h0L8iPRP2htmkF.png&#34;
	width=&#34;1271&#34;
	height=&#34;512&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;image-20251010203557427&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;248&#34;
		data-flex-basis=&#34;595px&#34;
	
&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;微分项&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;微分的本质是求误差变化的斜率，而斜率和当前时刻附近误差变化的趋势有关系&lt;/li&gt;
&lt;li&gt;误差变化的越大，误差变化率的斜率就越大根据斜率来输出阻力，就可以阻碍误差的急剧变化。
&lt;ul&gt;
&lt;li&gt;当误差急剧升高时，对误差求导得到的斜率就会变大&lt;/li&gt;
&lt;li&gt;当误差急剧降低时，对误差求导得到的斜率就会变小&lt;/li&gt;
&lt;li&gt;直接使用这个斜率作为参数再乘以一个常量就可以给系统引入阻尼了。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如果$K_d$给的过大，阻尼就会过大，此时系统会表现得“卡卡的”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.rinchord.top/p/%E7%AE%80%E5%8D%95%E4%BA%86%E8%A7%A3pid/5oFtDv1jHaDqZh4MuBJhYurV.png&#34;
	width=&#34;574&#34;
	height=&#34;249&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;image-20251010205004615&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;230&#34;
		data-flex-basis=&#34;553px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;倒立摆电机编码器在不同$K_d$时的输出值拟合曲线。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;将PID离散化&lt;/strong&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%A3pid/8TfW2X9exXHWmlapGSKkBoNw.png&#34;
	width=&#34;266&#34;
	height=&#34;216&#34;
	
	loading=&#34;lazy&#34;
	
		alt=&#34;image-20251010232522266&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;123&#34;
		data-flex-basis=&#34;295px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;原有的pid公式是一个线性过程，适用于模拟电路。但是在数字电路中并不适用，所以需要进行离散化&lt;/p&gt;
&lt;p&gt;原有公式$out(t)=K_p&lt;em&gt;error(t)+K_i&lt;/em&gt;\int^{t}_{0}error(t)dt+K_d*\frac{derror(t)}{dt}$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;通过面积法，可以把$K_i$转换为$K_i*T\sum^t_{j=0}error(j)$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;其中$T$为单个步长，即“所有矩形面积相加之和”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过中值定理，可以把$K_d$转换为$K_d*\frac{error(k)-error(k-1)}{T}$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;公式中分数的含义即对应“矩形的中值”。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最终得到公式&lt;br&gt;
&lt;/p&gt;
$$
out(t)=K_p*error(k)+K_i*T\sum^t_{j=0}error(j)+K_d*\frac{error(k)-error(k-1)}{T}
$$&lt;p&gt;&lt;br&gt;
当然我们也可以把T并入到$K_i$和$K_d$中，也就是&lt;br&gt;
&lt;/p&gt;
$$
out(t)=K_p*error(k)+K_i*\sum^t_{j=0}error(j)+K_d*error(k)-error(k-1)
$$&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;全量式PID和增量式PID&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;全量式PID&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;即传统式PID&lt;/li&gt;
&lt;li&gt;优势
&lt;ul&gt;
&lt;li&gt;可以直接输出给目标设备&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;增量式PID&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;即输出为上一次的增量(或负增量)&lt;/li&gt;
&lt;li&gt;优势
&lt;ul&gt;
&lt;li&gt;计算方便：只需要得到&lt;code&gt;out(k)&lt;/code&gt; &lt;code&gt;out(k-1)&lt;/code&gt; &lt;code&gt;out(k-2)&lt;/code&gt;这三个值就可以计算增量了&lt;/li&gt;
&lt;li&gt;限幅更方便（防止积分饱和&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;与过摆）&lt;/li&gt;
&lt;li&gt;因为会持续存储控制状态，在手动切换到自动的过渡中会更平缓(全量式pid需要一定的时间来进行适应)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;计算公式：$\Delta out(k)=out(k)-out(k-1)$&lt;/li&gt;
&lt;/ul&gt;
$$
\Delta out(k)=[K_p*(error(k)-error(k-1))]+[K_i*error(k)]+[K_d*(error(k)-2error(k-1)+error(k-2)])
$$&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;更高级的PID&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;积分限幅&lt;/p&gt;
&lt;p&gt;积分分离(线性&amp;amp;非线性)&lt;/p&gt;
&lt;p&gt;【待补充】&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;积分饱和是指&lt;a class=&#34;link&#34; href=&#34;https://zh.wikipedia.org/wiki/PID%e6%8e%a7%e5%88%b6%e5%99%a8&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;PID控制器&lt;/a&gt;或是其他有&lt;a class=&#34;link&#34; href=&#34;https://zh.wikipedia.org/wiki/%e7%a9%8d%e5%88%86%e5%99%a8&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;积分器&lt;/a&gt;的控制器中的现象，是指误差有大幅变化（例如大幅增加），积分器因为误差的大幅增加有很大的累计量，因此造成&lt;a class=&#34;link&#34; href=&#34;https://zh.wikipedia.org/wiki/%e8%bf%87%e5%86%b2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;过冲&lt;/a&gt;，而且当误差变为负时，其过冲仍维持一段时间之后才恢复正常的情形&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
        </item>
        
    </channel>
</rss>
