133 lines
5.3 KiB
Python
133 lines
5.3 KiB
Python
|
|
"""
|
|||
|
|
Tan mingyan
|
|||
|
|
2026/3/9
|
|||
|
|
|
|||
|
|
CAN 驱动示例(bus_can.py)—— 补充参考
|
|||
|
|
"""
|
|||
|
|
# midware/drivers/bus_can.py
|
|||
|
|
from .base_driver import BaseBusDriver
|
|||
|
|
from typing import Optional, Dict, Any
|
|||
|
|
from loguru import logger
|
|||
|
|
import time
|
|||
|
|
|
|||
|
|
from midware.config.base_config import get_device_config
|
|||
|
|
from .base_driver import BaseBusDriver
|
|||
|
|
from .renode_agent import renode
|
|||
|
|
from midware.config.base_config import DEVICE_CONFIG_DICT
|
|||
|
|
|
|||
|
|
class BusCANDriver(BaseBusDriver):
|
|||
|
|
"""CAN总线驱动实现(适配CANoe/CANalyzer/USB-CAN)"""
|
|||
|
|
def _init_config(self):
|
|||
|
|
self.config.setdefault("channel", 0) # CAN通道
|
|||
|
|
self.config.setdefault("baudrate", 500000) # 500kbps
|
|||
|
|
self.config.setdefault("frame_format", "standard") # 标准帧/扩展帧
|
|||
|
|
logger.info(f"CAN驱动配置初始化完成:{self.config}")
|
|||
|
|
|
|||
|
|
def connect(self) -> bool:
|
|||
|
|
try:
|
|||
|
|
# 实际逻辑:打开CAN通道
|
|||
|
|
time.sleep(0.05)
|
|||
|
|
self.is_connected = True
|
|||
|
|
logger.info("CAN总线连接成功")
|
|||
|
|
return True
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"CAN总线连接失败:{str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def disconnect(self) -> bool:
|
|||
|
|
try:
|
|||
|
|
self.is_connected = False
|
|||
|
|
logger.info("CAN总线断开成功")
|
|||
|
|
return True
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"CAN总线断开失败:{str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def send(self, data: bytes, **kwargs) -> bool:
|
|||
|
|
if not self.is_connected:
|
|||
|
|
logger.error("CAN驱动未连接,发送失败")
|
|||
|
|
return False
|
|||
|
|
# ========== 核心步骤1:从kwargs提取设备名称 ==========
|
|||
|
|
|
|||
|
|
dev_name = kwargs.get("dev_name")#2026/4/10
|
|||
|
|
if not dev_name:
|
|||
|
|
logger.error("CAN发送失败:kwargs中未传入dev_name(设备名称)")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
device_config = get_device_config().get(dev_name)
|
|||
|
|
if not device_config:
|
|||
|
|
logger.error(f"CAN发送失败:设备 {dev_name} 未在DEVICE_CONFIG_DICT中配置")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
frame_id = kwargs.get("frame_id", 0x123) # CAN帧ID
|
|||
|
|
is_extended = kwargs.get("is_extended", False) # 是否扩展帧
|
|||
|
|
logger.info(
|
|||
|
|
f"CAN发送数据|帧ID:0x{frame_id:X}|扩展帧:{is_extended}|"
|
|||
|
|
f"数据:{data.hex()}|长度:{len(data)}字节"
|
|||
|
|
)
|
|||
|
|
# logger.info(
|
|||
|
|
# #f"UART发送数据|帧ID:0x{frame_id:X}|扩展帧:{is_extended}|"
|
|||
|
|
# f"CAN发送数据:{data.hex()}|长度:{len(data)}字节"
|
|||
|
|
# )
|
|||
|
|
## 外设名称+函数名+字符串参数 uart24 WriteRXFIFODataString "0xEB9000C571000827C00000BC1003190000106C02AC020101FF5716"'
|
|||
|
|
|
|||
|
|
## 收到的CAN帧可能是多帧连在一起,需要拆分单帧保证虚拟平台能读取。
|
|||
|
|
frame_len = 11
|
|||
|
|
frame_list = []
|
|||
|
|
total =len(data)
|
|||
|
|
#步长11字节截取完整帧,不满足的丢弃(尾帧长度可以不满11,不丢弃)
|
|||
|
|
end = 0
|
|||
|
|
for start in range(0,total, frame_len):
|
|||
|
|
'''
|
|||
|
|
if end>total:
|
|||
|
|
break
|
|||
|
|
end = start + frame_len
|
|||
|
|
frame_list.append(data[start:end])
|
|||
|
|
sysbus_cmd = f'{dev_name} SendRxBufferDataString "0x{data[start:end].hex()}"'
|
|||
|
|
#print(sysbus_cmd)
|
|||
|
|
logger.info(f"CAN发送指令:{sysbus_cmd}")
|
|||
|
|
response = renode.send_sync(sysbus_cmd)#2026/4/10
|
|||
|
|
time.sleep(0.0001)
|
|||
|
|
'''
|
|||
|
|
#计算当前帧结束的位置
|
|||
|
|
end = min(start + frame_len, total)
|
|||
|
|
frame = data[start:end]
|
|||
|
|
#尾帧长度不足11时,补0到11字节
|
|||
|
|
if len(frame)<frame_len:
|
|||
|
|
#补0
|
|||
|
|
frame = frame.ljust(frame_len, b'\x00')
|
|||
|
|
frame_list.append(frame)
|
|||
|
|
sysbus_cmd = f'{dev_name} SendRxBufferDataString "0x{frame.hex()}"'
|
|||
|
|
logger.info(f"CAN发送指令:{sysbus_cmd}")
|
|||
|
|
response = renode.send_sync(sysbus_cmd,timeout_ms=2)#2026/4/10
|
|||
|
|
# response = renode.enqueue_cmd(sysbus_cmd)#2026/6/4
|
|||
|
|
time.sleep(0.0001)
|
|||
|
|
|
|||
|
|
|
|||
|
|
#sysbus_cmd = f'{dev_name} SendRxBufferDataString "0x{data.hex()}"'
|
|||
|
|
#print(sysbus_cmd)
|
|||
|
|
#logger.info(f"CAN发送指令:{sysbus_cmd}")
|
|||
|
|
#response = renode.send_sync(sysbus_cmd)#2026/4/10
|
|||
|
|
|
|||
|
|
# 实际逻辑:调用CAN驱动发送接口
|
|||
|
|
return True
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"CAN数据发送失败:{str(e)}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def recv(self, timeout: float = 0.1, **kwargs) -> Optional[bytes]:
|
|||
|
|
if not self.is_connected:
|
|||
|
|
logger.error("CAN驱动未连接,接收失败")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# 模拟接收
|
|||
|
|
time.sleep(0.001)
|
|||
|
|
# mock_data = b"\x11\x22\x33\x44"
|
|||
|
|
# logger.debug(f"CAN接收数据:{mock_data.hex()}")
|
|||
|
|
# return mock_data
|
|||
|
|
return None
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"CAN数据接收失败:{str(e)}")
|
|||
|
|
return None
|