can报文解析(CAN报文解析 CSDN博客)

can报文解析(CAN报文解析 CSDN博客)p strong 如果不知道代码里的参数设置 看了这篇文章你可能会对 CAN 代码有更清晰的认识 strong p 首先要配置 GPIO CAN TX 是输出 引脚控制权在 CAN 外设 所以我们需要配置为复用推挽输出模式 CAN RX 是输入

大家好,我是讯享网,很高兴认识大家。



 <p><strong>如果不知道代码里的参数设置&#xff0c;看了这篇文章你可能会对CAN代码有更清晰的认识。</strong></p> 

讯享网


讯享网

        首先要配置GPIO,CAN_TX是输出,引脚控制权在CAN外设,所以我们需要配置为复用推挽输出模式CAN_RX是输入,需要配置为上拉输入模式。

        由发送和接收控制器全权管理输入和输出的报文,当接收到一个报文后,它会自动和配置的过滤器进行比对,符合过滤器的报文,它自动帮你存入到FIFO的队列中,CPU直接读取FIFO就行。在程序中只需要告诉发送和接收控制器我们想要发出什么报文和读取它帮我们存入到FIFO里的接收报文即可。

        红框所示,当我们想要发出一个报文时,我们只需要把报文的各个参数,比如ID、Data、IDE、RTR等写入到其中一个发送邮箱,然后给一个请求发送的命令,之后发送和接收控制器就会等待总线空闲时,自动把这个报文广播到总线上。为了防止总线繁忙造成发送拥堵,造成CPU等待,故设计了3个发送邮箱。当CPU想发送报文时,任意选一个空的邮箱写入报文,请求发送,然后CPU就可以干别的事了,如果CPU再发时,看到上次的报文还在等待,那CPU就可以换另外一个空置邮箱,写入报文,再次请求发送。如果三个都满了,还要发,只能让CPU等待或者让CPU放弃本次发送。

        最后这个发送可以设置发送策略,如果有多个报文都在邮箱里待发,此时总线空闲了,那么发送和接收控制器可以通过配置决定先发谁:先请求先发送/按ID号优先级发送(ID号最小的先发送)。

        黄框所示,当CAN总线出现任何一个数据帧或遥控帧的报文波形时,发送和接收控制器就会把这个报文收下来,但是总线上的报文各种各样,这个报文不一定是这个设备需要的,所以这个报文收下来之后会先经过接收滤波器,接收滤波器可以根据ID号对报文进行过滤,通过不了过滤器这个报文就直接丢弃。

        过滤器一共有14个,在程序中,我们可以对任意一个过滤器进行配置,把我们想要接收的报文ID规则写入到过滤器中,这样总线上一旦出现我们想要的报文那它就会通过其中某一个过滤器。没有使用到的过滤器不需要去配置,那它就处于默认失能状态,不起作用。

        需要的报文会被储存到FIFO先进先出寄存器中,排队等待CPU读取,配置过滤器的时候,有参数可以指定通过这个过滤器的报文该进哪一个FIFO队伍,进了队伍以后从邮箱0开始排队。报文从邮箱0被读取后,存储在邮箱1的报文会排到邮箱0,邮箱2的报文会排到邮箱1。

        STM32可以配置FIFO的锁定状态,来处理当FIFO满之后,新的报文该怎么存:如果配置FIFO锁定,那么FIFO满之后,新的报文会直接丢弃,如果配置FIFO不锁定,那么FIFO满之后,新的报文会把邮箱2的数据替换成自己。

        CPU可以用轮询或者中断的方法依次检查FIFO 0和FIFO 1的队伍长度,只要队伍里有报文,长度大于0,那CPU就可以读取对应队伍,队首的报文,这样就完成了报文数据的读取。

        设置两个队列是为了将重要报文和不那么重要的报文区分开,这样重要报文丢失的概率就大大降低了。

基本流程:选择一个空置邮箱→写入报文 →请求发送

        上图表示一个发送邮箱的状态图,邮箱默认的状态是空置状态1,RQCP(Request completed)请求完成位,X表示任意值;TXOK(Transmission OK)发送成功,X表示任意值;TME(Transmit mailbox empty)是发送邮箱空,=1表示当前邮箱是空置状态。

        当我们指定这个空置邮箱后,首先写入报文,然后请求发送,TXRQ(Transmit mailbox request)发送请求控制位,TXRQ = 1,表示产生这个发送请求,所以该邮箱就进入到挂号状态2。挂号状态,请求完成 = 0,发送成功 = 0,发送邮箱空 = 0,挂号状态说明此邮箱的数据已经准备好了。

        但是邮箱有3个,可能别的邮箱也有数据准备好了,所以该邮箱得排队,等优先级已经是最高优先级了,邮箱进入预定状态3,如果在预定状态邮箱的优先级又被比下去了,就会回到挂号状态2。

        处于预定状态的报文,只要出现CAN总线 = IDLE空闲,那么发送和接收控制器就会把该报文发送到CAN总线,邮箱也进入发送状态4,发送状态持续一段时间,如果报文正常发送成功,那么该邮箱就完成了全部使命,回到空置状态5,并且置状态位,请求完成 = 1,发送成功 = 1,发送邮箱空 = 1。

        如果发送失败,根据NART走向两个状态。NART(No automatic retransmission)是禁止自动重传:NART = 0,表示使用自动重传,那么发送失败的报文就回到预定状态3,下次总线空闲了,会再次发送,直到发送成功为止;NART = 1,表示禁止自动重传,发送失败后,直接回到空置状态6,并且置状态位,请求完成 = 1,发送成功 = 0,发送邮箱空 = 1(请求已经完成,但是发送没成功,邮箱目前空置)。

        ABRQ(Abort request)是中止发送,如果邮箱处于预定或挂号状态,当前报文其实还没发出去,这时,我们可以置ABRQ = 1,中止该发送,回到空置状态6,并且置状态位,请求完成 = 1,发送成功 = 0,发送邮箱空 = 1(请求已经完成,但是发送没成功,邮箱目前空置)。

        在程序中,我们可以读取这些状态寄存器来获取邮箱的状态。

基本流程:接收到一个报文→匹配过滤器后进入FIFO 0或FIFO 1→CPU读取。

        上图表示一个FIFO的接收流程图,最初状态FIFO是空状态,此时FMP(FIFO message pending)报文数目 = 0,FOVR(FIFO overrun)FIFO溢出 = 0,当收到一个有效报文时,FIFO队伍里就排队一个报文,这时FIFO处于挂号1状态,报文数目 = 1,FIFO溢出 = 0,如果又收到有效报文,那么FIFO队伍里排队两个报文,此时进入挂号2状态,报文数目 = 0b10(2),FIFO溢出 = 0,如果又收到有效报文,那么FIFO队伍里排队三个报文,此时进入挂号3状态,报文数目 = 0b11(3),FIFO溢出 = 0,此时FIFO已经满了,有一个没标注出来的FULL位置1,如果再收到有效报文,那么就进入溢出状态,报文数目 = 0b11(3),FIFO溢出 = 1。

        当FIFO队伍里有报文时,就可以读取FIFO了并且读完一个报文,必须得释放邮箱,如果FIFO是溢出状态,我们设置RFOM(Release FIFO output mailbox)为1,释放邮箱,FIFO就进入挂号3状态,挂号3状态,我们读取FIFO后,也释放邮箱,这时FIFO进入挂号2状态,队伍变短了,如果继续读取,释放邮箱直到为空状态。

        值得注意的是,溢出状态和挂号3属于一个状态,它们的队伍长度都是3,释放一次都回到挂号2。

        NART:置1,关闭自动重传,CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失);置0,自动重传,CAN硬件在发送报文失败时会一直自动重传直到发送成功。

        TXFP:置1,优先级由发送请求的顺序来决定,先请求的先发送;置0,优先级由报文标识符来决定,标识符值小的先发送(标识符值相等时,邮箱号小的报文先发送)。

        RFLM:置1,接收FIFO锁定,FIFO溢出时,新收到的报文会被丢弃;置0,禁用FIFO锁定,FIFO溢出时,FIFO中最后收到的报文被新报文覆盖。

小讯
上一篇 2025-06-02 16:37
下一篇 2025-05-30 21:36

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/178314.html