CAN类——控制器局域网通信总线

CAN 实现了标准的 CAN 通信协议。在物理层,它由 2 条线组成:RX 和 TX。请注意,要将 pyboard 连接到 CAN 总线,您必须使用 CAN 收发器将来自 pyboard 的 CAN 逻辑信号转换为总线上正确的电压电平。

示例用法(无需任何连接即可工作):

from pyb import CAN
can = CAN(1, CAN.LOOPBACK)
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))  # set a filter to receive messages with id=123, 124, 125 and 126
can.send('message!', 123)   # send a message with id 123
can.recv(0)                 # receive message on FIFO 0

构造函数

class pyb.CAN(bus, ...)

在给定的总线上构造一个 CAN 对象。 总线可以是 1-2,或'YA''YB'。没有附加参数,CAN 对象被创建但不初始化(它具有总线上次初始化的设置,如果有的话)。如果给出了额外的参数,则总线被初始化。参见CAN.init() 初始化参数。

CAN 总线的物理引脚为:

  • CAN(1)YA: (RX, TX) = (Y3, Y4) = (PB8, PB9)

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

类方法

classmethod CAN.initfilterbanks(nr)

重置并禁用所有滤波器组并分配应可用于 CAN(1) 的组数。

STM32F405 有 28 个滤波器组,它们在两个可用的 CAN 总线控制器之间共享。此功能配置应为每个滤波器组分配多少个滤波器组。nr是将分配给 CAN(1) 的 bank 数,其余 28 个分配给 CAN(2)。启动时,每个控制器分配了 14 个组。

方法

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 之间(包括 1 和 1024)

  • bs2以时间量子为单位定义发射点的位置;它可以在 1 到 16 之间(包括 1 和 16)

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

  • 波特率如果设置为0以外的波特率,该功能将尝试自动计算CAN位定时(覆盖预分频器,BS1和BS2)同时满足波特率和所需sample_point。

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

时间量 tq 是 CAN 总线的基本时间单位。tq 为 CAN 预分频器值除以 PCLK1(内部外设总线 1 的频率);参见pyb.freq() 确定 PCLK1。

单个位由同步段组成,始终为 1 tq。然后是位段 1,然后是位段 2。采样点在位段 1 结束之后。传输点在位段 2 完成之后。波特率为 1/位时间,其中位时间为 1 + BS1 + BS2 乘以时间量 tq。

例如,PCLK1=42MHz,prescaler=100,sjw=1,bs1=6,bs2=8,tq的值为2.38微秒。位时间为 35.7 微秒,波特率为 28kHz。

有关更多详细信息,请参阅 STM32F405 数据表的第 680 页。

CAN.deinit()

关闭 CAN 总线。

CAN.restart()

强制软件重启 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 缓冲区的信息。如果列表被提供,那么它应该是具有至少8个条目,这将在与该信息来填充一个列表对象。否则将创建并填充一个新列表。在这两种情况下,该方法的返回值都是填充的列表。

列表中的值是:

  • TEC值

  • REC值

  • 控制器进入错误警告状态的次数(在 65535 之后回绕到 0)

  • 控制器进入错误被动状态的次数(在 65535 之后回绕到 0)

  • 控制器进入总线关闭状态的次数(在 65535 之后回绕到 0)

  • 待处理的 TX 消息数

  • fifo 0 上未决 RX 消息的数量

  • fifo 1 上未决 RX 消息的数量

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

配置滤波器组:

  • bank是要配置的滤波器组。

  • mode是过滤器应该运行的模式。

  • FIFO是一种先进先出(0或1)的消息应当被存储在,如果它是由该过滤器接受。

  • params是定义过滤器的值数组。数组的内容取决于模式参数。

模式

params数组的内容

CAN.LIST16

将被接受的四个 16 位 ID

CAN.LIST32

将被接受的两个 32 位 ID

CAN.MASK16

两个 16 位 ID/掩码对。例如 (1, 3, 4, 4)
第一对,1 和 3 将接受所有 ID
位 0 = 1 和位 1 = 0。
第二对,4 和 4,将接受所有 ID
位 2 = 1。

CAN.MASK32

与 CAN.MASK16 一样,但只有一对 32 位 ID/掩码。

  • rtr是一个布尔数组,用于说明过滤器是否应接受远程传输请求消息。如果未给出此参数,则默认False为所有条目。数组的长度取决于模式参数。

模式

rtr数组的长度

CAN.LIST16

4

CAN.LIST32

2

CAN.MASK16

2

CAN.MASK32

1

CAN.clearfilter(bank)

清除并禁用滤波器组:

  • bank是要清除的滤波器组。

CAN.any(fifo)

True 如果有任何消息在 FIFO 上等待,则返回,否则返回False

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

在总线上接收数据:

  • fifo是一个整数,它是要接收的 FIFO

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

  • timeout 是等待接收的超时时间(以毫秒为单位)。

返回值:包含四个值的元组。

  • 消息的 ID。

  • 指示消息是否为 RTR 消息的布尔值。

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

  • 包含数据的数组。

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

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

buf = bytearray(8)
lst = [0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
CAN.send(data, id, *, timeout=0, rtr=False)

在公交车上发送消息:

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

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

  • timeout 是等待发送的超时时间(以毫秒为单位)。

  • rtr 是一个布尔值,指定消息是否应作为远程传输请求发送。如果rtr为 True,则仅使用数据长度来填充帧的 DLC 插槽;数据中的实际字节未使用。

如果 timeout 为 0,则消息被放置在三个硬件缓冲区之一的缓冲区中,并且该方法立即返回。如果所有三个缓冲区都在使用中,则会引发异常。如果 timeout 不为 0,则该方法等待直到消息被传输。如果无法在指定时间内传输消息,则会引发异常。

返回值: None.

CAN.rxcallback(fifo, fun)

注册一个函数,当一个消息被接受到一个空的 fifo 时被调用:

  • fifo 是接收 fifo。

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

回调函数有两个参数,第一个是它自己的 can 对象,第二个是指示回调原因的整数。

原因

0

一条消息已被接收到一个空的 FIFO 中。

1

FIFO 已满

2

由于 FIFO 已满,消息已丢失

rxcallback 的使用示例:

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

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

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

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

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

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