btm can-net 透传协议

This commit is contained in:
xzb 2023-11-21 17:20:03 +08:00
parent eb13545d55
commit 2be3990983
7 changed files with 199 additions and 141 deletions

View File

@ -30,36 +30,6 @@ type CanFrameId struct {
ID4 byte
}
func (f *CanFrameId) Encode(bits CanBitsWriter) {
bits.AddByte(f.ID1)
bits.AddByte(f.ID2)
bits.AddByte(f.ID3)
bits.AddBits(f.ID4, 5)
}
func (f *CanFrameId) Decode(bits CanBitsReader) bool {
if id, ok := bits.ReadByte(); ok {
f.ID1 = id
} else {
return false
}
if id, ok := bits.ReadByte(); ok {
f.ID2 = id
} else {
return false
}
if id, ok := bits.ReadByte(); ok {
f.ID3 = id
} else {
return false
}
if id, ok := bits.ReadBits(5); ok {
f.ID4 = id
} else {
return false
}
return true
}
// NewCanFrameId 创建CAN串行总线帧ID
// dstAddr 目的设备地址
// srcAddr 源设备地址
@ -102,10 +72,11 @@ func NewAtpRequestFrame(sn byte) *AtpRequestFrame {
FId: *NewCanFrameId(CAN_ADDR_REQ_BTM, CAN_ADDR_REQ_ATP, CAN_FRAME_ATP_REQ, sn),
}
}
func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool {
if !f.FId.Decode(bits) {
return false
}
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
bits := NewCanBitsReader(cf.CanData, 8)
//
if d, ok := bits.ReadBits(1); ok {
f.PowerAmplifierTurnOn = d == 1
} else {
@ -188,10 +159,14 @@ func (f *AtpRequestFrame) Decode(bits CanBitsReader) bool {
//
return true
}
func (f *AtpRequestFrame) Encode() CanBusData {
bits := NewCanBitsWriter(12)
func (f *AtpRequestFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(bits)
bits := NewCanBitsWriter(8)
//
if f.PowerAmplifierTurnOn {
bits.AddBits(1, 1)
@ -223,5 +198,7 @@ func (f *AtpRequestFrame) Encode() CanBusData {
bits.AddByte(byte(crc16 >> 8))
bits.AddByte(byte(crc16))
//
return bits.(CanBusData)
cf.CanData = bits.(CanBusData).GetData()
//
return cf
}

View File

@ -16,20 +16,26 @@ func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
}
}
func (f *BtmDataMessageFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
func (f *BtmDataMessageFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(writer)
writer := NewCanBitsWriter(8)
//
for _, data := range f.Message {
writer.AddByte(data)
}
return writer.(CanBusData)
}
func (f *BtmDataMessageFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
cf.CanData = writer.(CanBusData).GetData()
//
return cf
}
func (f *BtmDataMessageFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//
f.Message = make([]byte, 0, 8)
for c := 0; c < 8; c++ {
@ -61,10 +67,14 @@ func NewBtmDataMessageTimeAFrame(sn byte) *BtmDataMessageTimeAFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
}
}
func (f *BtmDataMessageTimeAFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(writer)
writer := NewCanBitsWriter(8)
//
byteMsk := uint32(0x00_00_00_ff)
//
@ -78,13 +88,15 @@ func (f *BtmDataMessageTimeAFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32A >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32A & byteMsk))
//
return writer.(CanBusData)
cf.CanData = writer.(CanBusData).GetData()
//
return cf
}
func (f *BtmDataMessageTimeAFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
}
func (f *BtmDataMessageTimeAFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//
f.TimeA = 0
a1, a1Ok := reader.ReadByte()
@ -157,10 +169,14 @@ func NewBtmDataMessageTimeBFrame(sn byte) *BtmDataMessageTimeBFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn),
}
}
func (f *BtmDataMessageTimeBFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(writer)
writer := NewCanBitsWriter(8)
//
byteMsk := uint32(0x00_00_00_ff)
//
@ -174,12 +190,14 @@ func (f *BtmDataMessageTimeBFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32B >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32B & byteMsk))
//
return writer.(CanBusData)
}
func (f *BtmDataMessageTimeBFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
cf.CanData = writer.(CanBusData).GetData()
//
return cf
}
func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//
f.TimeB = 0
a1, a1Ok := reader.ReadByte()
@ -253,10 +271,14 @@ func NewBtmDataMessageEndFrame(sn byte) *BtmDataMessageEndFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
}
}
func (f *BtmDataMessageEndFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(writer)
writer := NewCanBitsWriter(8)
//
byteMsk := uint32(0x00_00_00_ff)
//
@ -270,12 +292,14 @@ func (f *BtmDataMessageEndFrame) Encode() CanBusData {
writer.AddByte(byte((f.Crc32C >> 8) & byteMsk))
writer.AddByte(byte(f.Crc32C & byteMsk))
//
return writer.(CanBusData)
}
func (f *BtmDataMessageEndFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
cf.CanData = writer.(CanBusData).GetData()
//
return cf
}
func (f *BtmDataMessageEndFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//
f.TkB = 0
a1, a1Ok := reader.ReadByte()

View File

@ -61,60 +61,38 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
end := NewBtmDataMessageEndFrame(sn)
end.TkB = tkTimeB
//
crc32CData := make([]byte, 0, 132) //17*8-4
rt := make([]byte, 0, 204) //17*12
// 状态应答帧
statusData := statusRsp.Encode()
crc32CData = append(crc32CData, canFrameContent(statusData)...)
rt = append(rt, statusData.GetData()...)
// 数据帧
statusCf := statusRsp.Encode()
dmsCfs := make([]*CanetFrame, 0, 13)
for _, dm := range dms {
dmData := dm.Encode()
crc32CData = append(crc32CData, canFrameContent(dmData)...)
rt = append(rt, dmData.GetData()...)
}
// 消息时刻A
dtAData := dtA.Encode()
crc32CData = append(crc32CData, canFrameContent(dtAData)...)
rt = append(rt, dtAData.GetData()...)
// 消息时刻B
dtBData := dtB.Encode()
crc32CData = append(crc32CData, canFrameContent(dtBData)...)
rt = append(rt, dtBData.GetData()...)
// 消息结束帧
crc32CData = append(crc32CData, canTimeToBytes(end.TkB)...)
if len(crc32CData) != 132 {
slog.Warn("BtmDataMessageEndFrame crc32 校验数据须132字节")
return nil, false
}
end.Crc32C = calculateDataRspCrc32C(crc32CData)
rt = append(rt, end.Encode().GetData()...)
if len(rt) != 204 {
slog.Warn("BTM响应ATP 17帧须136字节")
return nil, false
dmsCfs = append(dmsCfs, dm.Encode())
}
dtACf := dtA.Encode()
dtBCf := dtB.Encode()
//
crc32cData := make([]byte, 0, 132)
crc32cData = append(crc32cData, statusCf.CanData...)
for _, dmCf := range dmsCfs {
crc32cData = append(crc32cData, dmCf.CanData...)
}
crc32cData = append(crc32cData, dtACf.CanData...)
crc32cData = append(crc32cData, dtBCf.CanData...)
crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...)
//
end.Crc32C = calculateDataRspCrc32C(crc32cData)
//
endCf := end.Encode()
//
rt := make([]byte, 0, 221) //17*13
rt = append(rt, statusCf.Encode()...)
for _, dmCf := range dmsCfs {
rt = append(rt, dmCf.Encode()...)
}
rt = append(rt, dtACf.Encode()...)
rt = append(rt, dtBCf.Encode()...)
rt = append(rt, endCf.Encode()...)
if len(rt) != 221 {
slog.Warn("len(rt)!=221")
return nil, false
}
return rt, true
}
// CAN帧中除去开始29bits的剩余8字节数据
func canFrameContent(canFrame CanBusData) []byte {
rd := NewCanBitsReader(canFrame.GetData(), canFrame.GetLastRowBitsLen())
rd.ReadByte() //ID1
rd.ReadByte() //ID2
rd.ReadByte() //ID3
rd.ReadBits(5) //ID4
//
rt := make([]byte, 0, 8)
for {
d, ok := rd.ReadByte()
if !ok {
break
}
rt = append(rt, d)
}
if len(rt) != 8 {
panic("CAN帧中数据体须为8字节")
}
return rt
}

View File

@ -29,10 +29,10 @@ func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
}
}
func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool {
if !f.FId.Decode(reader) {
return false
}
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
reader := NewCanBitsReader(cf.CanData, 8)
//数据流水号
if d, ok := reader.ReadByte(); ok {
f.Dsn = d
@ -106,10 +106,14 @@ func (f *BtmStatusRspFrame) Decode(reader CanBitsReader) bool {
//
return true
}
func (f *BtmStatusRspFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
func (f *BtmStatusRspFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
f.FId.Encode(writer)
writer := NewCanBitsWriter(8)
writer.AddByte(f.Dsn)
writer.AddByte(f.BaliseCounter)
writer.AddByte(f.MessageCounter)
@ -150,5 +154,6 @@ func (f *BtmStatusRspFrame) Encode() CanBusData {
writer.AddByte(tk3)
writer.AddByte(tk4)
//
return writer.(CanBusData)
cf.CanData = writer.(CanBusData).GetData()
return cf
}

View File

@ -17,11 +17,10 @@ func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
}
}
func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool {
func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool {
f.FId = cf.CanId
//
if !f.FId.Decode(reader) {
return false
}
reader := NewCanBitsReader(cf.CanData, 8)
//T2
t21, t21Ok := reader.ReadByte()
if !t21Ok {
@ -69,9 +68,14 @@ func (f *BtmTimeSyncCheckFrame) Decode(reader CanBitsReader) bool {
//
return true
}
func (f *BtmTimeSyncCheckFrame) Encode() CanBusData {
writer := NewCanBitsWriter(12)
f.FId.Encode(writer)
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
cf := &CanetFrame{}
cf.CanId = f.FId
cf.CanLen = 8
cf.FF = true
cf.RTR = false
//
writer := NewCanBitsWriter(8)
//
timeByteMsk := uint32(0x00_00_00_ff)
//t2
@ -93,5 +97,6 @@ func (f *BtmTimeSyncCheckFrame) Encode() CanBusData {
writer.AddByte(t33)
writer.AddByte(t34)
//
return writer.(CanBusData)
cf.CanData = writer.(CanBusData).GetData()
return cf
}

View File

@ -4,8 +4,6 @@ package message
// CanBits 可以在CAN总线上传输的bit流
// 按bit位来存储数据
// 一个字节中bit位编号从高位到低位依次为bit7-bit0
// 对于一个CAN帧29bits帧ID+64bits帧数据以bit为单位最后一字节即第12个字节的低位3bits为无用数据
type CanBits struct {
Data []byte //bits
LastBitsLen int //Data中最后一个字节中从高位到低位存储数据的有效位数值范围[1,8],8-LastBitsLen则为最后一个字节中低位剩余的空位数量
@ -211,7 +209,7 @@ var (
crc32CanTable []uint32 = nil
)
func CanCreateCrcTable() {
func CreateCanCrcTable() {
if crc16AtpReqTable == nil {
crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
}

71
third_party/message/can_net.go vendored Normal file
View File

@ -0,0 +1,71 @@
package message
import (
"fmt"
"strings"
)
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节)
type CanetFrame struct {
FF bool //true-1扩展帧
RTR bool //true-1远程帧
CanLen byte //CAN帧数据长度[0,8]CanData中有效数据字节数
CanId CanFrameId //CAN帧ID
CanData []byte //CAN帧数据8字节
}
func NewCanetFrame(buf []byte) *CanetFrame {
cf := &CanetFrame{}
cf.Decode(buf)
return cf
}
func (p *CanetFrame) Encode() []byte {
buf := make([]byte, 0, 13)
//canet200帧信息
b1 := byte(0x00)
if p.FF {
b1 |= 0x80 //bit7
}
if p.RTR {
b1 |= 0x40 //bit6
}
b1 |= p.CanLen & 0x0f
buf = append(buf, b1)
//CAN 帧ID
buf = append(buf, p.CanId.ID1)
buf = append(buf, p.CanId.ID2)
buf = append(buf, p.CanId.ID3)
buf = append(buf, p.CanId.ID4<<3)
//CAN 帧数据
if len(p.CanData) != 8 {
panic("len(p.CanData)!=8")
}
buf = append(buf, p.CanData...)
return buf
}
func (p *CanetFrame) Decode(buf []byte) {
if len(buf) != 13 {
panic("len(buf)!=13")
}
//
p.FF = buf[0]&0x80 == 0x80
p.RTR = buf[0]&0x40 == 0x40
p.CanLen = buf[0] & 0x0f
//1 2 3 4
p.CanId.ID1 = buf[1]
p.CanId.ID2 = buf[2]
p.CanId.ID3 = buf[3]
p.CanId.ID4 = buf[4] >> 3
//
p.CanData = buf[5:]
}
func (p *CanetFrame) String() string {
sb := strings.Builder{}
sb.WriteString(fmt.Sprintf("FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,", p.FF, p.RTR, p.CanLen,
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
sb.WriteString("CanData = ")
for _, d := range p.CanData {
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
}
return sb.String()
}