<h1 style="text-align:center;"><a name="_Toc342394264"><span style="font-family:宋体;">第三十章</span> <span lang="EN-US">CAN</span></a><span style="font-family:宋体;">通讯实验</span></h1>
<span lang="EN-US"> </span><span style="font-family:宋体;">本章我们将向大家介绍如何使用</span><span lang="EN-US">STM32</span><span style="font-family:宋体;">自带的</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">控制器来实现两个开发板之间的</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">通讯,并将结果显示在</span><span lang="EN-US">TFTLCD</span><span style="font-family:宋体;">模块上。本章分为如下几个部分:</span>
<span lang="EN-US">30.1 CAN</span><span style="font-family:宋体;">简介</span>
<span lang="EN-US">30.2 </span><span style="font-family:宋体;">硬件设计</span>
<span lang="EN-US">30.3 </span><span style="font-family:宋体;">软件设计</span>
<span lang="EN-US">30.4 </span><span style="font-family:宋体;">下载验证</span>
<h2 style="margin:7.8pt 0cm;"><a name="_Toc342394265"><span lang="EN-US">30.1
CAN</span></a><span style="font-family:宋体;">简介</span></h2>
<span lang="EN-US">CAN </span><span style="font-family:宋体;">是</span><span lang="EN-US">Controller Area Network </span><span style="font-family:宋体;">的缩写(以下称为</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">),是</span><span lang="EN-US">ISO</span><span style="font-family:宋体;">国际标准化的串行通信协议。在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个</span><span lang="EN-US">LAN</span><span style="font-family:宋体;">,进行大量数据的高速通信”的需要,</span><span lang="EN-US">1986 </span><span style="font-family:宋体;">年德国电气商博世公司开发出面向汽车的</span><span lang="EN-US">CAN </span><span style="font-family:宋体;">通信协议。此后,</span><span lang="EN-US">CAN </span><span style="font-family:宋体;">通过</span><span lang="EN-US">ISO11898 </span><span style="font-family:宋体;">及</span><span lang="EN-US">ISO11519 </span><span style="font-family:宋体;">进行了标准化,现在在欧洲已是汽车网络的标准协议。</span> <span style="font-family:宋体;"> </span>
<span style="font-family:宋体;">现在,</span><span lang="EN-US">CAN </span><span style="font-family:宋体;">的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。现场总线是当今自动化领域技术发展的热点之一,被誉为自动化领域的计算机局域网。它的出现为分布式控制系统实现各节点之间实时、可靠的数据通信提供了强有力的技术支持。</span>
<span lang="EN-US">CAN </span><span style="font-family:宋体;">控制器根据两根线上的电位差来判断总线电平。总线电平分为显性电平和隐性电平,二者必居其一。发送方通过使总线电平发生变化,将消息发送给接收方。</span>
<span lang="EN-US">CAN</span><span style="font-family:宋体;">协议具有一下特点:</span>
<span lang="EN-US">1)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">多主控制。</span></b><span style="font-family:宋体;">在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(</span><span lang="EN-US">Identifier </span><span style="font-family:宋体;">以下称为</span><span lang="EN-US"> ID</span><span style="font-family:宋体;">)决定优先级。</span><span lang="EN-US">ID </span><span style="font-family:宋体;">并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息</span><span lang="EN-US">ID </span><span style="font-family:宋体;">的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。</span>
<span lang="EN-US">2)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">系统的若软性。</span></b><span style="font-family:宋体;">与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。</span>
<span lang="EN-US">3)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">通信速度较快,通信距离远。</span></b><span style="font-family:宋体;">最高</span><span lang="EN-US">1Mbps</span><span style="font-family:宋体;">(距离小于</span><span lang="EN-US">40M</span><span style="font-family:宋体;">),最远可达</span><span lang="EN-US">10KM</span><span style="font-family:宋体;">(速率低于</span><span lang="EN-US">5Kbps</span><span style="font-family:宋体;">)。</span>
<span lang="EN-US">4)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">具有错误检测、错误通知和错误恢复功能。</span></b><span style="font-family:宋体;">所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。</span>
<span lang="EN-US">5)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">故障封闭功能。</span></b><span lang="EN-US">CAN </span><span style="font-family:宋体;">可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。</span>
<span lang="EN-US">6)<span style="font:7pt 'Times New Roman';"> </span></span><b><span style="font-family:宋体;">连接节点多。</span></b><span lang="EN-US">CAN </span><span style="font-family:宋体;">总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。</span>
<span style="font-family:宋体;">正是因为</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">协议的这些特点,使得</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">特别适合工业过程监控设备的互连,因此,越来越受到工业界的重视,并已公认为最有前途的现场总线之一。</span>
<span lang="EN-US">CAN</span><span style="font-family:宋体;">协议经过</span><span lang="EN-US">ISO</span><span style="font-family:宋体;">标准化后有两个标准:</span><span lang="EN-US">ISO11898</span><span style="font-family:宋体;">标准和</span><span lang="EN-US">ISO11519-2</span><span style="font-family:宋体;">标准。其中</span><span lang="EN-US">ISO11898</span><span style="font-family:宋体;">是针对通信速率为</span><span lang="EN-US">125Kbps~1Mbps</span><span style="font-family:宋体;">的高速通信标准,而</span><span lang="EN-US">ISO11519-2</span><span style="font-family:宋体;">是针对通信速率为</span><span lang="EN-US">125Kbps</span><span style="font-family:宋体;">以下的低速通信标准。</span>
<span style="font-family:宋体;">本章,我们使用的是</span><span lang="EN-US">450Kbps</span><span style="font-family:宋体;">的通信速率,使用的是</span><span lang="EN-US">ISO11898</span><span style="font-family:宋体;">标准,该标准的物理层特征如图</span><span lang="EN-US">30.1.1</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"><center>
<ignore_js_op>
<img src="data/attach/1908/bxxstgr6ila4v134424ky95tvm613ie3.jpg" alt=" " title=" ">
</ignore_js_op>
</center><br><div style="text-align: center;"><span style="font-family: 宋体;">图</span><span lang="EN-US">30.1.1 ISO11898</span><span style="font-family: 宋体;">物理层特性</span>
<span lang="EN-US"> </span></div>
</span><p><span style="font-family:宋体;">从该特性可以看出,显性电平对应逻辑</span><span lang="EN-US">0</span><span style="font-family:宋体;">,</span><span lang="EN-US">CAN_H</span><span style="font-family:宋体;">和</span><span lang="EN-US">CAN_L</span><span style="font-family:宋体;">之差为</span><span lang="EN-US">2.5V</span><span style="font-family:宋体;">左右。而隐性电平对应逻辑</span><span lang="EN-US">1</span><span style="font-family:宋体;">,</span><span lang="EN-US">CAN_H</span><span style="font-family:宋体;">和</span><span lang="EN-US">CAN_L</span><span style="font-family:宋体;">之差为</span><span lang="EN-US">0V</span><span style="font-family:宋体;">。在总线上显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。另外,在</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">总线的起止端都有一个</span><span lang="EN-US">120</span><span style="font-family:宋体;">Ω的终端电阻,来做阻抗匹配,以减少回波反射。</span>
<span lang="EN-US"> CAN</span><span style="font-family:宋体;">协议是通过以下</span><span lang="EN-US">5</span><span style="font-family:宋体;">种类型的帧进行的:</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">数据帧</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">要控帧</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">错误帧</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">过载帧</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">帧间隔</span>
<span style="font-family:宋体;">另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有</span><span lang="EN-US">11 </span><span style="font-family:宋体;">个位的标识符(</span><span lang="EN-US">ID</span><span style="font-family:宋体;">),扩展格式有</span><span lang="EN-US">29 </span><span style="font-family:宋体;">个位的</span><span lang="EN-US">ID</span><span style="font-family:宋体;">。各种帧的用途如表</span><span lang="EN-US">30.1.1</span><span style="font-family:宋体;">所示:</span>
<span style="font-family:宋体;font-size:12pt;">帧类型</span>
<span style="font-family:宋体;font-size:12pt;">帧用途</span>
<span style="font-family:宋体;font-size:12pt;">数据帧</span>
<span style="font-family:宋体;font-size:12pt;">用于发送单元向接收单元传送数据的帧</span>
<span style="font-family:宋体;font-size:12pt;">遥控帧</span>
<span style="font-family:宋体;font-size:12pt;">用于接收单元向具有相同<span lang="EN-US"> ID </span>的发送单元请求数据的帧</span>
<span style="font-family:宋体;font-size:12pt;">错误帧</span>
<span style="font-family:宋体;font-size:12pt;">用于当检测出错误时向其它单元通知错误的帧</span>
<span style="font-family:宋体;font-size:12pt;">过载帧</span>
<span style="font-family:宋体;font-size:12pt;">用于接收单元通知其尚未做好接收准备的帧</span>
<span style="font-family:宋体;font-size:12pt;">间隔帧</span>
<span style="font-family:宋体;font-size:12pt;">用于将数据帧及遥控帧与前面的帧分离开来的帧</span>
<span style="font-family:宋体;">表</span><span lang="EN-US">30.1.1 CAN</span><span style="font-family:宋体;">协议各种帧及其用途</span>
<span lang="EN-US"> </span><span style="font-family:宋体;">由于篇幅所限,我们这里仅对数据帧进行详细介绍,数据帧一般由</span><span lang="EN-US">7</span><span style="font-family:宋体;">个段构成,即:</span>
<span lang="EN-US">(1)<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">帧起始。表示数据帧开始的段。</span>
<span lang="EN-US">(2)<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">仲裁段。表示该帧优先级的段。</span>
<span lang="EN-US">(3)<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">控制段。表示数据的字节数及保留位的段。</span>
<span lang="EN-US">(4)<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">数据段。数据的内容,一帧可发送</span><span lang="EN-US">0~8</span><span style="font-family:宋体;">个字节的数据。</span>
<span lang="EN-US">(5)<span style="font:7pt 'Times New Roman';"> </span></span><span lang="EN-US">CRC</span><span style="font-family:宋体;">段。检查帧的传输错误的段。</span>
<span lang="EN-US">(6)<span style="font:7pt 'Times New Roman';"> </span></span><span lang="EN-US">ACK</span><span style="font-family:宋体;">段。表示确认正常接收的段。</span>
<span lang="EN-US">(7)<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">帧结束。表示数据帧结束的段。</span>
<span style="font-family:宋体;">数据帧的构成如图</span><span lang="EN-US">30.1.2</span><span style="font-family:宋体;">所示:</span>
<span style="font-family:宋体;"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/e5zl1fe3m93yo1ke0e92f0toj052k2fh.jpg" alt=" " title=" ">
</ignore_js_op>
</center><br><p style="text-align: center; ">
图<span lang="EN-US">30.1.2 </span><span style="font-family: 宋体;">数据帧的构成</span> </p><p><span style="font-family:宋体;">图中</span><span lang="EN-US">D</span><span style="font-family:宋体;">表示显性电平,</span><span lang="EN-US">R</span><span style="font-family:宋体;">表示隐形电平(下同)。</span>
<span style="font-family:宋体;">帧起始,这个比较简单,标准帧和扩展帧都是由</span><span lang="EN-US">1</span><span style="font-family:宋体;">个位的显性电平表示帧起始。</span>
<span style="font-family:宋体;">仲裁段,表示数据优先级的段,标准帧和扩展帧格式在本段有所区别,如图</span><span lang="EN-US">30.1.3</span><span style="font-family:宋体;">所示:</span>
</p><center>
<ignore_js_op>
<img src="data/attach/1908/3fr47pt1wvnvzo7kvw1nyc5qc0rwhvfs.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.3 </span>数据帧仲裁段构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span style="font-family:宋体;">标准格式的</span><span lang="EN-US">ID </span><span style="font-family:宋体;">有</span><span lang="EN-US">11 </span><span style="font-family:宋体;">个位。从</span><span lang="EN-US">ID28 </span><span style="font-family:宋体;">到</span><span lang="EN-US">ID18 </span><span style="font-family:宋体;">被依次发送。禁止高</span><span lang="EN-US">7 </span><span style="font-family:宋体;">位都为隐性(禁止设定:</span><span lang="EN-US">ID=1111111XXXX</span><span style="font-family:宋体;">)。扩展格式的</span><span lang="EN-US"> ID </span><span style="font-family:宋体;">有</span><span lang="EN-US">29 </span><span style="font-family:宋体;">个位。基本</span><span lang="EN-US">ID </span><span style="font-family:宋体;">从</span><span lang="EN-US">ID28 </span><span style="font-family:宋体;">到</span><span lang="EN-US">ID18</span><span style="font-family:宋体;">,扩展</span><span lang="EN-US">ID </span><span style="font-family:宋体;">由</span><span lang="EN-US">ID17 </span><span style="font-family:宋体;">到</span><span lang="EN-US">ID0 </span><span style="font-family:宋体;">表示。基本</span><span lang="EN-US">ID </span><span style="font-family:宋体;">和标准格式的</span><span lang="EN-US">ID </span><span style="font-family:宋体;">相同。禁止高</span><span lang="EN-US">7 </span><span style="font-family:宋体;">位都为隐性(禁止设定:基本</span><span lang="EN-US">ID=1111111XXXX</span><span style="font-family:宋体;">)。</span>
<span style="font-family:宋体;">其中</span><span lang="EN-US">RTR</span><span style="font-family:宋体;">位用于标识是否是远程帧(</span><span lang="EN-US">0</span><span style="font-family:宋体;">,数据帧;</span><span lang="EN-US">1</span><span style="font-family:宋体;">,远程帧),</span><span lang="EN-US">IDE</span><span style="font-family:宋体;">位为标识符选择位(</span><span lang="EN-US">0</span><span style="font-family:宋体;">,使用标准标识符;</span><span lang="EN-US">1</span><span style="font-family:宋体;">,使用扩展标识符),</span><span lang="EN-US">SRR</span><span style="font-family:宋体;">位为代替远程请求位,为隐性位,它代替了标准帧中的</span><span lang="EN-US">RTR</span><span style="font-family:宋体;">位。</span>
<span style="font-family:宋体;">控制段,由</span><span lang="EN-US">6</span><span style="font-family:宋体;">个位构成,表示数据段的字节数。标准帧和扩展帧的控制段稍有不同,如图</span><span lang="EN-US">30.1.4</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/vilo62v78kowgn152jtu8mqgq2vva789.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.4 </span>数据帧控制段构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span lang="EN-US"></span><span style="font-family:宋体;">上图中,</span><span lang="EN-US">r0</span><span style="font-family:宋体;">和</span><span lang="EN-US">r1</span><span style="font-family:宋体;">为保留位,必须全部以显性电平发送,但是接收端可以接收显性、隐性及任意组合的电平。</span><span lang="EN-US">DLC</span><span style="font-family:宋体;">段为数据长度表示段,高位在前,</span><span lang="EN-US">DLC</span><span style="font-family:宋体;">段有效值为</span><span lang="EN-US">0~8</span><span style="font-family:宋体;">,但是接收方接收到</span><span lang="EN-US">9~15</span><span style="font-family:宋体;">的时候并不认为是错误。</span>
<span style="font-family:宋体;">数据段,该段可包含</span><span lang="EN-US">0~8</span><span style="font-family:宋体;">个字节的数据。从最高位(</span><span lang="EN-US">MSB</span><span style="font-family:宋体;">)开始输出,标准帧和扩展帧在这个段的定义都是一样的。如图</span><span lang="EN-US">30.1.5</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/br3fdj7powgxlqjl67vhyfcwd0lw4jcz.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.5 </span>数据帧数据段构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span lang="EN-US"> CRC</span><span style="font-family:宋体;">段,该段用于检查帧传输错误。由</span><span lang="EN-US">15</span><span style="font-family:宋体;">个位的</span><span lang="EN-US">CRC</span><span style="font-family:宋体;">顺序和</span><span lang="EN-US">1</span><span style="font-family:宋体;">个位的</span><span lang="EN-US">CRC</span><span style="font-family:宋体;">界定符(用于分隔的位)组成,标准帧和扩展帧在这个段的格式也是相同的。如图</span><span lang="EN-US">30.1.6</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/w5k8p4w76e4wurx62ucztzkryg9ll0v2.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.6 </span>数据帧<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">CRC</span>段构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span lang="EN-US"> </span><span style="font-family:宋体;">此段</span><span lang="EN-US">CRC</span><span style="font-family:宋体;">的值计算范围包括:帧起始、仲裁段、控制段、数据段。接收方以同样的算法计算</span><span lang="EN-US"> CRC </span><span style="font-family:宋体;">值并进行比较,不一致时会通报错误。</span>
<span lang="EN-US"> ACK</span><span style="font-family:宋体;">段,此段用来确认是否正常接收。由</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">槽</span><span lang="EN-US">(ACK Slot)</span><span style="font-family:宋体;">和</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">界定符</span><span lang="EN-US">2</span><span style="font-family:宋体;">个位组成。标准帧和扩展帧在这个段的格式也是相同的。如图</span><span lang="EN-US">30.1.7</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/el64ared0dkitfrsk53zi4golwvikcf1.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.7 </span>数据帧<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">CRC</span>段构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span style="font-family:宋体;">发送单元的</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">,发送</span><span lang="EN-US">2</span><span style="font-family:宋体;">个位的隐性位,而接收到正确消息的单元在</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">槽(</span><span lang="EN-US">ACK
Slot</span><span style="font-family:宋体;">)发送显性位,通知发送单元正常接收结束,这个过程叫发送</span><span lang="EN-US">ACK/</span><span style="font-family:宋体;">返回</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">。发送</span><span lang="EN-US">
ACK </span><span style="font-family:宋体;">的是在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元(发送单元不发送</span><span lang="EN-US">ACK</span><span style="font-family:宋体;">)。所谓正常消息是指不含填充错误、格式错误、</span><span lang="EN-US">CRC </span><span style="font-family:宋体;">错误的消息。</span>
<span style="font-family:宋体;">帧结束,这个段也比较简单,标准帧和扩展帧在这个段格式一样,由</span><span lang="EN-US">7</span><span style="font-family:宋体;">个位的隐性位组成。</span>
<span lang="EN-US"> </span><span style="font-family:宋体;">至此,数据帧的</span><span lang="EN-US">7</span><span style="font-family:宋体;">个段就介绍完了,其他帧的介绍,请大家参考光盘的</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">入门书</span><span lang="EN-US">.pdf</span><span style="font-family:宋体;">相关章节。接下来,我们再来看看</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">的位时序。</span>
<span style="font-family:宋体;">由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位可分为</span><span lang="EN-US"> 4 </span><span style="font-family:宋体;">段。</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">同步段(</span><span lang="EN-US">SS</span><span style="font-family:宋体;">)</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">传播时间段(</span><span lang="EN-US">PTS</span><span style="font-family:宋体;">)</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">相位缓冲段</span><span lang="EN-US">1</span><span style="font-family:宋体;">(</span><span lang="EN-US">PBS1</span><span style="font-family:宋体;">)</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">相位缓冲段</span><span lang="EN-US">2</span><span style="font-family:宋体;">(</span><span lang="EN-US">PBS2</span><span style="font-family:宋体;">)</span>
<span style="font-family:宋体;">这些段又由可称为</span><span lang="EN-US"> Time
Quantum</span><span style="font-family:宋体;">(以下称为</span><span lang="EN-US">Tq</span><span style="font-family:宋体;">)的最小时间单位构成。</span>
<span lang="EN-US">1 </span><span style="font-family:宋体;">位分为</span><span lang="EN-US">4 </span><span style="font-family:宋体;">个段,每个段又由若干个</span><span lang="EN-US">Tq </span><span style="font-family:宋体;">构成,这称为位时序。</span>
<span lang="EN-US">1 </span><span style="font-family:宋体;">位由多少个</span><span lang="EN-US">Tq </span><span style="font-family:宋体;">构成、每个段又由多少个</span><span lang="EN-US">Tq </span><span style="font-family:宋体;">构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。各段的作用和</span><span lang="EN-US"> Tq </span><span style="font-family:宋体;">数如表</span><span lang="EN-US">30.1.2</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/34g9po57sxmccetbkbbo7pr4k9sgiyc8.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">表<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.2 一个</span>位各段及其作用<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span lang="EN-US">1</span><span style="font-family:宋体;">个位的构成如图</span><span lang="EN-US">30.1.8</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/d0vwnnvod5rut0faqr0lgcb3kknsmp4w.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.8 </span>一个位的构成<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span style="font-family:宋体;">上图的采样点,是指读取总线电平,并将读到的电平作为位值的点。位置在</span><span lang="EN-US"> PBS1 </span><span style="font-family:宋体;">结束处。根据这个位时序,我们就可以计算</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">通信的波特率了。具体计算方法,我们等下再介绍,前面提到的</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">协议具有仲裁功能,下面我们来看看是如何实现的。</span>
<span style="font-family:宋体;">在总线空闲态,最先开始发送消息的单元获得发送权。</span>
<span style="font-family:宋体;">当多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。实现过程,如图</span><span lang="EN-US">30.1.9</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center>
<ignore_js_op>
<img src="data/attach/1908/w7n53qoscygjebpxvbn7av00edw9cd57.jpg" alt=" " title=" ">
</ignore_js_op>
</center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.9 CAN</span>总线仲裁过程<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span style="font-family:宋体;">上图中,单元</span><span lang="EN-US">1</span><span style="font-family:宋体;">和单元</span><span lang="EN-US">2</span><span style="font-family:宋体;">同时开始向总线发送数据,开始部分他们的数据格式是一样的,故无法区分优先级,直到</span><span lang="EN-US">T</span><span style="font-family:宋体;">时刻,单元</span><span lang="EN-US">1</span><span style="font-family:宋体;">输出隐性电平,而单元</span><span lang="EN-US">2</span><span style="font-family:宋体;">输出显性电平,此时单元</span><span lang="EN-US">1</span><span style="font-family:宋体;">仲裁失利,立刻转入接收状态工作,不再与单元</span><span lang="EN-US">2</span><span style="font-family:宋体;">竞争,而单元</span><span lang="EN-US">2</span><span style="font-family:宋体;">则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权。</span>
<span lang="EN-US"> </span><span style="font-family:宋体;">通过以上介绍,我们对</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">总线有了个大概了解(详细介绍参考光盘的:《</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">入门书</span><span lang="EN-US">.pdf</span><span style="font-family:宋体;">》),接下来我们介绍下</span><span lang="EN-US">STM32</span><span style="font-family:宋体;">的</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">控制器。</span>
<span lang="EN-US"> STM32</span><span style="font-family:宋体;">自带的是</span><span lang="EN-US">bxCAN</span><span style="font-family:宋体;">,即基本扩展</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">。它支持</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">协议</span><span lang="EN-US">2.0A</span><span style="font-family:宋体;">和</span><span lang="EN-US">2.0B</span><span style="font-family:宋体;">。它的设计目标是,以最小的</span><span lang="EN-US">CPU</span><span style="font-family:宋体;">负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求</span><span lang="EN-US">(</span><span style="font-family:宋体;">优先级特性可软件配置</span><span lang="EN-US">)</span><span style="font-family:宋体;">。对于安全紧要的应用,</span><span lang="EN-US">bxCAN</span><span style="font-family:宋体;">提供所有支持时间触发通信模式所需的硬件功能。</span>
<span lang="EN-US">STM32</span><span style="font-family:宋体;">的</span><span lang="EN-US">bxCAN</span><span style="font-family:宋体;">的主要特点有:</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">支持</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">协议</span><span lang="EN-US">2.0A</span><span style="font-family:宋体;">和</span><span lang="EN-US">2.0B</span><span style="font-family:宋体;">主动模式</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">波特率最高达</span><span lang="EN-US">1Mbps</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">支持时间触发通信</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">具有</span><span lang="EN-US">3</span><span style="font-family:宋体;">个发送邮箱</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">具有</span><span lang="EN-US">3</span><span style="font-family:宋体;">级深度的</span><span lang="EN-US">2</span><span style="font-family:宋体;">个接收</span><span lang="EN-US">FIFO</span>
<span style="font-family:Wingdings;" lang="EN-US">l<span style="font:7pt 'Times New Roman';"> </span></span><span style="font-family:宋体;">可变的过滤器组(最多</span><span lang="EN-US">28</span><span style="font-family:宋体;">个)</span>
<span style="font-family:宋体;">在</span><span lang="EN-US">STM32</span><span style="font-family:宋体;">互联型产品中,带有</span><span lang="EN-US">2</span><span style="font-family:宋体;">个</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">控制器,而我们使用的</span><span lang="EN-US">STM32F103ZET6</span><span style="font-family:宋体;">属于增强型,不是互联型,只有</span><span lang="EN-US">1</span><span style="font-family:宋体;">个</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">控制器。双</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">的框图如图</span><span lang="EN-US">30.1.10</span><span style="font-family:宋体;">所示:</span>
<span lang="EN-US"></span></p><center><center>
<ignore_js_op>
<img src="data/attach/1908/j6l93vb8hwe8s9y70bgdd2onygdmyo0z.jpg" alt=" " title=" ">
</ignore_js_op>
</center></center>
<span style="font-family:宋体;"><div style="text-align: center;">图<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">30.1.10 </span>双<span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">CAN</span>框图<span style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;">
</span><span lang="EN-US" style="font-family: "PingFang SC", "Lantinghei SC", "Microsoft YaHei", "HanHei SC", "Helvetica Neue", "Open Sans", Arial, "Hiragino Sans GB", 微软雅黑, STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif;"> </span></div></span><p><span style="font-family:宋体;">从图中可以看出两个</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">都分别拥有自己的发送邮箱和接收</span><span lang="EN-US">FIFO</span><span style="font-family:宋体;">,但是他们共用</span><span lang="EN-US">28</span><span style="font-family:宋体;">个滤波器。通过</span><span lang="EN-US">CAN_FMR</span><span style="font-family:宋体;">寄存器的设置,可以设置滤波器的分配方式。</span>
<span lang="EN-US"> STM32</span><span style="font-family:宋体;">的标识符过滤是一个比较复杂的东东,它的存在减少了</span><span lang="EN-US">CPU</span><span style="font-family:宋体;">处理</span><span lang="EN-US">CAN</span><span style="font-family:宋体;">通信的开销。</span><span lang="EN-US">STM32</span><span style="font-family:宋体;">的过滤器组最多有</span><span lang="EN-US">28</span><span style="font-family:宋体;">个(互联型),但是</span><span lang="EN-US">STM32F103ZET6</span><span style="font-family:宋体;">只有</span><span lang="EN-US">14</span><span style="font-family:宋体;">个(增强型),每个滤波器组</span><span lang="EN-US">x</span><span style="font-family:宋体;">由</span><span lang="EN-US">2</span><span style="font-family:宋体;">个</span><span lang="EN-US">32</span><span style="font-family:宋体;">为寄存器,</span><span lang="EN-US">CAN_FxR1</span><span style="font-family:宋体;">和</span><span lang="EN-US">CAN_FxR2</span><span style="font-family:宋体;">组成。</span>
<span lang="EN-US">STM32</span><span style="font-family:宋体;">每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:</span>
<span style="font-family:宋体;">●</span><span lang="EN-US"> 1</span><span style="font-family:宋体;">个</span><span lang="EN-US">32</span><span style="font-family:宋体;">位过滤器,包括:</span><span lang="EN-US">STDID[10:0]</span><span style="font-family:宋体;">、</span><span lang="EN-US">EXTID[17:0]</span><span style="font-family:宋体;">、</span><span lang="EN-US">IDE</span><span style="font-family:宋体;">和</span><span lang="EN-US">RTR</span><span style="font-family:宋体;">位</span>
<span style="font-family:宋体;">●</span><span lang="EN-US"> 2</span><span style="font-family:宋体;">个</span><span lang="EN-US">16</span><span style="font-family:宋体;">位过滤器,包括:</span><span lang="EN-US">STDID[10:0]</span><span style="font-family:宋体;">、</span><span lang="EN-US">IDE</span><span style="font-family:宋体;">、</span><span lang="EN-US">RTR</span><span style="font-family:宋体;">和</span><span lang="EN-US">EXTID[17:15]</span><span style="font-family:宋体;">位</span>
<span style="font-family:宋体;">此外过滤器可配置为,屏蔽位模式和标识符列表模式。</span>
<span style="font-family:宋体;">在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。</span>
<span style="font-family:宋体;">而在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用</span><span lang="EN-US">2</span><span style="font-family:宋体;">个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。</span>
<span style="font-family:宋体;">通过</span><span lang="EN-US">CAN_FMR</span><span style="font-famil
CAN->MCR|=1<<0; //请求CAN进入初始化模式
while((CAN->MSR&1<<0)==0)
{
i++;
if(i>100)return 2;//进入初始化模式失败
}
请问这段代码中,为什么i>100时,就退出?
是不是表示当请求CAN进入初始化模式后,按照道理来说此时CAN->MSR&1<<0==1,所以正常情况的话,while语句都不会被执行,然后继续执行下面的初始化语句了;可是这里用了while语句,是不是在等待当前CAN活动的结束?那么i<=100代表了多少时间呢?
同样,例程里也有这样一段程序:
CAN1->MCR&=~(1<<0); //请求CAN退出初始化模式
while((CAN1->MSR&1<<0)==1)
{
i++;
if(i>0XFFF0)return 3;//退出初始化模式失败
}
这里的i为什么与0XFFF0比较呢?这个代表什么意思?
一周热门 更多>