add support extended id for mcp2515 (#857)

* add support extended id for mcp2515
* fix mcp2512 example code
* revert Pin control
This commit is contained in:
nobonobo
2026-04-20 18:51:56 +09:00
committed by GitHub
parent e960a6ff57
commit 1c10dea443
3 changed files with 53 additions and 42 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ func main() {
SDI: machine.SPI0_SDI_PIN, SDI: machine.SPI0_SDI_PIN,
Mode: 0}) Mode: 0})
can := mcp2515.New(spi, csPin) can := mcp2515.New(spi, csPin)
can.Configure() can.Configure(mcp2515.Configuration{})
err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz) err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz)
if err != nil { if err != nil {
failMessage(err.Error()) failMessage(err.Error())
+45 -41
View File
@@ -6,6 +6,7 @@
package mcp2515 // import "tinygo.org/x/drivers/mcp2515" package mcp2515 // import "tinygo.org/x/drivers/mcp2515"
import ( import (
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"time" "time"
@@ -15,15 +16,30 @@ import (
"tinygo.org/x/drivers/internal/pin" "tinygo.org/x/drivers/internal/pin"
) )
var (
ErrNothingIsReceived = errors.New("readMsg: nothing is received")
ErrRequestNewModeMaxTimeEx = errors.New("requestNewMode max time expired")
ErrLengthIsLongerThanCapacity = errors.New("length is longer than capacity")
ErrTxTimeout = errors.New("Tx: Tx timeout")
ErrInvalidDirection = errors.New("invalid direction")
ErrInvalidParameter = errors.New("invalid parameter")
ErrCannotExpandBuffer = errors.New("cannot expand buffer (to avoid memory allocation)")
)
// Device wraps MCP2515 SPI CAN Module. // Device wraps MCP2515 SPI CAN Module.
type Device struct { type Device struct {
spi SPI spi SPI
cs pin.OutputFunc cs pin.OutputFunc
msg *CANMsg msg *CANMsg
extended bool
mcpMode byte mcpMode byte
configurePins func() configurePins func()
} }
type Configuration struct {
Extended bool
}
// CANMsg stores CAN message fields. // CANMsg stores CAN message fields.
type CANMsg struct { type CANMsg struct {
ID uint32 ID uint32
@@ -56,10 +72,11 @@ func New(b drivers.SPI, csPin pin.Output) *Device {
} }
// Configure sets up the device for communication. // Configure sets up the device for communication.
func (d *Device) Configure() { func (d *Device) Configure(cfg Configuration) {
if d.configurePins == nil { if d.configurePins == nil {
panic(legacy.ErrConfigBeforeInstantiated) panic(legacy.ErrConfigBeforeInstantiated)
} }
d.extended = cfg.Extended
d.configurePins() d.configurePins()
} }
@@ -117,9 +134,13 @@ func (d *Device) Tx(canid uint32, dlc uint8, data []byte) error {
timeoutCount++ timeoutCount++
} }
if timeoutCount == timeoutvalue { if timeoutCount == timeoutvalue {
return fmt.Errorf("Tx: Tx timeout") return ErrTxTimeout
} }
err = d.writeCANMsg(bufNum, canid, 0, 0, dlc, data) ext := byte(0)
if d.extended {
ext = 1
}
err = d.writeCANMsg(bufNum, canid, ext, 0, dlc, data)
if err != nil { if err != nil {
return err return err
} }
@@ -389,7 +410,7 @@ func (d *Device) configRate(speed, clock byte) error {
set = false set = false
} }
if !set { if !set {
return errors.New("invalid parameter") return ErrInvalidParameter
} }
if err := d.setRegister(mcpCNF1, cfg1); err != nil { if err := d.setRegister(mcpCNF1, cfg1); err != nil {
return err return err
@@ -449,7 +470,7 @@ func (d *Device) readMsg() error {
return err return err
} }
} else { } else {
return fmt.Errorf("readMsg: nothing is received") return ErrNothingIsReceived
} }
return nil return nil
@@ -556,39 +577,22 @@ func (d *Device) writeCANMsg(bufNum uint8, canid uint32, ext, rtrBit, dlc uint8,
} }
func (s *SPI) setTxBufData(canid uint32, ext, rtrBit, dlc uint8, data []byte) error { func (s *SPI) setTxBufData(canid uint32, ext, rtrBit, dlc uint8, data []byte) error {
canid = canid & 0x0FFFF var id [4]byte
if ext == 1 { if ext == 1 {
// TODO: add Extended ID canid = canid & extidBottom29Mask
err := s.setTxData(0) extended_id := canid
if err != nil { high_11 := extended_id & extidTop11WriteMask
return err low_18 := extended_id & extidBottom18Mask
} high_11 <<= 3
err = s.setTxData(0) extended_id_shifted := high_11 | low_18
if err != nil { canid = extended_id_shifted | extidFlagMask
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
} else { } else {
err := s.setTxData(byte(canid >> 3)) canid = canid & stdidBottom11Mask
if err != nil { canid <<= 16 + 5
return err }
} binary.BigEndian.PutUint32(id[:], canid)
err = s.setTxData(byte((canid & 0x07) << 5)) for _, b := range id {
if err != nil { err := s.setTxData(b)
return err
}
err = s.setTxData(0)
if err != nil {
return err
}
err = s.setTxData(0)
if err != nil { if err != nil {
return err return err
} }
@@ -785,7 +789,7 @@ func (d *Device) requestNewMode(newMode byte) error {
if r&modeMask == newMode { if r&modeMask == newMode {
return nil return nil
} else if e := time.Now(); e.Sub(s) > 200*time.Millisecond { } else if e := time.Now(); e.Sub(s) > 200*time.Millisecond {
return errors.New("requestNewMode max time expired") return ErrRequestNewModeMaxTimeEx
} }
} }
} }
@@ -861,23 +865,23 @@ func (s *SPI) clearBuffer(dir int) error { return s.setBufferLength(0, dir) }
func (s *SPI) setBufferLength(length int, dir int) error { func (s *SPI) setBufferLength(length int, dir int) error {
if dir == tx { if dir == tx {
if length > cap(s.tx) { if length > cap(s.tx) {
return fmt.Errorf("length is longer than capacity") return ErrLengthIsLongerThanCapacity
} }
s.tx = s.tx[:length] s.tx = s.tx[:length]
} else if dir == rx { } else if dir == rx {
if length > cap(s.rx) { if length > cap(s.rx) {
return fmt.Errorf("length is longer than capacity") return ErrLengthIsLongerThanCapacity
} }
s.rx = s.rx[:length] s.rx = s.rx[:length]
} else { } else {
return fmt.Errorf("invalid direction") return ErrInvalidDirection
} }
return nil return nil
} }
func (s *SPI) setTxData(data byte) error { func (s *SPI) setTxData(data byte) error {
if len(s.tx) >= bufferSize { if len(s.tx) >= bufferSize {
return fmt.Errorf("cannot expand buffer (to avoid memory allocation)") return ErrCannotExpandBuffer
} }
s.tx = append(s.tx, data) s.tx = append(s.tx, data)
+7
View File
@@ -417,4 +417,11 @@ const (
canFail = 0xff canFail = 0xff
canMaxCharInMessage = 8 canMaxCharInMessage = 8
// for extended id
extidTop11WriteMask = 0x1FFC0000
extidBottom29Mask = (1 << 29) - 1 // extended id bits
extidBottom18Mask = (1 << 18) - 1 // bottom 18 bits
stdidBottom11Mask = 0x7FF
extidFlagMask = 1 << 19
) )