智能车制作

标题: 有人懂CAN总线协议吗?它是怎么实现一对一通讯的? [打印本页]

作者: 尕玍紿    时间: 2014-5-21 14:14
标题: 有人懂CAN总线协议吗?它是怎么实现一对一通讯的?
CAN总线是以广播的方式将数据发送到总线上的,不存在目标对象的地址,那CAN是怎么实现一对一的通讯的呢?印象中也有另一种通讯协议也是这样以广播的形式发送数据的,但是它把目标对象的地址融合在了发送出去的数据里,所有对象在接收到数据后,会对数据进行分析,从而知道这数据是不是发给它的,即如果接收到的数据中包含的地址信息与自身的一致,则表示是发给自己的,那他就会接收;否则则会丢弃,从而实现一对一的通讯。我想问的是CAN通讯协议是怎么实现一对一的通讯的?它的数据中没有包含类似这样的信息啊。

CAN通讯内容的数据结构,即数据帧的数据结构:

数据帧由7 个段构成。

(1)  帧起始 (标准格式 和 扩展格式一样:1bit 显性电平0)

表示数据帧开始的段。

(2)  仲裁段 (标准格式:11bit的基本ID;扩展格式:11bit的基本ID + 18bit的扩展ID)

表示数据的优先级。

(3)  控制段 (标准格式:1bitIDE + 1bit保留位 + 4bit数据字节数;扩展格式:2bit保留位 + 4bit数据字节数)

表示保留位 及 数据的字节数 的段。

(4)  数据段 (标准格式 和 扩展格式一样:0 - 8字节)

数据的内容,可发送0 ~8 个字节的数据。

(5) CRC 段 (标准格式 和 扩展格式一样:15bitCRC顺序 + 1bitCRC界定符)

检查帧的传输错误的段。
[注]CRC 顺序是根据多项式生成的 CRC 值,CRC 的计算范围包括帧起始、仲裁段、控制段、数据段。
    接收方以同样的算法计算 CRC 值并进行比较,不一致时会通报错误。

(6) ACK 段 (标准格式 和 扩展格式一样:由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成)

表示确认正常接收的段。

【注】
发送单元的 ACK段:发送单元在 ACK段发送 2 个位的隐性位。
接收单元的 ACK段:
接收到正确消息的单元在 ACK槽(ACK Slot)发送显性位, 通知发送单元正常接收结束。
这称作“发送 ACK”或者“返回 ACK”。 发送 ACK 的是在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元发送单元不发送 ACK。所谓正常消息是指不含填充错误、格式错误、CRC错误的消息。

(7)  帧结束

表示数据帧结束的段

作者: 尕玍紿    时间: 2014-5-21 14:23
http://hi.baidu.com/xiaomambzh/item/edc955f09ea7a51ad6ff8c2e

作者: lf1286    时间: 2014-5-21 17:33
依据仲裁机制。
作者: 尕玍紿    时间: 2014-5-22 14:15
lf1286 发表于 2014-5-21 17:33
依据仲裁机制。

谢谢...这个我搞明白了。
通过配置滤波寄存器和滤波屏蔽寄存器能实现。
那个,用K60能直接实现CAN总线通讯吗?好像还得加CAN收发器(如:pca82c250C)才行是不是?


作者: lf1286    时间: 2014-5-22 18:09
是的
作者: 尕玍紿    时间: 2014-5-23 10:43
lf1286 发表于 2014-5-22 18:09
是的

[attach]60132[/attach]
两个板子实现CAN通讯,这样连接可以吧?(CANH接CANH,CANl接CANL,只是简单的两条导线,10cm左右,不是双绞线)一直调不通,看到手册上说传输介质要是双绞线、光纤什么的,我这样接可以吗?

作者: lf1286    时间: 2014-5-23 11:21
那么短没问题的。因为没见到你的具体的东西,建议:硬件方面,检查有没有出现信号反射振荡,加稳定器件。如果硬件没问题,那软件设置对了没。
作者: 尕玍紿    时间: 2014-5-23 18:33
lf1286 发表于 2014-5-23 11:21
那么短没问题的。因为没见到你的具体的东西,建议:硬件方面,检查有没有出现信号反射振荡,加稳定器件。如 ...

硬件方面,检查有没有出现信号反射振荡。这个怎么检查啊?
我现在发现问题的所在了,发送一直不成功,所以应该是发送方出现了问题。我触发发送请求后,读取了发送控制寄存器TXBNCTRL的值发现:TXERR位被置位了,即发生了总线错误。现在正在仔细的阅读CAN协议的内容和了解mcp2510的发送流程,目标就是:了解什么叫:“总线错误”,什么原因会导致“总线错误”,怎么解决“总线错误”,我想我弄懂这些应该就没问题了。针对这方面,你有什么好建议吗?
发送控制寄存器TXBNCTRL的描述如下图:
[attach]60142[/attach]
触发发送请求后,即将bit3:TXREQ位置1后,
再读取这个寄存器的值,bit6=0; bit5=0;bit4=1(发生了总线错误)

作者: 尕玍紿    时间: 2014-5-24 10:37
搞定了。是我的板子有问题,换了板子后就能通讯了。
作者: lf1286    时间: 2014-5-24 19:05
搞定了就好。
作者: 尕玍紿    时间: 2014-5-27 11:30
lf1286 发表于 2014-5-24 19:05
搞定了就好。

额,又有个问题想问下。
之前我是用STM32+MCP25210+A82C250实现CAN通讯的。(STM32自带的CAN被USB占用了)
现在要换成K60的FlexCAN + A82C250来实现CAN通讯,查了下两个芯片的数据手册,有个问题不确定,关于电平兼容的。我的问题是:K60输出高电平‘1’;A82C250能识别吗?不能的话,该怎么解决?把K60的IO上拉5V的电源这样解决行吗?  详细数据见下文,IO口的电平要求都列出来了。对K60的输出电平描述看不懂。

K60兼容A82C250的输入:
A82C250:
电源:5V
输出高电平范围:4V < V(oH) < 5.3V
输出低电平范围:0V < V(oL)  <1V
K60:
电源:3.3V
输入高电平要求:2.4V < V(oH) < 无最大值(即多大都行)
输入低电平要求:无最小值(即多小都行) < V(oL) <1.155V

A82C250能兼容K60的输入吗????(低电平能兼容,高电平我不懂)
K60:
电源:3.3V
输出高电平范围:2.8V < V(oH) < 无最大值 (这里的无最大值是什么意思呢?会自行根据负载调节输出电压吗?不可能吧,3.3V的电源再怎么也不可能输出比3.3还大的吧???)
输出低电平范围:无最小值(这又是什么意思?)< V(oL) <0.5V
A82C250:
电源:5V
输入高电平要求:3.5V < V(oH) < 5.3V
输入低电平要求:-0.3V < V(oL) <1.5V

数据手册原图:
K60:
[attach]60261[/attach]
[attach]60260[/attach]

A82C250:
[attach]60262[/attach]
[attach]60263[/attach]



作者: lf1286    时间: 2014-5-27 18:09
上拉是可以的,也可以用转换芯片来实现。
作者: 尕玍紿    时间: 2014-5-31 14:19
本帖最后由 尕玍紿 于 2014-5-31 14:20 编辑
lf1286 发表于 2014-5-27 18:09
上拉是可以的,也可以用转换芯片来实现。

我之前弄的是:STM32+MCP2510+A82C250 与 STM32+MCP2510+A82C250 进行CAN通讯,已经调通了。现在在弄:K60 + A82C250 与 STM32+MCP2510+A82C250,将K60的CAN输出上拉后还是没能成功,不知道是什么原因。
现在有一个疑问:
不管什么协议的通讯,双方的波特率设置要一样这是必须的,但是CAN这里的波特率设置在细节上面我有一个问题:
CAN的波特率设置是基于“最小时间分量TQ”对不同段位的位时间长度进行配置从而得到了一个波特率的。我现在的情况是通讯双方的最终波特率是一样的,都设置为125Kbps了;但是他们在细节上的配置是不一致的(即TQ不等、不同段位的位时间长度也不尽相同),这样的配置行得通吗?

以下是具体配置:
STM32+MCP2510+A82C250的波特率配置:
write_mcp2510_oneByte(CNF1,0x07); // 8分频:TQ= 2 * 1/(16/8) = 1us
write_mcp2510_oneByte(CNF2,0x90); // Pseg=1TQ,PS1=3TQ
write_mcp2510_oneByte(CNF3,0x02); // PS2=3TQ
//时钟源Fosc=16MHz ; 预分频数:BRP=7(8分频) ; 即:最小时间分子TQ = 2*(1/Fosc)*(BRP+1);
//(再同步补偿时间长度)Sync Seg=1TQ ;       (传播段的位时间长度) Prop Seg=1TQ ;
//(相位段1的位时间长度)Phase Seg1=3TQ ;  (相位段2的位时间长度)Phase Seg2=3TQ ;
//所以波特率就为 Bus speed = 1 / ((Total of TQ) * TQ) = 125Kbps


K60+A82C250的波特率配置:
CAN_CTRL1_REG(CANBaseAdd) |= CAN_CTRL1_CLKSRC_MASK; //选择时钟源:外设时钟,由PLL分频得到:48MHz
CAN_CTRL1_REG(CANBaseAdd) = ( 0 | CAN_CTRL1_PROPSEG(1)      /*设置传播段位时间长度=2TQ*/
                                                   | CAN_CTRL1_RJW(1)             /*设置再同步补偿时间长度=2TQ*/
                                                   | CAN_CTRL1_PSEG1(3)          /*设置相位段1位时间长度=4TQ*/
                                                   | CAN_CTRL1_PSEG2(3)          /*设置相位段2位时间长度=4TQ*/
                                                   | CAN_CTRL1_PRESDIV(31) );  /*32分频:TQ=1/(48/32)=0.67us*/

//所以波特率就为 Bus speed = 48M / 32分频 /12个TQ = 125Kbps
        






欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2