.. currentmodule:: pyb .. _pyb.CAN: 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)。 方法 ------- .. method:: 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状态后是否自动尝试重启通信;如果禁用,则可以使用 :meth:`~CAN.restart()` 离开总线关闭状态 - *baudrate* 如果提供的波特率不是 0,该函数将尝试自动计算满足波特率和所需 *sample_point* 的 CAN 位时序(覆盖 *prescaler*、*bs1* 和 *bs2*)。 - *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.) .. method:: CAN.deinit() 关闭CAN总线。 .. method:: CAN.restart() 在不重置其配置的情况下强制软件重新启动控制器。 如果控制器进入总线关闭状态,则它将不再参与总线活动。如果未将控制器配置为自动重启( 请参见:meth:`~CAN.init()`),则可以使用此方法来触发重启,并且控制器将遵循CAN协议以退出总线关闭状态,并且进入错误激活状态。 .. method:: 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)。 .. method:: CAN.info([list]) 获取有关控制器的错误状态以及TX和RX缓冲区的信息。如果提供了 *list* , 则它应该是一个至少包含8个条目的列表对象,并将在其中填充信息。 否则,将创建并填充一个新列表。在两种情况下,方法的返回值都是填充的列表。 列表中的值为: - TEC value - REC value - 控制器进入错误警告状态的次数(65535后环绕为0) - 控制器进入错误被动状态的次数(65535后环绕为0) - 控制器进入总线关闭状态的次数(65535后环绕为0) - 待处理的TX消息数 - fifo 0上待处理的RX消息数 - fifo 1上待处理的RX消息数 .. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr) 配置一个滤波器组: - ``bank`` 是将被配置的滤波器组。 - ``mode`` 是滤波器运行的模式。 - ``fifo`` 是fifo (0 or 1)信息储存的位置,前提是滤波器接受该信息。 - ``params`` 是一组定义滤波器的值。该组值取决于mode参数。 +-----------+---------------------------------------------------------+ |``mode`` |参数数组内容 | +===========+=========================================================+ |CAN.LIST16 |将接受的4个16位id | +-----------+---------------------------------------------------------+ |CAN.LIST32 |将接受的2个32位id | +-----------+---------------------------------------------------------+ |CAN.MASK16 |2个16位id/掩码对。 例:(1, 3, 4, 4) | | | | 第一对,1和3将接受所有的bit 0 = 1和bit 1 = 0的id。 | | | | | | | | 第二对:4和4将接受所有bit 2 = 1的id。 | | | | | +-----------+---------------------------------------------------------+ |CAN.MASK32 |像CAN.MASK16一样,但是只有一个32位id/掩码对。| +-----------+---------------------------------------------------------+ - ``rtr`` 是一组布尔数组,该数组规定过滤器是否应接受远程传输请求消息。若该参数未给出,则默认所有条目为False。这一数组的长度取决于 `mode` 参数。 +-----------+----------------------+ |``mode`` |Rtr数组的长度 | +===========+======================+ |CAN.LIST16 |4 | +-----------+----------------------+ |CAN.LIST32 |2 | +-----------+----------------------+ |CAN.MASK16 |2 | +-----------+----------------------+ |CAN.MASK32 |1 | +-----------+----------------------+ .. method:: CAN.clearfilter(bank) 清空并禁用一个滤波器组: - ``bank`` 是将被清空的滤波器组。 .. method:: CAN.any(fifo) 若有消息在FIFO上等待,则返回 ``True`` ;若无,则返回 ``False`` 。 .. method:: 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) .. method:: CAN.send(data, id, *, timeout=0, rtr=False) 在总线上发送消息: - ``data`` 是发送的数据(发送一个整数或一个缓冲区对象)。 - ``id`` 是所发送的消息的id。 - ``timeout`` 是以毫秒计的等待发送的超时时长。 - ``rtr`` 是一个指定消息是否应该作为远程传输请求发送的布尔值。若 ``rtr`` 为True ,则只使用 ``data`` 长度来填充框架的DLC插槽, 而不使用 ``data`` 中的实际字节。 若暂停时间为0,消息则置于三个硬件缓冲区中的其中一个,该方法立即返回。若三个缓冲区都被占用,则会引发异常。若暂停时间不为0,该方法会等待消息传输完毕。若该消息不能在指定时间内传输,则会引发异常。 返回值: ``None``. .. method:: CAN.rxcallback(fifo, fun) 当空FIFO接收消息时,注册一个回调函数: - ``fifo`` 是接收的FIFO。 - ``fun`` 是FIFO变为非空时要调用的函数。 回调函数有两个参数:一个是CAN对象本身,一个是表明回调原因的整数。 +--------+------------------------------------------------+ | 原因 | | +========+================================================+ | 0 | 空FIFO接收消息。 | +--------+------------------------------------------------+ | 1 | FIFO已满。 | +--------+------------------------------------------------+ | 2 | 由于FIFO已满,消息丢失。 | +--------+------------------------------------------------+ 回调用法示例:: 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) 常量 --------- .. data:: CAN.NORMAL CAN.LOOPBACK CAN.SILENT CAN.SILENT_LOOPBACK :meth:`~CAN.init()` 中使用的 CAN 总线模式。 .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.ERROR_WARNING CAN.ERROR_PASSIVE CAN.BUS_OFF 返回的控制器的可能状态 :meth:`~CAN.state()`. .. data:: CAN.LIST16 CAN.MASK16 CAN.LIST32 CAN.MASK32 :meth:`~CAN.setfilter()` 中使用的过滤器的操作模式。