Python学习--Python_can

01模块简介

python-can库为Python提供控制器局域网支持 ,为不同的硬件设备提供通用抽象,以及一套用于在 CAN 总线上发送和接收消息的实用程序

import can
 8
 9
10def send_one():
11    """Sends a single message."""
12
13    # this uses the default configuration (for example from the config file)
14    # see https://python-can.readthedocs.io/en/stable/configuration.html
15    with can.interface.Bus() as bus:
16
17        # Using specific buses works similar:
18        # bus = can.interface.Bus(bustype='socketcan', channel='vcan0', bitrate=250000)
19        # bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
20        # bus = can.interface.Bus(bustype='ixxat', channel=0, bitrate=250000)
21        # bus = can.interface.Bus(bustype='vector', app_name='CANalyzer', channel=0, bitrate=250000)
22        # ...
23
24        msg = can.Message(
25            arbitration_id=0xC0FFEE, data=[0, 25, 0, 1, 3, 1, 4, 1], is_extended_id=True
26        )
27
28        try:
29            bus.send(msg)
30            print(f"Message sent on {bus.channel_info}")
31        except can.CanError:
32            print("Message NOT sent")
33
34
35if __name__ == "__main__":
36    send_one()

bustype的类型一共有四种:

        1)socketcan  对应的channel 为:vcan0

                SocketCAN

        2)ixxat 对应的channel为:0

                IXXAT Virtual CAN Interface

        3)pcan 对应的channel为PCAN_USBBUS1

                PCAN Basic API

        4)vector 对应的channel为0,需要额外增加一个app_name 为CANalyzer

                Vector

        5)。。。python-can库基于PCAN-USB使用方法

总线的比特率咱们自己是500ms

02准备的环境

1)Python安装:https://www.python.org/ftp/python/3.7.9/python-3.7.9-amd64.exe

2)PCAN-USB驱动:Home: PEAK-System

3)库:pip install python-can

参考文档:python-can — python-can 4.0.0 documentation

03PCAN默认配置API

1)interface = pcan

2)channel = PCAN_USBBUS1    

3)state = can.bus.BusState.ACTIVE

4)bitrate = 500000

class PcanBus(BusABC):
    def __init__(
        self,
        channel="PCAN_USBBUS1",
        state=BusState.ACTIVE,
        bitrate=500000,
        *args,
        **kwargs,
    ):

04PCAN可用参数

1)channel(通道)

:param str channel:
    The can interface name. An example would be 'PCAN_USBBUS1'.
    Alternatively the value can be an int with the numerical value.
    Default is 'PCAN_USBBUS1'

2)BusState(总线状态)

:param can.bus.BusState state:
    BusState of the channel.
    Default is ACTIVE

3)bitrate(比特率,非CANFD)

:param int bitrate:
    Bitrate of channel in bit/s.
    Default is 500 kbit/s.
    Ignored if using CanFD.

3)fd(布尔类型,判断是否为CANFD)

:param bool fd:
    Should the Bus be initialized in CAN-FD mode.

4)f_clock(时钟频率HZ,非CANFD)

:param int f_clock:
    Clock rate in Hz.
    Any of the following:
    20000000, 24000000, 30000000, 40000000, 60000000, 80000000.
    Ignored if not using CAN-FD.
    Pass either f_clock or f_clock_mhz.

5)f_clock——mhz(时钟频率MHZ,非CANFD)

:param int f_clock_mhz:
    Clock rate in MHz.
    Any of the following:
    20, 24, 30, 40, 60, 80.
    Ignored if not using CAN-FD.
    Pass either f_clock or f_clock_mhz.

05接收报文

from can.interfaces.pcan.pcan import PcanBus
 
def bus_recv():
    """轮询接收消息"""
    try:
        while True:
            msg = bus.recv(timeout=100)
            print(msg)
    except KeyboardInterrupt:
        pass
 
if __name__ == '__main__':
    bus = PcanBus(channel='PCAN_USBBUS1', bitrate=500000)
    bus_recv()

用到的类:

        1)bus.recv

def  recv ( self, timeout :  Optional [ float ]  =  None )  ->  Optional [ Message ]: 
        """阻塞等待来自总线的消息。

        :param timeout:
            等待消息的秒数或无无限期等待

        :return: ``None`` 超时或 :class:`Message` 对象。
        """
        can.CanOperationError # 读取时发生错无的错误类型

 06发送报文

from can.interfaces.pcan.pcan import PcanBus
 
def bus_send():
    """can消息发送"""
    while True:
        time.sleep(0.02)
        try:
            bus.send(msg)
            print("消息发送 {}".format(bus.channel_info))
        except can.CanError:
            print("消息未发送")
 
if __name__ == '__main__':
    msg = can.Message(arbitration_id=0x181DFF00, data=[0xEE, 0xFE, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE],
                      is_extended_id=True)  # 报文
    bus = PcanBus(channel='PCAN_USBBUS1', bitrate=500000)
    bus_send()

用到的类:

1)bus.send()

def  send ( self ,  msg :  Message ,  timeout :  Optional [ float ]  =  None )  ->  None : 
        """向 CAN 总线发送消息。

        覆盖此方法以启用传输路径。

        :param Message msg:一个消息对象。

        :param timeout:
            如果 > 0,则等待这么多秒,以便消息被 ACK 或
            传输队列准备好,具体取决于驱动程序实现。
            如果超时,将引发异常。
            可能并非所有接口都支持。
            无无限期阻塞。

        :raises can.CanOperationError: If an error occurred while sent 
        """ 
        raise  NotImplementedError ( " Trying to write to a readonly bus?" )

07定期发送报文

def bus_send_periodic():
    """周期发送报文"""
    print("开始每200毫秒发送一条消息。持续时间10s")
    task = bus.send_periodic(msg, 1.5)  # 定期发送
    if not isinstance(task, can.ModifiableCyclicTaskABC):  # 断言task类型
        print("此接口似乎不支持")
        task.stop()
        return
    time.sleep(5)  # 持续时间
    print("发送完成")
    print("更改运行任务的数据以99开头")
    msg.data[0] = 0x99
    task.modify_data(msg)  # 修改data首字节
    time.sleep(10)
 
    task.stop()
    print("停止循环发送")
    print("将停止任务的数据更改为单个 ff 字节")
    msg.data = bytearray([0xff])  # 重新定向data

用到的类:

081)bus.send_periodic()

    def send_periodic(
        self,
        msgs: Union[Message, Sequence[Message]],
        period: float,
        duration: Optional[float] = None,
        store_task: bool = True,
    ) -> can.broadcastmanager.CyclicSendTaskABC:

        :param msgs:
            要传输的消息
        :param period:
            每条消息之间的周期(以秒为单位) 
        :param duration:
            继续发送消息的近似持续时间(以秒为单位)。如果
            没有提供持续时间,则任务将无限期地继续。
        :param store_task:
            如果为 True(默认值),任务将附加到此 Bus 实例。
            禁用改为手动管理任务。
        :return:
            一个启动的任务实例。

 08循环收发消息

from can.interfaces.pcan.pcan import PcanBus
 
def send_cyclic(stop_event):
    """循环发送消息"""
    print("开始每1秒发送1条消息")
    start_time = time.time()
    while not stop_event.is_set():
        msg.timestamp = time.time() - start_time
        bus.send(msg)
        print(f"tx: {msg}")
        time.sleep(1)
    print("停止发送消息")
 
def receive(stop_event):
    """循环接收消息"""
    print("开始接收消息")
    while not stop_event.is_set():
        rx_msg = bus.recv(1)
        if rx_msg is not None:
            print(f"rx: {rx_msg}")
    print("停止接收消息")
 
def send_and_recv_msg():
    """发送一个消息并接收一个消息,需要双通道CAN"""
    stop_event = threading.Event()
    t_send_cyclic = threading.Thread(target=send_cyclic, args=(stop_event,))
    t_receive = threading.Thread(target=receive, args=(stop_event,))
    t_receive.start()
    t_send_cyclic.start()
    try:
        while True:
            time.sleep(0)  # yield
    except KeyboardInterrupt:
        pass  # 正常退出
    stop_event.set()
    time.sleep(0.5)
 
if __name__ == '__main__':
    msg = can.Message(arbitration_id=0x181DFF00, data=[0xEE, 0xFE, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE],
                      is_extended_id=True)  # 报文
    bus = PcanBus(channel='PCAN_USBBUS1', bitrate=500000)
    send_and_recv_msg()

09常用方法

can.message(timestamp=0.0,                            //时间戳

                        arbitration_id=0,                         //报文id

                        is_extended_id=True,                 //是否为扩展帧

                        is_remote_frame=False,             //是否为远程帧

                        is_error_frame=False,                //是否为错误帧

                        channel=None,                           //通道

                        dlc=None,                                   //dlc大小

                        data=None,                                 //数据

                        is_fd=False,                                 //是否为canfd

                        is_rx=True,                                  //是否为接收帧

                        bitrate_switch=False,                  //比特率开关

                        error_state_indicator=False,       

                        check=False)                       

                

  • 1
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值