stm32——can(一)基础知识

一、简介 

        CAN 是控制器局域网络(Controller Area Network)的简称,它是由研发和生产汽车电子产品著称的德国BOSCH 公司开发的。当时,提出 CAN 总线的最初动机就是为了解决现代汽车中庞大的电子控制装置之间的通讯,减少不断增加的信号线。于是,他们设计了一个单一的网络总线, 所有的外围器件可以被挂接在该总线上。后来逐步发展成为ISO国际标准,成为目前汽车电子、工业控制等行业中应用最广泛的协议之一。

二、特点

①多主工作模式

        所谓多主工作方式,是指总线上的所有节点没有主从之分,大家都处于平等的地位,在总线空闲状态(当总线上的上出现连续的11位隐性电平,那么总线就处于空闲状态。也就是说对于任意一个节点而言,只要它监听到总线上连续出现了11位隐性电平,那么该节点就会认为总线当前处于空闲状态,它就会立即向总线上发送自己的报文),任意节点都可以往总线上发送消息。

②非破坏性仲裁机制

       在CAN协议中,所有的消息都以固定的帧格式发送。当多个节点同时向总线发送消息时,对各个消息的标识符(即ID号)进行逐位仲裁,如果某个节点发送的消息仲裁获胜,那么这个节点将获取总线的发送权,仲裁失败的节点则立即停止发送并转变为监听(接收)状态。这种仲裁机制既不会造成已发送数据的延迟,也不会破坏已经发送的数据,所以称为非破坏性仲裁机制。

③完善的错误处理机制

  • 所有的节点都可以检测错误(错误检测功能)。
  • 检测出错误的节点会立即同时通知其他所有节点(错误通知功能)。
  • 正在发送消息的节点一旦检测出错误,会强制结束当前的发送。强制结束发送的节点会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
  • 数据帧中包含crc校验,保证数据通信的可靠性。

④抗干扰能力强

        can通讯使用差分信号传输数据,当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所以外界的共模噪声几乎可以被完全抵消。因此其具有较强的抗干扰能力。

三、can信号

        can总线通讯属于异步通讯,不同于I2C、SPI 等具有时钟信号的同步通讯方式,CAN 通过can_H和can_L两根信号线的差分信号进行通讯。其中逻辑1规定为隐性电平,逻辑0规定为显性电平,其电平信号的标准见下图(下图分别包含 ISO-11898(高速can)和 ISO11519(低速can)规定的can差分信号电平标准)。

     

        ISO-11898 定义了通信速率最高可达1Mbps 的高速 CAN 通信标准,属于闭环总线,总线两端各要求有一个120欧的电阻,总线长度 ≤ 40米,如图所示。

        ISO11519 定义了通信速率最高可达125 kbps 的低速 CAN 通信标准,属于开环总线,两根通讯线相互独立,要求每根通讯线串联一个2.2千欧的电阻,不形成闭环。其传输速率为40kbps时,总线长度可达1000米,如图所示。

四、can报文

        can报文的种类共有5种,分别为:数据帧、远程帧、错误帧、过载帧、帧间隔。

4.1 数据帧

4.1.1 报文结构

        can数据帧根据仲裁段ID长度不同又分为标准数据帧和扩展数据帧(标准帧ID长度11bit,扩展帧29bit),数据帧结构由7个段组成,分别为:起始段、仲裁段、控制段、数据段、CRC段、ACK段、帧结束段,如下图所示。

1)起始段——start of frame(SOF)

        起始段只有一位数据,是一个显性电平。用于通知各个节点将有数据传输,其它节点通过起始帧信号来进行硬同步

2)仲裁段——Arbitration field

        当总线上同时有两个节点需要发送报文时,总线会根据仲裁段的内容决定哪个数据包能被传输。

        仲裁段的内容主包含本条数据帧的标识符,两个节点同时竞争总线占有权时,由于can总线数据传输遵循显性优先的原则,所以谁的仲裁段先出现隐形电平则失去对总线的占有权,另外通过前面介绍也知道逻辑1表示隐形电平,所以两个节点同时发送数据时标识符的大小就和数据发送的优先级息息相关。

        另外仲裁段除了标识符外,还有RTR、IDE和SRR位。

        ①RTR(Remote Transmission Request),它用于区分can报文是属于远程帧还是数据帧,该位为显性电平时表示数据帧,隐形电平时表示远程帧(不包含数据段);

        ②IDE(Identifier Extension),它用于区分can报文是标准帧(包含11位帧ID)还是扩展帧(包含29位帧ID,在标准帧11位ID基础上包含额外的18位ID),该位为显性电平时表示标准帧,隐形电平时表示扩展帧;

        ③SRR(Substitute Remote Request),该位只存在于扩展帧中,用于替代标准格式中RTR位。在扩展帧中该位必须为隐形电平,因此对于前11位ID相同的标准帧和扩展帧,标准帧优先级比扩展帧高;

3)控制段

        在控制段中的r1 和r0 为保留位,默认设置为显性位。

        它最主要的是DLC 段(Data Length Code),它由4 个数据位组成,用于表示本报文中的数据段含有多少个字节,DLC 段表示的数字为0~8。

4)数据段

        数据段为数据帧的核心内容,它是节点要发送的原始信息,由0~8 个字节组成。

5)CRC段

        为了保证报文的正确传输,CAN 的报文包含了一段15 位的CRC 校验码,一旦接收节
点算出的CRC 码跟接收到的CRC 码不同,则它会向发送节点反馈出错信息,利用错误帧
请求它重新发送。CRC 部分的计算一般由CAN 控制器硬件完成,出错时的处理则由软件
控制最大重发数。

        在CRC 校验码之后,有一个CRC 界定符,它为隐性位,主要作用是把CRC 校验码与
后面的ACK 段间隔起来。

6)ACK段

        ACK 段包括一个ACK 槽位,和ACK 界定符位。类似I2C 总线,在ACK 槽位中,发
送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答。在ACK 槽和帧
结束之间由ACK 界定符间隔开。

7)结束段

      EOF 段(End Of Frame),帧结束段由发送节点发送的7 个隐性位表示结束。

4.1.2 实例分析 

        这里使用上位机软件设置波特率为500kbps,发送标准数据帧如下,另一张图为示波器采集的完整数据帧,我们来慢慢分析。

canIDDLCdata0data1data2data3data4data5data6data7
501h855h55h55h55h55h55h55h55

         ①波特率位500kbps,每一位数据占2us。其中帧起始段(SOF)固定为一个显性位,如下图所示。

        ②下图绿色标识部分包含标准帧11位ID——10100000001b, 逻辑1为隐性电平,逻辑0为显性电平。之所以下图中绿色标识部分有12bit,是因为其中灰色标识为1bit位填充,后面会有说明。

         ③如下图,黄色标识为仲裁段的RTR位,显性电平表示数据帧;控制段分包含IDE、r0和DLC,IDE为显性位表示标准帧,r0为保留位默认为显性位,DLC表示数据长度8=1000b;

        ④DLC后面接着就是8byte数据段,因为这里我发送的数据都是0x55=01010101b,所以在示波器上看到的就是0和1交替,如下图所示。

        ⑤数据段后面接着就是CRC段,crc段含15bit的crc校验值和1位隐形crc界定符;crc段后就是ack应答信号,如下图所示。

4.2 远程帧 

        远程帧和数据帧类似,也分为标准远程帧和扩展远程帧,不同的是远程帧只包含6个段,分别为:起始段、仲裁段、控制段、CRC段、ACK段、帧结束段,没有数据段。除此之外,就是远程帧的RTR位恒为隐性1,数据帧的RTR位恒为显性0如下图所示。

4.3 错误帧 

        错误帧是用于在接收和发送报文时检测出错误而通知错误的帧,错误帧由错误标志和错误界定符构成,了解错误帧结构之前我们需要先了解一下can的错误种类和错误状态。

 4.3.1 can错误分类

        在CAN总线通信中,一共有五种错误:位错误、ACK错误、填充错误、CRC错误、格式错误。

        ①位错误,是指节点将自己发送到总线上的电平与同时从总线上回读到的电平进行比较,如果发现二者不一致,那么这个节点就会检测出一个位错误。但是以下三种情况不属于位错误

  • 在仲裁区,节点向总线发送隐性位却回读到显性位,这种情况表示该节点仲裁失败;
  • 在ACK槽,节点向总线发送隐性位却回读到显性位,这种情况表示,该节点当前发送的这一帧报文至少被一个其它节点正确接收;
  • 该节点发送被动错误标志,节点A向总线发送连续六个隐性位(被动错误标志)却回读到显性位。因为被动错误标志是六个连续的隐性位,所以在总线上按照线与机制,有可能这六个连续隐性位被其它节点发送的显性电平线与成显性位;

        ②ACK错误,按照CAN协议的规定,在一帧报文(数据帧或者遥控帧)发出之后,如果接收节点B成功接收了该帧报文,那么接收节点B就要在该帧报文ACK槽对应的时间段内向总线上发送一个显性位来应答发送节点A。这样发送节点Node_A就会在ACK槽时间段内从总线上回读到一个显性位。因此:当发送节点A在ACK槽时间段内没有回读到显性位,那么发送节点A就会检测到一个ACK应答错误,表示没有一个节点成功接收该帧报文。

        ③位填充错误,说这个之前我们需要先了解什么是位填充——CAN协议中规定,当相同极性的电平持续五位时,则添加一个极性相反的位。CAN接收节点会自动删除这个新增的额外电平位位填充作用是为了缩短从同步周期,因为重同步机制是基于信号跳变沿来进行的。位填充机制保证了传输过程中有足够的跳变沿。ISO 11898-1规定,发送方在传输连续5个相同位后必须传输一个相反的位;即使连续5个相同位后本就是一个相反位,也需要添加填充位。

        而为填错误就是在需要执行位填充原则的帧段数据帧遥控帧的SOF~CRC序列),检测到连续六个同性位,此时就会产生一个位填充错误。

        ④CRC错误,发送节点A在发送数据帧或者遥控帧时,会计算出该帧报文的CRC序列并包含在报文中。接收节点B在接收报文时也会执行相同的CRC算法,如果接收节点B计算出的CRC序列值与发送节点A发来的CRC序列值不一致,那么接收节点就检测到一个CRC错误。

        ⑤格式错误,在一帧报文发送时,如果在必须发送预定值的区域内检测到了非法值,那么就检测到一个格式错误。CAN报文中,有预定值的区域有如下几种:

  • 数据帧和遥控帧的CRC界定符、ACK界定符、EOF;
  • 错误帧界定符;
  • 过载帧界定符;

4.3.2 can错误状态

        按照CAN协议的规定,CAN总线上的节点始终处于以下三种状态之一,分别是主动错误状态、被动错误状态和总线关闭状态,如下图所示。

        

        那么一个CAN节点如何在这三种状态间实现切换的呢?答案是在CAN节点内有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC),其值会根据检测到的错误而增加或减少。按照CAN的标准,当接收出错时, 根据出错的条件,该计数器加1或加8;而在每次接收成功后,该计数器减1,或当该计数器的值大于127时,设置它的值为120。当该计数器的值超过127时,CAN进入错误被动状态。发送错误计数类似于接收计数器。具体如何计数如下图所示。

        ①主动错误状态,最开始TCE和REC都小于127时,就处于主动错误状态。节点处于主动错误状态可以正常通信。在这一状态下,节点检测到一个错误就会发送带有主动错误标志(主动错误标志是连续六个显性位)的错误帧,所以这个时候主动错误标志将会“覆盖”掉总线上其它节点的发送,而之前在CAN总线上传输的报文就被这“六个连续显性位”破坏掉了。

        ②被动错误状态,当某个节点的TCE>127 或者 REC>127,该节点就进入被动错误状态。节点处于被动错误状态也可以正常通信。在这一状态下,节点检测到一个错误就会发送带有被动错误标志(被动错误标志是连续六个隐性位)的错误帧。

        ③离线状态,如果一个处于被动错误状态的节点,仍然多次发送被动错误帧,那么势必导致TEC > 255,这样就处于总线关闭状态。在总线关闭状态下的节点不能向总线上发送报文,也不能从总线上接收报文,整个节点脱离总线。等到检测到128次11个连续的隐性位时,TEC和REC置0,重新回到主动错误状态。

 4.3.3 错误寄存器 

        在stm32中can错误寄存器相关信息如下:

can错误状态寄存器——CAN error status register (CAN_ESR) 

Bits 31:24 REC[7:0]: Receive error counter

        这个计数器按照CAN协议的故障界定机制的接收部分实现。按照CAN的标准,当接收出错时, 根据出错的条件,该计数器加1或加8;而在每次接收成功后,该计数器减1,或当该计数器的值大于127时,设置它的值为120。当该计数器的值超过127时,CAN进入错误被动状态。

Bits 23:16 TEC[7:0]: Least significant byte of the 9-bit transmit error counter

        通接收计数器类似

Bits 6:4 LEC[2:0]: Last error code

        在检测到CAN总线上发生错误时,硬件根据出错情况设置。当报文被正确发送或接收后,硬件清除其值为’0’。

Bit 2 BOFF: Bus-off flag

        当发送错误计数器TEC溢出,即大于255时,CAN进入离线状态,硬件对该位置’1’。

Bit 1 EPVF: Error passive flag 

        当出错次数达到错误被动的阈值时,硬件对该位置’1’。(接收错误计数器或发送错误计数器的值>127)。

Bit 0 EWGF: Error warning flag    

        当出错次数达到警告的阈值时,硬件对该位置’1’。(接收错误计数器或发送错误计数器的值≥96)。  

4.3.4 错误帧结构 

        有了前面的基础知识,最后我们再来认识一下can错误帧。错误帧由错误标志和错误界定符两个部分组成,如下图所示。

        错误标志包含主动错误标志(六个显性位)和被动错误标志(六个隐性位)两种;

        错误界定符由8bit连续隐形位表示;

        从上图可以看到除了6bit错误标志,后面还有0~6bit的错误标志重叠部分,这是什么意思呢?看下图。

         发送节点A发送一个显性位,但是却从总线上检测到一个隐形位,于是节点A就会判断出现一个位错误;于是立即在下一位开始发送一个主动错误帧(6个连续显性位的主动错误标志+8个连续隐性位的错误界定符);与此同时,接收节点B和C从总线上听到连续6个显性位,那么就会检测到一个填充错误,于是这两个节点也会发送主动错误帧;此时,总线又会出现6个连续显性电平,节点A和节点B、C的错误标志就会有2bit是重叠的,节点B、C剩余的 4bit错误标志就属于错误标志重叠部分。

4.3.5 错误帧的发送

按照CAN协议的规定:

  • 当节点检测到位错误、填充错误、格式错误和ACK错误后,就需要开始发送错误帧。
  • 当节点检测到CRC错误后,紧随ACK界定符后的位发送错误帧

4.4 过载帧

        过载帧包括:过载标志和过载界定符两个部分。过载标志包含连续6个显性位;过载界定符包含连续8个隐性位。

        过载帧与错误帧类似,过载帧中有过载帧重叠部分,且形成过载重叠标志的原因与形成错误帧中的错误重叠标志的原因也是相同的。

        形成过载帧主要有以下三种情况:

  • 接收节点自身原因。接收节点由于某种原因需要延迟接收下一个数据帧或者遥控帧。
  • 在帧间隔的间歇段的第一位和第二位检测到一个显性位(正常的间歇段都是隐性位)帧间隔的间隔段本应是三个连续的隐性位,如果接收节点A在间隔段检测到显性位,那么就意味着此时有报文发向接收节点A,但这个时候是不应该有报文发来的,于是节点A发送过载帧。
  • CAN节点在错误界定符或过载界定符的第八位(最后一位)听到一个显性位0,节点会发送一个过载帧,且错误计数器不会增加。

 4.5 帧间隔

        帧间隔是用来隔离数据帧或者远程帧的,数据帧或者远程帧通过插入帧间隔可以将本帧与先行帧(数据帧、遥控帧、错误帧、过载帧)分隔开来。

        间隔帧又有两种形式,分别为主动错误状态下间隔帧和被动错误下间隔帧,如下图所示。

主动错误状态下间隔帧
被动错误状态下间隔帧

        ①间隔段:包含连续三个隐性位;间隔段期间,所有节点不允许发送数据这或远程帧,只要在这期间监听到显性位,接收节点就会发送过载帧。
        ②空闲段:连续隐性位,个数不一定,0个或者多个都可以。总线空闲的时间是任意长的,只要总线空闲,节点就可以竞争总线。
        ③暂停段:只有处于被动错误状态的节点在发送帧间隔的时候,才会在帧间隔中插入8个连续隐性位的暂停段。 

五、can位时序与同步 

5.1 位时序

        由于CAN 属于异步通讯,没有时钟信号线,节点间除了像串口异步通讯那样使用约定好的波特率进行通讯。除此之外,CAN 还会使用"位同步"的方式来抗干扰、吸收误差,实现对总线电平信号进行正确的采样,确保通讯正常。

        为了实现位同步,CAN 协议把每一个数据位的时序分解成如下图所示的SS 段、PTS 段、PBS1 段、PBS2 段,这四段的长度加起来即为一个CAN 数据位的长度。分解后最小的时间单位是Tq,而一个完整的位由8~25 个Tq 组成。为方便表示,图中的高低电平直接代表信号逻辑0 或逻辑1(不是差分信号)。

1) SS 段(SYNC SEG)

        SS 段的大小固定为1Tq。若通讯节点检测到总线上信号的跳变沿被包含在SS 段的范围之内,则表示节点与总线的时序是同步的,当节点与总线同步时,采样点采集到的总线电平即可被确定为该位的电平。

2)传播段(Propagation Segment)

        PTS段是用于补偿网络的物理延时时间。是总线上输入比较器延时和输出驱动器延时总和的两倍。PTS 段的大小可以为1~8Tq。

3)相位缓冲段1(Phase Buffer Segment1):

        PBS1段主要用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以加长。PBS1 段的初始大小可以为1~8Tq。

4)相位缓冲段2(Phase Buffer Segment2):

        PBS2段也是用来补偿边沿阶段误差的,它的时间长度在重新同步时可以缩短。PBS2 段的初始大小可以为2~8Tq。

5.2 位同步

        CAN 的数据同步分为硬同步和重新同步两种。其中硬同步只在帧起始信号(SOF)时起作用,无法确保后续一连串的位时序都是同步的。而重新同步方式是利用普通数据位的高至低电平的跳变沿来同步(帧起始信号是特殊的跳变沿)。重新同步与硬同步方式相似的地方是它们都使用SS 段来进行检测,同步的目的都是使节点内的SS段把跳变沿包含起来。

        ①硬同步

        若某个CAN 节点通过总线发送数据时,它会发送一个表示通讯起始的信号(SOF),该信号是一个由高变低的下降沿。而挂载到CAN 总线上的通讯节点在不发送数据时,会时刻检测总线上的信号。节点A在发送SOF位时,SOF位的下降沿在SS段。这个时候接收节点B发现自己当前位的SS段和发送节点A的SOF位的SS段不同步。也就是说当节点A产生SOF位SS段时,Node_B的当前位的SS段已经在5个Tq之前产生了。于是接收节点Node_B强行将自己当前位的SS段拉到与SOF位的SS段同步,如下图所示。值得注意的是,在硬同步中所有接收节点调整各自当前位的同步段,调整宽度不限。

        

        ②重同步 

        重新同步的方式分为超前和滞后两种情况,以总线跳变沿与SS 段的相对位置进行区
分。

        第一种相位超前的情况如下图所示,节点从总线的边沿跳变中,检测到它内部的时序比
总线的时序相对超前2Tq,这时控制器在下一个位时序中的PBS1 段增加2Tq 的时间长度,
使得节点与总线时序重新同步。

         第二种相位滞后的情况如下图所示,节点从总线的边沿跳变中,检测到它的时序比总线
的时序相对滞后2Tq,这时控制器在前一个位时序中的PBS2 段减少2Tq 的时间长度,获
得同步。

         在重新同步的时候,PBS1 和PBS2 中增加或减少的这段时间长度被定义为“重新同步
补偿宽度SJW (reSynchronization Jump Width)”。一般来说CAN 控制器会限定SJW 的最大
值为4Tq。

5.3 stm32位时序及波特率配置

         前面说的是标准can位时序,stm32外设can定义的位时序与前面有一点区别。STM32 的CAN 外设位时序中只包含3 段,分别是同步段SYNC_SEG、位段BS1 及位段BS2,采样点位于BS1 及BS2 段的交界处。其中SYNC_SEG 段固定长度为1Tq,而BS1 及BS2 段可以在位时序寄存器CAN_BTR 设置它们的时间长度,它们可以在重新同步期间增长或缩短,该长度SJW 也可在位时序寄存器中配置。

stm32can位时序

位时序相关寄存器:
CAN bit timing register (CAN_BTR) 

Bits 9:0 BRP[9:0]: Baud rate prescaler

        波特率分频器 (Baud rate prescaler),该位域定义了时间单元(tq)的时间长度(tq = (BRP[9:0]+1) x tPCLK )。

Bits 19:16 TS1[3:0]: Time segment 1

        该位域定义了时间段1占用了多少个时间单元,tBS1 = tCAN x (TS1[3:0] + 1),tBS1最大为8。

Bits 22:20 TS2[2:0]: Time segment 2

        该位域定义了时间段2占用了多少个时间单元,tBS2 = tCAN x (TS2[2:0] + 1),tBS2最大为16。

Bits 25:24 SJW[1:0]: Resynchronization jump width

        为了重新同步,该位域定义了CAN在每位数据传输重同步过程中可以延长或缩短多少个时间单元的上限(tRJW = tCAN x (SJW[1:0] + 1)),tRJW最大为4。

波特率配置:

        了解位时序后,我们就可以配置波特率了。通过配置位时序寄存器CAN_BTR 的
TS1[3:0]及TS2[2:0]寄存器位设定BS1 及BS2 段的长度后,我们就可以确定每个CAN 数据
位的时间:
BS1 段时间:
        TS1=Tq x (TS1[3:0] + 1),
BS2 段时间:
        TS2= Tq x (TS2[2:0] + 1),
一个数据位的时间:
        T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq


        其中单个时间片的长度Tq 与CAN 外设的所挂载的时钟总线及分频器配置有关,CAN1 和CAN2 外设都是挂载在APB1 总线上的,而位时序寄存器CAN_BTR 中的BRP[9:0]寄存器位可以设置CAN 外设时钟的分频值 ,所以:
        Tq = (BRP[9:0]+1) x TPCLK
其中的PCLK 指APB1 时钟,我这里测试是为36MHz。
最终可以计算出CAN 通讯的波特率:
        BaudRate = 1/N Tq

int MX_CAN_Init(E_CAN_BAUDRATE rate)
{

    /* USER CODE BEGIN CAN_Init 0 */
	HAL_StatusTypeDef HAL_Status = HAL_OK;
	CAN_FilterTypeDef hCAN_Filter;
    /* USER CODE END CAN_Init 0 */

    /* USER CODE BEGIN CAN_Init 1 */

    /* USER CODE END CAN_Init 1 */
    hcan.Instance = CAN1;
    hcan.Init.Mode = CAN_MODE_NORMAL;
    hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
	//baudrate=APB1Clock/((1+Ts1+Ts2)*Prescaler)
	switch(rate)
	{
	case BAUDRATE_500K:
		hcan.Init.Prescaler = 8;//另外注意这里分频系数,在HAL_CAN_Init里面是有减1的,所以计算分频系数时候这里不需要减1
		hcan.Init.TimeSeg1 = CAN_BS1_7TQ;//CAN_BS1_7TQ这个宏实际值为6,对应CAN_BTR寄存器的TS1[3:0],实际Ts1=6+1=7Tq
		hcan.Init.TimeSeg2 = CAN_BS2_1TQ;//CAN_BS2_1TQ这个宏实际值为0,对应CAN_BTR寄存器的TS2[2:0],实际Ts2=0+1=1Tq
		break;
	}
    hcan.Init.TimeTriggeredMode = DISABLE;
    hcan.Init.AutoBusOff = DISABLE;
    hcan.Init.AutoWakeUp = DISABLE;
    hcan.Init.AutoRetransmission = DISABLE;
    hcan.Init.ReceiveFifoLocked = DISABLE;
    hcan.Init.TransmitFifoPriority = DISABLE;
    HAL_Status |= HAL_CAN_Init(&hcan);
}

/**
  * @brief  Initializes the CAN peripheral according to the specified
  *         parameters in the CAN_InitStruct.
  * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan)
{  
    /* Set the bit timing register */
    WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode           |
                                            hcan->Init.SyncJumpWidth  |
                                            hcan->Init.TimeSeg1       |
                                            hcan->Init.TimeSeg2       |
                                            (hcan->Init.Prescaler - 1U)));
    return HAL_OK;
}

最后,内容有点多了,下篇继续。。。

  • 30
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值