Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-can

License Go Version Platform

Go语言实现的CAN总线通信库,基于Linux SocketCAN,提供完整的CAN/CAN FD通信功能。

🚀 特性

  • 完整的SocketCAN支持: 基于Linux内核SocketCAN实现
  • CAN FD支持: 支持CAN FD协议,包括BRS和ESI标志
  • 高精度时间戳: 支持软件和硬件时间戳
  • 智能过滤器: 内核级CAN帧过滤,支持精确匹配、范围匹配、掩码匹配
  • 设备管理: 完整的CAN设备配置和管理功能
  • 命令行工具: 兼容can-utils的命令行工具
  • 高性能: 基于系统调用,性能优异
  • 错误处理: 完整的错误帧解析和处理

📋 系统要求

  • Linux系统 (内核支持SocketCAN)

📦 安装

go get github.com/wmem/go-can

🏗️ 项目结构

go-can/
├── pkg/                    # 核心库
│   ├── raw/               # SocketCAN原始接口
│   │   ├── socket.go      # CAN socket实现
│   │   ├── frame.go       # CAN帧处理
│   │   ├── filter.go      # CAN过滤器
│   │   ├── error.go       # 错误帧解析
│   │   └── const.go       # 常量定义
│   └── candevice/         # CAN设备管理
│       ├── device.go      # 设备配置
│       ├── param.go       # 参数管理
│       └── control.go     # 设备控制
├── cmd/                   # 命令行工具
│   ├── candevice/         # 设备配置工具
│   ├── cansend/           # 报文发送工具
│   └── candump/           # 报文接收工具
├── examples/              # 使用示例
└── docs/                  # 文档

🔧 快速开始

基本使用

package main

import (
    "fmt"
    "log"
    "github.com/wmem/go-can/pkg/raw"
)

func main() {
    // 创建CAN socket
    socket, err := raw.New("can0")
    if err != nil {
        log.Fatal(err)
    }
    defer raw.Free(socket)

    // 发送CAN帧
    frame := raw.RawFrameSend{
        ID:         0x123,
        Data:       []byte{0x01, 0x02, 0x03, 0x04},
        IsExtended: false,
        IsRemote:   false,
    }

    err = socket.SendFrame(frame)
    if err != nil {
        log.Fatal(err)
    }

    // 接收CAN帧
    recvFrame, err := socket.RecvFrame()
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("接收到CAN帧: ID=0x%X, 数据=%v\n", recvFrame.ID, recvFrame.Data)
}

CAN FD支持

// 发送CAN FD帧
fdFrame := raw.RawFrameSend{
    ID:     0x123,
    Data:   []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
    IsFD:   true,
    IsBRS:  true,  // 位率切换
    HasESI: false, // 错误状态指示
}

err = socket.SendFrame(fdFrame)

智能过滤器

// 精确匹配过滤器
filters := raw.NewExactFilter(0x123)
socket.SetFilter([]raw.CanFilter{filters})

// 范围过滤器 - 自动拆分为多个2^n对齐的子块
rangeFilters := raw.NewRangeFilter(0x100, 0x130)
socket.SetFilter(rangeFilters)

// 多个过滤器组合
filters := []raw.CanFilter{
    raw.NewExactFilter(0x123),
    raw.NewMaskFilter(0x200, 0xFF00), // 匹配0x200-0x2FF
}
socket.SetFilter(filters)

时间戳功能

frame, err := socket.RecvFrame()
if err == nil {
    // 软件时间戳
    if frame.SoftTime > 0 {
        fmt.Printf("软件时间戳: %.9f秒\n", float64(frame.SoftTime)/1e9)
    }

    // 硬件时间戳
    if frame.HardTime > 0 {
        fmt.Printf("硬件时间戳: %.9f秒\n", float64(frame.HardTime)/1e9)
    }
}

设备管理

package main

import (
    "github.com/wmem/go-can/pkg/candevice"
)

func main() {
    // 创建设备实例
    device, err := candevice.DeviceFromName("can0")
    if err != nil {
        log.Fatal(err)
    }

    // 配置CAN参数
    params := candevice.DeviceParam{
        "bitrate":      500000,
        "sample-point": 0.875,
        "loopback":     false,
        "listen-only":  false,
    }

    err = device.SetParam(params)
    if err != nil {
        log.Fatal(err)
    }

    // 启动接口
    err = device.SetUp()
    if err != nil {
        log.Fatal(err)
    }
}

🛠️ 命令行工具

candevice - CAN设备配置工具

# 显示can0接口信息
candevice -i can0 -show

# 设置can0为500kbps并启动
candevice -i can0 -bitrate 500000 -up

# 设置CAN FD模式
candevice -i can0 -bitrate 500000 -dbitrate 2000000 -fd on -up

# 关闭接口
candevice -i can0 -down

cansend - CAN报文发送工具

# 发送标准帧
cansend can0 123#01020304

# 发送扩展帧
cansend can0 1FFFFFFF#01020304

# 发送CAN FD帧
cansend can0 123##0102030405060708090A

# 发送远程帧
cansend can0 123#R

candump - CAN报文接收工具

# 接收所有报文
candump can0

# 接收100个报文并显示时间戳
candump -t -n 100 can0

# 仅显示错误帧
candump -e can0

# 彩色输出
candump -c can0

📚 API文档

核心类型

// CAN帧发送结构
type RawFrameSend struct {
    ID         uint32 // CAN ID
    Data       []byte // 数据
    IsRemote   bool   // 远程帧
    IsExtended bool   // 扩展帧
    IsFD       bool   // CAN FD帧
    HasESI     bool   // 错误状态指示
    IsBRS      bool   // 位率切换
}

// CAN帧接收结构
type RawFrameRecv struct {
    ID         uint32 // CAN ID
    Data       []byte // 数据
    IsRemote   bool   // 远程帧
    IsExtended bool   // 扩展帧
    IsFD       bool   // CAN FD帧
    HasESI     bool   // 错误状态指示
    IsBRS      bool   // 位率切换
    IsError    bool   // 错误帧
    IsTx       bool   // 发送帧(回环)
    SoftTime   uint64 // 软件时间戳(纳秒)
    HardTime   uint64 // 硬件时间戳(纳秒)
}

// CAN过滤器
type CanFilter struct {
    ID   uint32 // 过滤ID
    Mask uint32 // 过滤掩码
}

主要函数

// 创建CAN socket
func New(ifName string) (*SocketRaw, error)

// 释放CAN socket
func Free(s *SocketRaw)

// 发送CAN帧
func (s *SocketRaw) SendFrame(msg RawFrameSend) error

// 接收CAN帧
func (s *SocketRaw) RecvFrame() (RawFrameRecv, error)

// 设置过滤器
func (s *SocketRaw) SetFilter(filters []CanFilter) error

// 设置超时
func (s *SocketRaw) SetTimeout(ms uint)

// 过滤器创建函数
func NewExactFilter(id uint32) CanFilter
func NewRangeFilter(startID, endID uint32) []CanFilter
func NewMaskFilter(id, mask uint32) CanFilter
func NewAcceptAllFilter() CanFilter

🔮 路线图

  • Raw SocketCAN: 基础CAN通信功能
  • CAN FD: CAN FD协议支持
  • 过滤器: 智能CAN帧过滤
  • 时间戳: 高精度时间戳支持
  • 设备管理: CAN设备配置管理
  • 命令行工具: can-utils兼容工具
  • CAN TP: ISO-TP (ISO 14229-2) 传输协议
  • J1939: SAE J1939 车载网络协议
  • 诊断协议: UDS (ISO 14229) 统一诊断服务
  • 更多协议: CANopen, DeviceNet等

🤝 贡献

欢迎贡献代码!请遵循以下步骤:

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 开启 Pull Request

📄 许可证

本项目采用 MIT 许可证

🙏 致谢

📞 联系

如有问题或建议,请通过以下方式联系:


注意: 本库目前仅支持Linux系统。

About

go实现的linux socket库

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages