gocan

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT Imports: 21 Imported by: 0

README

gocan

Go CAN / CAN FD 多后端库:Windows 支持 PEAK-System PCANBasic、CANable 2.0 SLCAN-FD 与 MiniCANFD,Linux 支持 SocketCAN、SLCAN 和 MiniCANFD。

Go Reference CI CodeQL Go Report Card codecov

gocan 提供统一的 Go Bus API,让程序能在 Windows PCANBasic、CANable 2.0 SLCAN-FD、MiniCANFD 动态库和 Linux SocketCAN 之间复用同一套 CAN / CAN FD 收发逻辑。 Windows PCAN 后端用纯 Go(syscall 调用,无 CGO)封装 PCANBasic.dll;SLCAN 后端直接打开 COMx;Linux 后端使用内核 SocketCAN。

v1.0.0 起,公开 API 遵循语义化版本兼容承诺;破坏性变更只会在新的主版本中发布。


为什么做这个

  • Windows 端 PEAK 官方仅提供 C/C++、C#、Java、Python 等绑定,没有 Go 封装
  • Linux 端事实标准是内核 SocketCAN,接口通常是 can0 / vcan0
  • 现有的 Python 桥接(can-bridge-win)需要打包 PyInstaller、引入 python-can 依赖, 在嵌入到机器人控制等纯 Go 项目时既笨重又难以追踪问题

gocan 的目标是提供稳定的跨平台 CAN 抽象层:Windows 可走 PCANBasic 或 SLCAN, Linux 可走 SocketCAN 或 SLCAN,上层业务尽量只依赖统一的 Bus / Frame API。


特性

  • ✅ Classical CAN 与 CAN FD 双标准支持
  • ✅ 高层 Bus API:Send / SendMany / Receive / ReadOne / TryRead / Status / Reset / SetFilter
  • ✅ 三种接收模式:ModeAuto / ModePolling / ModeEvent(Windows Event 驱动)
  • ✅ 子包 raw:与 PCANBasic C API 1:1 对应的低层绑定
  • ✅ 错误处理:位掩码语义 + errors.Is 哨兵
  • ✅ Linux SocketCAN 后端:Open(SocketCAN("can0")) / OpenFD(SocketCAN("vcan0"), "") / SetFilter
  • ✅ CANable 2.0 SLCAN-FD:OpenSLCAN("COM5", ...) / OpenSLCANFD("COM5", ...)
  • ✅ MiniCANFD 厂商动态库:LookupMiniCANFDDevices / OpenMiniCANFD
  • ✅ SLCAN 多通道合流:BusGroup.AddSLCAN / BusGroup.AddSLCANFD
  • ✅ 通道发现与设备信息:LookupChannels() / GetDeviceInfo()
  • ✅ 完整的中文文档与 15 个示例

详细范围见 设计文档


快速开始

按你的平台跳转:

完整 Option 总览:docs/options.md


通道发现

channels, err := gocan.LookupChannels()
if err != nil {
    log.Fatal(err)
}
for _, ch := range channels {
    info, err := gocan.GetDeviceInfo(ch.Channel)
    if err != nil {
        log.Printf("%s %s: %v", ch.Backend, ch.Name, err)
        continue
    }
    log.Printf("%s %s up=%v fd=%v hardware=%s", info.Backend, info.Name, info.Up, info.FD, info.HardwareName)
}

Linux SocketCAN

bus, err := gocan.Open(gocan.SocketCAN("can0"))
if err != nil {
    log.Fatal(err)
}
defer bus.Close()

CAN FD:

bus, err := gocan.OpenFD(gocan.SocketCAN("vcan0"), "")

Linux 上 bitrate 由系统配置,不由 WithBitrate 设置,例如:

sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up

MiniCANFD 厂商动态库

MiniCANFD 是 USB-CANFD 适配器后端,不会创建 canN 网卡,也不负责识别 L30/O20;上层仍可复用自己的 CAN FD 协议识别逻辑。Linux 使用 libcanbus.so (aarch64 可使用 libcanbus_arm64.so),Windows amd64 使用 HCanbus.dll

devices, err := gocan.LookupMiniCANFDDevices("")
if err != nil {
    log.Fatal(err)
}
bus, err := gocan.OpenMiniCANFD(gocan.MiniCANFDConfig{
    DeviceIndex: devices[0].Index,
    Channel:     0,
    LibraryPath: os.Getenv("MINICANFD_LIBRARY_PATH"),
})

库路径也可通过 MINICANFD_LIBRARY_PATHLINKERBOT_CANFD_LIB 指定。厂商 二进制不随 gocan 发布包提供,需由应用按目标平台分发。

MiniCANFD 的动态库按路径在进程内共享:首次使用时调用厂商 LibCANbus_Init(旧版库未导出该符号时兼容运行),最后一个总线关闭时调用 LibCANbus_Exit。应用重连应完整执行 Bus.Close 后重新调用 LookupMiniCANFDDevices / OpenMiniCANFD,不要只重复 CAN_OpenDeviceBus.Reset 会调用 CAN_Reset 并恢复默认接收全部帧的过滤器。

CANable 2.0 SLCAN-FD

bus, err := gocan.OpenSLCANFD(
    "COM5",
    gocan.SLCANBitrate500K,
    gocan.SLCANDataBitrate2M,
)

该入口使用 CANable 2.0 官方 canable2-fw 的扩展协议,支持 d/D 无 BRS FD 帧、 b/B BRS FD 帧和最大 64 字节载荷。完整说明见 Windows SLCAN-FD 文档

系统要求

  • Windows PCAN:Go 1.22+、已安装 PEAK PCAN 驱动、PCANBasic.dll 与 Go 程序架构匹配
  • Windows SLCAN:Go 1.22+、CANable 2.0 已刷入 SLCAN-FD 固件并出现 COMx
  • Linux:Go 1.22+、内核启用 SocketCAN、已创建并启用 can0 / vcan0 等网络接口
  • macOS:串口 SLCAN 可用于真机;PCAN API 仅提供编译桩

版本状态

版本 主要内容
v1.1.0 MiniCANFD 厂商动态库后端、初始化/退出生命周期、重置与关闭重连契约
v1.0.0 首个稳定版本:PCANBasic、SocketCAN、CANable 2.0 SLCAN-FD、BusGroup、通道发现与跨平台文档

发布说明见 CHANGELOG.md。厂商 .so / .dll 不随 gocan 发布, 由使用 gocan 的应用按目标平台自行分发。


许可证

MIT

Documentation

Overview

Package gocan 是 Go CAN/CAN FD 多后端库。

顶层包提供 idiomatic Go 高层 API(Bus / Frame / Option / Error), 大多数应用直接使用本包即可。Windows 支持 PCANBasic 和 CANable 2.0 SLCAN-FD, Linux 支持 SocketCAN;串口 SLCAN 后端也可在 Linux/macOS 使用。 需要 PCAN 特殊功能或希望进一步定制时,可使用子包 github.com/zhuzx17/gocan/raw。

快速开始

bus, err := gocan.Open(gocan.USBBus1, gocan.WithBitrate(gocan.Baud1M))
if err != nil { log.Fatal(err) }
defer bus.Close()

f, _ := gocan.NewFrame(0x123, []byte{1, 2, 3})
_ = bus.Send(context.Background(), f)

详见 README 与 docs/quickstart-linux.md / docs/quickstart-windows.md。

平台

Windows 真机可使用 PCANBasic 或 SLCAN;Linux 可使用 SocketCAN 或 SLCAN; macOS 可使用串口 SLCAN,PCAN API 在非 Windows 平台是编译桩。

并发

Bus 内部使用单 reader goroutine 独占底层 Read, 调用方可在多个 goroutine 中并发 Send / Status / Reset / Receive; Close 是幂等的。

Index

Constants

View Source
const (
	// MiniCANFDConfig holds the vendor adapter initialization parameters.
	MiniCANFDDefaultNominalBitrate  = 1_000_000
	MiniCANFDDefaultDataBitrate     = 5_000_000
	MiniCANFDDefaultConfig          = 0x07
	MiniCANFDDefaultModel           = 0
	MiniCANFDDefaultCANType         = 1
	MiniCANFDDefaultFrameType       = 0x04
	MiniCANFDMaxDataLength          = 64
	MiniCANFDDefaultTransmitTimeout = 100 * time.Millisecond
	MiniCANFDDefaultReceiveTimeout  = 100 * time.Millisecond
)
View Source
const (
	CANErrTxTimeout = raw.CANErrTxTimeout
	CANErrLostArb   = raw.CANErrLostArb
	CANErrCrtl      = raw.CANErrCrtl
	CANErrProt      = raw.CANErrProt
	CANErrTrx       = raw.CANErrTrx
	CANErrAck       = raw.CANErrAck
	CANErrBusOff    = raw.CANErrBusOff
	CANErrBusError  = raw.CANErrBusError
	CANErrRestarted = raw.CANErrRestarted
	CANErrMaskAll   = raw.CANErrMaskAll
)

CAN 错误帧位掩码(与 raw 包对应常量等价)。

Variables

View Source
var (
	// ErrIDOutOfRange 表示 CAN ID 超出范围(标准 11 位 / 扩展 29 位)。
	ErrIDOutOfRange = errors.New("can: CAN ID out of range")
	// ErrDataTooLong 表示数据长度超过该帧类型允许的最大长度。
	ErrDataTooLong = errors.New("can: data length exceeds capacity")
	// ErrInvalidFDLength 表示 FD 帧 data 长度不在 {0..8, 12, 16, 20, 24, 32, 48, 64} 中。
	ErrInvalidFDLength = errors.New("can: invalid CAN FD data length")
	// ErrRemoteOnFD 表示在 FD 帧上指定了 Remote 标志(FD 协议无 RTR)。
	ErrRemoteOnFD = errors.New("can: remote frame not allowed on CAN FD")
	// ErrBusClosed 表示 Bus 已被关闭,后续操作非法。
	ErrBusClosed = errors.New("can: bus is closed")
	// ErrNotSupported 表示当前平台或后端协议不支持此操作。
	ErrNotSupported = errors.New("can: operation not supported by current backend")
	// ErrDLLNotFound 表示 PCANBasic.dll 加载失败。
	ErrDLLNotFound = errors.New("can: PCANBasic.dll not found or failed to load")
	// ErrFDNotSupportedOnBus 表示在非 FD Bus 上尝试发送 FD 帧。
	ErrFDNotSupportedOnBus = errors.New("can: FD frame requires a bus opened with OpenFD or OpenSLCANFD")
	// ErrSLCANProtocol 表示串口收到的记录不符合 CANable 2.0 SLCAN-FD 格式。
	ErrSLCANProtocol = errors.New("can: malformed SLCAN record")
	// ErrSLCANESINotSupported 表示尝试发送协议无法表达的 ESI 标志。
	ErrSLCANESINotSupported = errors.New("can: CANable SLCAN-FD cannot encode ESI")
)

库内部错误(参数校验、状态等)。

View Source
var (
	// ErrQueueEmpty 表示接收队列暂时为空(TryRead 用)。
	ErrQueueEmpty = errors.New("can: receive queue empty")
	// ErrQueueOverrun 表示接收队列被覆盖(应用读取过慢)。
	ErrQueueOverrun = errors.New("can: receive queue overrun")
	// ErrQueueXmtFull 表示发送队列已满。
	ErrQueueXmtFull = errors.New("can: transmit queue full")
)

队列状态相关错误。

View Source
var (
	ErrBusLight   = errors.New("can: bus light")
	ErrBusHeavy   = errors.New("can: bus heavy")
	ErrBusPassive = errors.New("can: bus passive")
	ErrBusOff     = errors.New("can: bus off")
)

总线状态相关错误(位掩码语义,多个可同时为真)。

View Source
var (
	// ErrNotInitialized 对应 PCAN_ERROR_INITIALIZE:通道未被初始化。
	ErrNotInitialized = errors.New("can: channel not initialized")
	// ErrIllHandle 对应 PCAN_ERROR_ILLHANDLE:非法通道句柄。
	ErrIllHandle = errors.New("can: invalid channel handle")
	// ErrIllParamType 对应 PCAN_ERROR_ILLPARAMTYPE。
	ErrIllParamType = errors.New("can: invalid parameter type")
	// ErrIllParamValue 对应 PCAN_ERROR_ILLPARAMVAL。
	ErrIllParamValue = errors.New("can: invalid parameter value")
	// ErrIllOperation 对应 PCAN_ERROR_ILLOPERATION:非法操作(如平台不支持)。
	ErrIllOperation = errors.New("can: illegal operation")
	// ErrNoDriver 对应 PCAN_ERROR_NODRIVER:驱动未加载。
	ErrNoDriver = errors.New("can: driver not loaded")
	// ErrUnknown 对应 PCAN_ERROR_UNKNOWN。
	ErrUnknown = errors.New("can: unknown error")
)

API / 驱动层错误。

View Source
var (
	// ErrInvalidName 表示 BusGroup.Add 收到的 name 为空字符串。
	ErrInvalidName = errors.New("gocan: invalid bus name")
	// ErrDuplicateName 表示 BusGroup 中已存在同名 Bus。
	ErrDuplicateName = errors.New("gocan: duplicate bus name in group")
)

多 Bus 群组错误。

Functions

func StatusHas

func StatusHas(status, bit Status) bool

StatusHas 判断 status 中是否包含指定的位。

特别处理 StatusOK (0):仅当 status 也是 0 时才算"包含", 否则按位掩码 AND 判断。

Types

type Bitrate

type Bitrate = raw.TPCANBaudrate

Bitrate 是 Classical CAN 波特率的别名。

常用 Classical CAN 波特率。

type Bus

type Bus struct {
	// contains filtered or unexported fields
}

Bus 表示一个已初始化的 CAN/CAN FD 通道。

必须使用 Close 释放资源。Close 是幂等的,可以从多个 goroutine 安全调用。

func Open

func Open(ch Channel, opts ...Option) (*Bus, error)

Open 打开一个 Classical CAN 通道。

ch 是通道句柄(USBBus1..USBBus16 等); opts 用于配置波特率、接收模式、buffer 大小、Logger 等。

func OpenFD

func OpenFD(ch Channel, fdBitrate string, opts ...Option) (*Bus, error)

OpenFD 打开一个 CAN FD 通道。

fdBitrate 是 PCAN 官方格式的字符串,详见 docs/can-fd.md。 WithBitrate 对 OpenFD 无效(FD 波特率完全由 fdBitrate 决定)。

func OpenMiniCANFD added in v1.1.0

func OpenMiniCANFD(cfg MiniCANFDConfig, opts ...Option) (*Bus, error)

OpenMiniCANFD opens and initializes one vendor CAN FD channel.

func OpenSLCAN

func OpenSLCAN(port string, bitrate SLCANBitrate, opts ...Option) (*Bus, error)

OpenSLCAN opens a serial CANable 2.0 using the Classical CAN command set.

func OpenSLCANFD

func OpenSLCANFD(port string, bitrate SLCANBitrate, dataBitrate SLCANDataBitrate, opts ...Option) (*Bus, error)

OpenSLCANFD opens a serial CANable 2.0 with its non-standard SLCAN-FD extensions. The returned Bus accepts both Classical CAN and CAN FD frames.

func (*Bus) Close

func (b *Bus) Close() error

Close 释放底层通道或串口。幂等:多次调用安全。

流程:标记 closed → 关闭 closing → 触发 abort event 唤醒 reader → 等 reader 关闭 rxCh → 释放 event 句柄 → Uninitialize → 关闭 errCh。

func (*Bus) Errors

func (b *Bus) Errors() <-chan error

Errors 返回接收侧的异步错误流。Bus 关闭时 channel 也关闭。 QRCVEMPTY(队列空)不会出现在这里 —— 它是正常状态,不算错误。

func (*Bus) ReadOne

func (b *Bus) ReadOne(ctx context.Context) (Frame, error)

ReadOne 阻塞从接收队列取一帧,直到 ctx 取消或 Bus 关闭。

Bus 关闭时返回 ErrBusClosed。 ctx 被取消时返回 ctx.Err()。

func (*Bus) Receive

func (b *Bus) Receive() <-chan Frame

Receive 返回流式接收 channel。Bus 关闭时 channel 也关闭。

推荐用法:在专门的 goroutine 里 `for f := range bus.Receive()`。

func (*Bus) Reset

func (b *Bus) Reset() error

Reset 复位通道。PCAN/SocketCAN 清空底层收发队列;SLCAN 发送 C/O 重开通道。 通常用于 BUSOFF 恢复。

func (*Bus) ResetFilter

func (b *Bus) ResetFilter() error

ResetFilter 恢复"接收全部"。 实现方式:通过 SetValue(PCAN_MESSAGE_FILTER, PCAN_FILTER_OPEN) 打开滤波器。

func (*Bus) Send

func (b *Bus) Send(ctx context.Context, f Frame) error

Send 同步发送一帧。Close 后调用返回 ErrBusClosed。

ctx 在 Send 入口被一次性检查(Send 自身是同步调用,不会阻塞太久), 真正长时阻塞应通过 SendMany 或上层超时机制控制。

func (*Bus) SendMany

func (b *Bus) SendMany(ctx context.Context, frames []Frame) error

SendMany 顺序逐帧发送,任意一帧失败立即返回 *SendManyError。

已成功发送的帧不会回滚 —— CAN 总线无事务概念。 ctx 在每帧前检查一次,便于及时取消大批量发送。

func (*Bus) SetErrFilter

func (b *Bus) SetErrFilter(mask uint32) error

SetErrFilter 运行期更新 CAN_RAW_ERR_FILTER 掩码。 setsockopt 失败时返回错误,linuxChannel 里持久化的 mask 保持原值(与内核状态一致)。

func (*Bus) SetFilter

func (b *Bus) SetFilter(idMin, idMax uint32, mode FilterMode) error

SetFilter 设置消息过滤范围(PCAN 默认是开放的,本方法用于收窄)。

idMin/idMax 是要接受的 ID 闭区间;mode 区分 11 位 / 29 位 ID。 多次调用会累加:要恢复"接收全部"应调用 ResetFilter。

func (*Bus) SetJoinFilters

func (b *Bus) SetJoinFilters(and bool) error

SetJoinFilters 运行期更新 CAN_RAW_JOIN_FILTERS(true=AND, false=OR)。 setsockopt 失败时返回错误,linuxChannel 里持久化的标志保持原值。

func (*Bus) Status

func (b *Bus) Status() (Status, error)

Status 查询通道当前状态。

返回的 Status 是位掩码,使用 StatusHas 判断具体位。 CANable 2.0 SLCAN-FD 固件不提供可安全用于帧流的状态查询,返回 ErrNotSupported。

func (*Bus) TryRead

func (b *Bus) TryRead() (Frame, error)

TryRead 非阻塞读一帧。队列空时返回 ErrQueueEmpty;Bus 已关闭返回 ErrBusClosed。

type BusGroup

type BusGroup struct {
	// contains filtered or unexported fields
}

BusGroup 管理一组按业务名字索引的 *Bus。 零值不可用,必须通过 NewBusGroup 构造。所有方法并发安全。

func NewBusGroup

func NewBusGroup(outBufferSize int) *BusGroup

NewBusGroup 创建空 group。 outBufferSize 是 Receive 合并 channel 的容量;非正值用默认 1024。

func (*BusGroup) Add

func (g *BusGroup) Add(name string, ch Channel, opts ...Option) (*Bus, error)

Add 打开一个 Classical CAN 通道并以 name 加入 group。

  • name 为空 → ErrInvalidName
  • name 重复 → ErrDuplicateName
  • 底层 Open 失败 → 返回相应错误,group 状态不变
  • group 已 Close → ErrBusClosed

func (*BusGroup) AddFD

func (g *BusGroup) AddFD(name string, ch Channel, fdBitrate string, opts ...Option) (*Bus, error)

AddFD 等价于 Add,但调底层 OpenFD。

func (*BusGroup) AddSLCAN

func (g *BusGroup) AddSLCAN(name, port string, bitrate SLCANBitrate, opts ...Option) (*Bus, error)

AddSLCAN opens a Classical CAN SLCAN serial port and adds it to the group.

func (*BusGroup) AddSLCANFD

func (g *BusGroup) AddSLCANFD(name, port string, bitrate SLCANBitrate, dataBitrate SLCANDataBitrate, opts ...Option) (*Bus, error)

AddSLCANFD opens a CANable 2.0 SLCAN-FD serial port and adds it to the group.

func (*BusGroup) Close

func (g *BusGroup) Close() error

Close 并发关闭所有 Bus,聚合错误。幂等。 关闭顺序:closing → 等所有 fan-in 退出 → Close 每个 Bus → close(out)。 返回非 nil 时一定是 *GroupCloseError。

func (*BusGroup) Each

func (g *BusGroup) Each(fn func(name string, bus *Bus))

Each 在持有读锁下按 Names 顺序遍历每个 Bus。 fn 内禁止调 Add/AddFD/AddSLCAN/AddSLCANFD/Close —— 会死锁,race 模式下会被检测出来。

func (*BusGroup) Get

func (g *BusGroup) Get(name string) (*Bus, bool)

Get 按名字取 Bus;不存在返回 nil, false。

func (*BusGroup) Names

func (g *BusGroup) Names() []string

Names 返回当前 group 内所有 Bus 名字的拷贝(已排序)。

func (*BusGroup) Receive

func (g *BusGroup) Receive() <-chan SourcedFrame

Receive 返回合并接收 channel;group 关闭时该 channel 也关闭。 反压策略:写入 out 阻塞 → 反压回对应 Bus 的 fan-in goroutine (不丢帧;需要更高吞吐时调大 NewBusGroup 的 outBufferSize)。

type Channel

type Channel = raw.TPCANHandle

Channel 是 PCAN 通道句柄的别名,方便 Open 调用。

PCAN-USB 通道常量。重新导出 raw 包的对应值,避免使用者引入 raw 包。

func SocketCAN

func SocketCAN(iface string) Channel

SocketCAN 返回 Linux SocketCAN 网络接口对应的通道句柄。

典型用法:Open(SocketCAN("can0")) 或 OpenFD(SocketCAN("vcan0"), "")。 空接口名会返回 PCAN_NONEBUS,Open/OpenFD 随后会返回参数错误。

type ChannelBackend

type ChannelBackend string

ChannelBackend 表示通道所属的底层后端。

const (
	// BackendPCAN 表示 Windows PCANBasic 后端。
	BackendPCAN ChannelBackend = "pcan"
	// BackendSocketCAN 表示 Linux SocketCAN 后端。
	BackendSocketCAN ChannelBackend = "socketcan"
	// BackendSLCAN 表示串口 SLCAN / CANable 2.0 SLCAN-FD 后端。
	BackendSLCAN ChannelBackend = "slcan"
	// BackendMiniCANFD 表示 MiniCANFD 厂商动态库后端。
	BackendMiniCANFD ChannelBackend = "minicanfd"
)

type ChannelInfo

type ChannelInfo struct {
	Channel Channel
	Name    string
	Backend ChannelBackend
	Up      bool
	FD      bool
}

ChannelInfo 描述一个可尝试打开的 CAN/CAN FD 通道。

func LookupChannels

func LookupChannels() ([]ChannelInfo, error)

LookupChannels 返回当前平台可发现的 CAN/CAN FD 通道。

type DeviceInfo

type DeviceInfo struct {
	Channel          Channel
	Name             string
	Backend          ChannelBackend
	HardwareName     string
	InterfaceName    string
	DeviceNumber     uint32
	ControllerNumber uint32
	Features         uint32
	Up               bool
	FD               bool
}

DeviceInfo 描述一个 CAN/CAN FD 通道对应的设备信息。

func GetDeviceInfo

func GetDeviceInfo(ch Channel) (DeviceInfo, error)

GetDeviceInfo 查询指定通道的设备信息。

type Error

type Error struct {
	Code raw.TPCANStatus // 原始 PCAN 错误位掩码
	Op   string          // 触发错误的操作,如 "CAN_Initialize"
	Msg  string          // 通过 CAN_GetErrorText 取到的可读描述(可能为空)
}

Error 是一次 PCAN API 调用产生的错误。

Code 保留原始的 PCAN 错误位掩码(可能是多个 bit 的 OR 组合), 用 errors.Is(err, ErrXxx) 可精确判断"是否包含某种错误"。

func (*Error) Error

func (e *Error) Error() string

Error 实现 error。

func (*Error) Has

func (e *Error) Has(code raw.TPCANStatus) bool

Has 判断错误码中是否包含某个具体错误位。

特别处理 PCAN_ERROR_OK (0):仅当 e.Code 也是 0 时才算"包含"。 否则按位掩码 AND 判断。

func (*Error) Is

func (e *Error) Is(target error) bool

Is 让一个 *Error 可以同时匹配多个哨兵错误(位掩码语义)。

因为 PCAN 错误码本质是位掩码,单次 API 调用可能同时报告 BUSOFF|QOVERRUN, 此时 errors.Is(err, ErrBusOff) 和 errors.Is(err, ErrQueueOverrun) 都应为 true。

type FilterMode

type FilterMode uint8

FilterMode 用于 SetFilter。

const (
	FilterStandard FilterMode = 0 // 接收 11 位 ID
	FilterExtended FilterMode = 1 // 接收 29 位 ID
)

过滤器模式:区分 11 位 / 29 位 ID。

type Frame

type Frame struct {
	ID    uint32     // CAN 标识符(11 位 / 29 位由 FlagExtended 决定)
	Data  []byte     // 数据载荷
	Flags FrameFlags // 帧类型标志位

	TimestampMicros uint64    // PCAN 提供的微秒时间戳(接收帧才有效)
	ReceivedAt      time.Time // Go 进程接收到该帧的时刻(接收帧才有效)
}

Frame 代表一帧 CAN 报文,统一承载 Classical / Extended / Remote / FD。

通过 Flags 区分帧类型;Data 长度 + Flags 决定底层映射到 TPCANMsg 还是 TPCANMsgFD。 接收到的帧会填充 TimestampMicros(PCAN 自带)和 ReceivedAt(Go 端时刻)。

func NewExtendedFrame

func NewExtendedFrame(id uint32, data []byte) (Frame, error)

NewExtendedFrame 构造一帧扩展 Classical CAN 报文(29 位 ID)。

ID 必须 ≤ 0x1FFFFFFF;data 长度必须 ≤ 8。

func NewFDFrame

func NewFDFrame(id uint32, data []byte, brs, extended bool) (Frame, error)

NewFDFrame 构造一帧 CAN FD 报文。

data 长度必须属于 {0..8, 12, 16, 20, 24, 32, 48, 64}。 brs 控制是否启用加速段;extended 控制是否使用 29 位扩展 ID。 FD 协议无 RTR,因此不允许 Remote 标志。

func NewFrame

func NewFrame(id uint32, data []byte) (Frame, error)

NewFrame 构造一帧标准 Classical CAN 报文(11 位 ID)。

ID 必须 ≤ 0x7FF;data 长度必须 ≤ 8。 data 会被深拷贝,调用者后续修改原切片不影响已构造的 Frame。

func NewRemoteFrame

func NewRemoteFrame(id uint32, dlc uint8, extended bool) (Frame, error)

NewRemoteFrame 构造一帧远程请求帧(Classical CAN 专用)。

dlc 表示请求长度(≤ 8);extended 控制是否使用 29 位扩展 ID。 远程帧没有真实数据,Data 字段会被填充 dlc 个零字节用于标记长度。

func (Frame) Has

func (f Frame) Has(flag FrameFlags) bool

Has 判断 Flags 中是否包含指定位。

type FrameFlags

type FrameFlags uint16

FrameFlags 是 Frame 类型/属性位的组合。

const (
	FlagExtended FrameFlags = 1 << iota // 29 位扩展 ID
	FlagRemote                          // 远程帧(仅 Classical CAN)
	FlagFD                              // CAN FD 帧
	FlagBRS                             // FD 加速段(仅 FD 帧有意义)
	FlagESI                             // FD 错误状态指示(仅 FD 帧有意义)
)

Frame 标志位常量。

type GroupCloseError

type GroupCloseError struct {
	Causes map[string]error
}

GroupCloseError 聚合 BusGroup.Close 时多个 Bus 的失败。

Causes 按名字索引每个失败 Bus 的错误;成功关闭的 Bus 不出现在 map 中。 errors.Is 会按 Causes 逐个尝试匹配,因此可以 errors.Is(err, ErrBusClosed) 等。

func (*GroupCloseError) Error

func (e *GroupCloseError) Error() string

Error 实现 error。

func (*GroupCloseError) Unwrap

func (e *GroupCloseError) Unwrap() []error

Unwrap 返回所有底层错误,便于 errors.Is/errors.As 穿透。

type Logger

type Logger interface {
	Debugf(format string, args ...any)
	Infof(format string, args ...any)
	Warnf(format string, args ...any)
}

Logger 是本库内部使用的极简日志接口。

默认使用 noopLogger(什么都不打印)。如需接入 slog/zap/logrus, 实现下面三个方法并通过 WithLogger 注入即可。

接口故意保持最小:库本身只在少数地方打 Debug/Info/Warn 日志, 不输出 Error 级(错误通过 *Error/Errors() 返回给调用方)。

type MiniCANFDConfig added in v1.1.0

type MiniCANFDConfig struct {
	DeviceIndex  int
	ChannelIndex int
	// Channel is an alias for ChannelIndex kept for callers that use the
	// vendor SDK's shorter terminology. When non-zero and ChannelIndex is zero,
	// Channel is used.
	Channel     int
	NominalRate uint32
	DataRate    uint32
	Config      uint8
	Model       uint8
	CANType     uint8
	FrameType   uint8
	LibraryPath string
}

MiniCANFDConfig describes one channel of a MiniCANFD vendor adapter. The dynamic library is loaded on demand and is never unloaded while the process is running, because vendor libraries may retain global USB state.

type MiniCANFDDeviceInfo added in v1.1.0

type MiniCANFDDeviceInfo struct {
	Index           int
	HardwareType    string
	SerialNumber    string
	HardwareVersion string
	FirmwareVersion string
	ManufactureDate string
}

MiniCANFDDeviceInfo describes an adapter returned by CAN_ReadDevInfo. It identifies the USB-CANFD adapter, not a L30/O20 device on the bus.

func LookupMiniCANFDDevices added in v1.1.0

func LookupMiniCANFDDevices(libraryPath string) (devices []MiniCANFDDeviceInfo, err error)

LookupMiniCANFDDevices loads the vendor library and returns all scanned adapter indices. Device metadata is read when the vendor API provides it.

type Option

type Option func(*config)

Option 用于配置 Open / OpenFD。

func WithBitrate

func WithBitrate(b Bitrate) Option

WithBitrate 设置 Classical CAN 波特率,默认 Baud1M。

OpenFD 时此选项被忽略 —— FD 波特率由 OpenFD 的 fdBitrate 字符串决定。

func WithErrBufferSize

func WithErrBufferSize(n int) Option

WithErrBufferSize 设置错误 channel 容量,默认 16。 非正值会被忽略并保留默认。

func WithErrFilter

func WithErrFilter(mask uint32) Option

WithErrFilter 启用 CAN_RAW_ERR_FILTER,只接收 mask 中位标记的错误帧类型。 参见 raw/can_err_linux.go 中的 CANErr* 常量。

func WithJoinFilters

func WithJoinFilters(and bool) Option

WithJoinFilters 设置 CAN_RAW_JOIN_FILTERS 语义: true 表示多个 SetFilter 范围必须**全部**匹配(AND);false / 默认是任一匹配(OR)。 内核 < 4.1 不支持,setsockopt 会返回 ENOPROTOOPT;调用 Open 时会返回包含 PCAN_ERROR_ILLPARAMVAL 的 *Error,提示需要 ≥ 4.1。

func WithLogger

func WithLogger(l Logger) Option

WithLogger 注入日志接口。默认 noopLogger 不打印任何东西。 传入 nil 会被忽略。

func WithLoopback

func WithLoopback(enabled bool) Option

WithLoopback 设置 CAN_RAW_LOOPBACK(默认内核为 true,即本地回环开启)。 关闭后,本进程发出的帧不会被同主机其他 socket 看到。

func WithPollInterval

func WithPollInterval(d time.Duration) Option

WithPollInterval 设置 Polling 模式下的轮询间隔,默认 1ms。

非正值(≤0)会被忽略并保留默认。 仅 ModePolling(或 ModeAuto 降级到 Polling)时生效。

func WithRWTimeout

func WithRWTimeout(read, write time.Duration) Option

WithRWTimeout 设置 SO_RCVTIMEO / SO_SNDTIMEO。零值表示该方向不设超时。 注意:当前 reader goroutine 用 polling 循环 + 短读,超时通常无显著影响; 主要用于 SocketCAN 在某些场景下避免 read() 永远阻塞。

func WithReceiveMode

func WithReceiveMode(m ReceiveMode) Option

WithReceiveMode 设置接收模式,默认 ModeAuto。

func WithRecvOwnMsgs

func WithRecvOwnMsgs(enabled bool) Option

WithRecvOwnMsgs 设置 CAN_RAW_RECV_OWN_MSGS。开启后会收到本 socket 自己发出的帧 (需配合 WithLoopback(true);通常用于自发自收的回归测试)。

func WithRecvTimestamp

func WithRecvTimestamp(mode RxTimestamp) Option

WithRecvTimestamp 启用内核接收时间戳,结果写入 Frame.TimestampMicros。 不传该 Option 时保持现有行为:SocketCAN 后端用 time.Now() 合成时间戳。

func WithRxBufferSize

func WithRxBufferSize(n int) Option

WithRxBufferSize 设置接收 channel 容量,默认 1024。 非正值会被忽略并保留默认。

func WithSLCANAutoRetransmit

func WithSLCANAutoRetransmit(enabled bool) Option

WithSLCANAutoRetransmit controls automatic retransmission. It defaults to on.

func WithSLCANSerialBaud

func WithSLCANSerialBaud(baud int) Option

WithSLCANSerialBaud sets the host serial line rate. CANable 2.0 uses USB CDC and normally ignores this value; 115200 is used by default.

func WithSLCANSilent

func WithSLCANSilent(enabled bool) Option

WithSLCANSilent selects listen-only mode before the CAN channel is opened.

func WithSocketBuffers

func WithSocketBuffers(rcvBytes, sndBytes int) Option

WithSocketBuffers 设置 SO_RCVBUF / SO_SNDBUF。任一非正值则跳过对应方向。 实际生效值受内核 net.core.rmem_max / wmem_max 上限限制。

type ReceiveMode

type ReceiveMode int

ReceiveMode 控制 Bus 内部 reader goroutine 的等待策略。

const (
	// ModeAuto:Windows + 驱动支持事件 → Event;否则退回 Polling。
	// 库的默认模式:兼顾延迟与可移植性。
	ModeAuto ReceiveMode = iota
	// ModePolling:以 WithPollInterval 设定的间隔轮询底层。
	ModePolling
	// ModeEvent:Windows Event Handle 阻塞等待,CPU 占用最低。
	ModeEvent
)

接收模式常量。

type RxTimestamp

type RxTimestamp uint8

RxTimestamp 选择内核给入帧打时间戳的机制。 默认 RxTimestampNone 不启用;启用时 Frame.TimestampMicros 由内核提供。

const (
	RxTimestampNone     RxTimestamp = 0
	RxTimestampSecond   RxTimestamp = 1 // SO_TIMESTAMP(μs 精度)
	RxTimestampNano     RxTimestamp = 2 // SO_TIMESTAMPNS(ns 精度)
	RxTimestampHardware RxTimestamp = 3 // SO_TIMESTAMPING + RX_HARDWARE,不支持时降级到 NS
)

type SLCANBitrate

type SLCANBitrate uint8

SLCANBitrate is one of the nominal bitrate presets implemented by the CANable 2.0 SLCAN-FD firmware.

const (
	SLCANBitrate10K SLCANBitrate = iota
	SLCANBitrate20K
	SLCANBitrate50K
	SLCANBitrate100K
	SLCANBitrate125K
	SLCANBitrate250K
	SLCANBitrate500K
	SLCANBitrate750K
	SLCANBitrate1M
	SLCANBitrate83K3
)

type SLCANDataBitrate

type SLCANDataBitrate uint8

SLCANDataBitrate is a CAN FD data-phase bitrate preset implemented by the CANable 2.0 firmware.

const (
	SLCANDataBitrate2M SLCANDataBitrate = 2
	SLCANDataBitrate5M SLCANDataBitrate = 5
)

type SLCANPortInfo

type SLCANPortInfo struct {
	Name         string
	VID          string
	PID          string
	SerialNumber string
	Product      string
	CANable2     bool
}

SLCANPortInfo describes a USB serial port that can be passed to OpenSLCAN or OpenSLCANFD. CANable2 is true for the official firmware VID:PID 16D0:117E.

func LookupSLCANPorts

func LookupSLCANPorts() ([]SLCANPortInfo, error)

LookupSLCANPorts enumerates USB serial ports, including Windows COM ports. It does not hide non-CANable devices so callers can also use compatible SLCAN-FD firmware with a different USB identifier.

type SendManyError

type SendManyError struct {
	Index int   // 失败的帧下标
	Frame Frame // 失败的帧本身(深拷贝)
	Err   error // 底层错误
}

SendManyError 标识 SendMany 中第 Index 帧(0-based)发送失败。

Frame 是失败帧的深拷贝,调用方可安全持有以供日志或重试使用。 已成功发送的帧不会回滚(CAN 总线无事务概念)。

func (*SendManyError) Error

func (e *SendManyError) Error() string

Error 实现 error。

func (*SendManyError) Unwrap

func (e *SendManyError) Unwrap() error

Unwrap 让 errors.Is/errors.As 可以穿透到内部错误。

type SourcedFrame

type SourcedFrame struct {
	Source string
	Frame  Frame
}

SourcedFrame 是 BusGroup.Receive 返回的合流帧, 把帧和发出它的 Bus 名字打包在一起。

type Status

type Status = raw.TPCANStatus

Status 是 PCAN 通道当前状态的位掩码值。

直接 alias raw.TPCANStatus 以保证与官方常量值一致; 与 *Error.Code 是同一底层类型,便于互操作。

const (
	StatusOK           Status = raw.PCAN_ERROR_OK
	StatusBusLight     Status = raw.PCAN_ERROR_BUSLIGHT
	StatusBusHeavy     Status = raw.PCAN_ERROR_BUSHEAVY
	StatusBusPassive   Status = raw.PCAN_ERROR_BUSPASSIVE
	StatusBusOff       Status = raw.PCAN_ERROR_BUSOFF
	StatusQueueOverrun Status = raw.PCAN_ERROR_QOVERRUN
)

通道状态常量。注意这些是位掩码,可以多个同时置位(如 BUSOFF|QOVERRUN)。

Directories

Path Synopsis
examples
04_send_fd command
05_receive_fd command
07_filter command
09_with_logger command
10_using_raw command
15_canable_slcan_fd command
示例 15:Windows 上通过 CANable 2.0 SLCAN-FD 固件发送一帧 CAN FD。
示例 15:Windows 上通过 CANable 2.0 SLCAN-FD 固件发送一帧 CAN FD。
Package raw 提供 PCANBasic.dll C API 的零开销 Go 绑定。
Package raw 提供 PCANBasic.dll C API 的零开销 Go 绑定。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL