CAN类 –控制器区域网络通信总线

CAN实施标准CAN通信协议。其物理层包括两道线:RX和TX。注意:将pyboard或OpenMV Cam与CAN总线连接时,您必须使用来CAN传输器将来自的CAN逻辑信号转换为总线上正确的电压等级。

示例用法(在没有任何连接的情况下工作):

from pyb import CAN
can = CAN(2, CAN.LOOPBACK)
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))  # 设置一个过滤器来接收id为123、124、125和126的消息
can.send('message!', 123)   # 发送 ID 为 123 的消息
can.recv(0)                 # 在FIFO 0上接收消息

构造函数

class pyb.CAN(bus, ...)

在给定总线上构建一个CAN对象。 bus 可为2。在没有其他参数的情况下,可创建CAN对象,但未进行初始化( 该对象的设置来自总线的最后一次初始化,若存在的话)。若给定额外参数,则总线进行初始化。初始化参数详见 init

CAN总线的物理引脚为:

  • CAN(2): (RX, TX) = (PB12, PB13)

类方法

classmethod CAN.initfilterbanks(nr)

28 - nr 滤波器组分配给CAN(2)。

方法

CAN.init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False, baudrate=0, sample_point=75)

使用给定参数初始化CAN总线:

  • mode 为下列之一:NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • extframe 为True,总线使用框架(29位)中的扩展标识符;否则使用标准的11位标识符。

  • prescaler 用于设置1时间量的持续时长;时间量为分配器分割的输入时钟(PCLK1,见 pyb.freq() )。

  • sjw 是以时间量计的同步跳转宽度;数值可为1、2、3、4。

  • bs1 以时间量为单位定义了样本点的位置;该数值介于1-1024间。

  • bs2 以时间量为单位定义了传输点的位置;该数值介于1-16间。

  • auto_restart 设置控制器进入bus-off状态后是否自动尝试重启通信;如果禁用,则可以使用 restart() 离开总线关闭状态

  • baudrate 如果提供的波特率不是 0,该函数将尝试自动计算满足波特率和所需 sample_point 的 CAN 位时序(覆盖 prescalerbs1bs2)。

  • sample_point 以位时间的百分比给出,sample_point 指定最后一个位样本相对于整个位时间的位置。默认 sample_point 为 75%。

时间量(tq)是CAN总线的基本时间单位。

一个位是由同步段组成的,通常即为1时间量。然后是位段1,位段2。样本点在位段1结束后。传输点在位段2结束后。波特率是二进时间,位时间即1 + BS1 + BS2与tq的乘积。

使用以下代码计算可以设置:

def get_can_settings(bit_rate, sampling_point):
    clk = 48000000 if omv.board_type() == "H7" else pyb.freq()[2]
    for prescaler in range(8):
        for bs1 in range(16):
            for bs2 in range(8):
                if bit_rate == ((clk >> prescaler) // (1 + bs1 + bs2)) and (sampling_point * 10) == (((1 + bs1) * 1000) // (1 + bs1 + bs2)):
                    return (1 << prescaler, bs1, bs2)
    raise ValueError("Invalid bit_rate and/or sampling_point!")
  • bit_rate - CAN bit rate.

  • sampling_point - Tseg1/Tseg2 ratio. Typically 75%. (50.0, 62.5, 75, 87.5, etc.)

CAN.deinit()

关闭CAN总线。

CAN.restart()

在不重置其配置的情况下强制软件重新启动控制器。

如果控制器进入总线关闭状态,则它将不再参与总线活动。如果未将控制器配置为自动重启( 请参见:meth:~CAN.init()),则可以使用此方法来触发重启,并且控制器将遵循CAN协议以退出总线关闭状态,并且进入错误激活状态。

CAN.state()

返回控制器的状态。返回值可以是:

  • CAN.STOPPED – 控制器完全关闭并复位;

  • CAN.ERROR_ACTIVE – 控制器打开且处于错误激活状态(TEC和REC均小于96);

  • CAN.ERROR_WARNING – 控制器打开且处于错误警告状态(TEC或REC至少一个为96或更高);

  • CAN.ERROR_PASSIVE – 控制器打开并处于错误被动状态(TEC或REC中至少有一个等于或大于128);

  • CAN.BUS_OFF – 控制器打开但未参与总线活动(TEC溢出超过255)。

CAN.info([list])

获取有关控制器的错误状态以及TX和RX缓冲区的信息。如果提供了 list , 则它应该是一个至少包含8个条目的列表对象,并将在其中填充信息。 否则,将创建并填充一个新列表。在两种情况下,方法的返回值都是填充的列表。

列表中的值为:

  • TEC value

  • REC value

  • 控制器进入错误警告状态的次数(65535后环绕为0)

  • 控制器进入错误被动状态的次数(65535后环绕为0)

  • 控制器进入总线关闭状态的次数(65535后环绕为0)

  • 待处理的TX消息数

  • fifo 0上待处理的RX消息数

  • fifo 1上待处理的RX消息数

CAN.setfilter(bank, mode, fifo, params, *, rtr)

配置一个滤波器组:

  • bank 是将被配置的滤波器组。

  • mode 是滤波器运行的模式。

  • fifo 是fifo (0 or 1)信息储存的位置,前提是滤波器接受该信息。

  • params 是一组定义滤波器的值。该组值取决于mode参数。

  • rtr 是一组布尔数组,该数组规定过滤器是否应接受远程传输请求消息。若该参数未给出,则默认所有条目为False。这一数组的长度取决于 mode 参数。

CAN.clearfilter(bank)

清空并禁用一个滤波器组:

  • bank 是将被清空的滤波器组。

CAN.any(fifo)

若有消息在FIFO上等待,则返回 True ;若无,则返回 False

CAN.recv(fifo, *, timeout=5000)

在总线上接收数据:

  • fifo 是一个整数,FIFO即在此接收。

  • list 是一个可选的列表对象,用作返回值

  • timeout 是以毫秒计的等待接收的超时时长。

返回值:包含4个值的元组

  • 消息的id。

  • 一个表明消息是否是RTR消息的布尔值。

  • FMI值(过滤器匹配指数)。

  • 一个包含数据的数组。.

如果*list* 是 None,则将分配一个新的元组以及一个包含数据的新字节对象(作为元组中的第四个元素)。

如果 list 不是 None,那么它应该是一个至少包含四个元素的列表对象。 第四个元素应该是一个memoryview对象,该对象是从字节数组或类型为’B’或’b’的数组创建的, 并且该数组必须有足够的空间来容纳至少8个字节。然后,将使用上面的前三个返回值填充list对象, 然后将memoryview对象的大小调整为数据的大小,并用该数据填充。 相同的列表和memoryview对象可以在对该方法的后续调用中重用,从而提供一种无需使用堆即可接收数据的方法。

例如:

buf = bytearray(8)
lst = [0, 0, 0, memoryview(buf)]
# 在以下调用中未分配堆内存
can.recv(0, lst)
CAN.send(data, id, *, timeout=0, rtr=False)

在总线上发送消息:

  • data 是发送的数据(发送一个整数或一个缓冲区对象)。

  • id 是所发送的消息的id。

  • timeout 是以毫秒计的等待发送的超时时长。

  • rtr 是一个指定消息是否应该作为远程传输请求发送的布尔值。若 rtr 为True ,则只使用 data 长度来填充框架的DLC插槽,

而不使用 data 中的实际字节。

若暂停时间为0,消息则置于三个硬件缓冲区中的其中一个,该方法立即返回。若三个缓冲区都被占用,则会引发异常。若暂停时间不为0,该方法会等待消息传输完毕。若该消息不能在指定时间内传输,则会引发异常。

返回值: None.

CAN.rxcallback(fifo, fun)

当空FIFO接收消息时,注册一个回调函数:

  • fifo 是接收的FIFO。

  • fun 是FIFO变为非空时要调用的函数。

回调函数有两个参数:一个是CAN对象本身,一个是表明回调原因的整数。

回调用法示例:

def cb0(bus, reason):
  print('cb0')
  if reason == 0:
      print('pending')
  if reason == 1:
      print('full')
  if reason == 2:
      print('overflow')

can = CAN(1, CAN.LOOPBACK)
can.rxcallback(0, cb0)

常量

CAN.NORMAL
CAN.LOOPBACK
CAN.SILENT
CAN.SILENT_LOOPBACK

init() 中使用的 CAN 总线模式。

CAN.STOPPED
CAN.ERROR_ACTIVE
CAN.ERROR_WARNING
CAN.ERROR_PASSIVE
CAN.BUS_OFF

返回的控制器的可能状态 state().

CAN.LIST16
CAN.MASK16
CAN.LIST32
CAN.MASK32

setfilter() 中使用的过滤器的操作模式。