この記事は TinyGo Advent Calendar 2025 10日目の記事です。
過去に、僭越ながら拙作として、TinyGo へ MCP2515 のドライバーをコミットさせていただきました。
まだ、Qiita などで使用方法について説明をしていなかったので、Advent Calender 2025 を機に記事にしてまとめます。
ゴール
- MCP2515 を TinyGo で動かすことができる
MCP2515 とは
MCP2515 は CAN(Controller Area Network) の通信を行うためのコントローラー IC です。
CAN は自動車の ECU 間の通信や医療機器のマイコン間通信など、様々なシステムで利用されている通信規格です。
以下へ秋月電子通商の商品ページの説明も引用します。
MCP2515は、CAN V2.0Bのスタンドアロンコントローラです。
標準・拡張データ、リモートフレームの送受信を行うことができます。
MCP2515は2個の受信マスタと6個の受信フィルタを持っていて
不要なメッセージをふるい落としホストMCUのオーバーヘッド負荷を減らします。
MCUとはSPIで通信します。
秋月電子通商の商品ページ
実際に使用するにあたっては、CAN トランシーバー等と一緒に基板実装されていると使いやすいため、
Amazon などで販売されている、例えば以下の商品のようなものを使用するのが良いです。
とても安価で購入できるため、気軽に試せるのも良いです。
環境を用意する
今回は以下の環境を使用しました。
MCP2515 はロジックレベルが 5V であるため、ロジックレベルが 5V のマイコンボードを使用するか、
異なるロジックレベルのマイコンボードとロジックレベル変換 IC を併用する必要があります。
今回は両方のパターンをノード A、ノード B に割り当てました。
(通信バスへ複数の通信チャンネルが存在する必要があるため、2 つのノードを用意しています。)
- ソフトウェア
- TinyGo 39.0
- ハードウェア
- ノード A
- Feather-m4
- 8bit双方向ロジックレベル変換 IC
- MCP2515 ボード
- ノード B
- Arduino UNO
- MCP2515 ボード
- ノード A
配線する
配線は以下のように行ってください。
各マイコンボードのどのピンが SPI のピンとなっているかは、
インターネットの検索や AI エージェントへ、「マイコンボード名 pinout SPI」 のようなプロンプトを入力すればピン配置図などを入手し確かめることができます。
| MCP2515 | マイコンボード |
|---|---|
| INT | (接続不要) |
| SCK | SCK |
| SI | SDO (旧い表記の MO、MOSI など) |
| SO | SDI (旧い表記の MI、MISO など) |
| CS | CS(SS などの表記の場合もあり) |
| GND | GND |
| VCC | 5V |
実際に配線をするとこのような感じになります。
サンプルコードを動かす
サンプルコード
サンプルコードは、TinyGo の drivers へ各デバイスごとに登録されているため、
そちらを利用してください。
https://github.com/tinygo-org/drivers/blob/release/examples/mcp2515/main.go
以下へ同じものを記載します。
以下は、Feather-m4 で実際に動作するコードですが、ボードにより SPI の設定が少し異なる場合はあるため、
それぞれのボードの SPI のピン配置などを確認して設定してください。
package main
import (
"fmt"
"machine"
"time"
"tinygo.org/x/drivers/mcp2515"
)
var (
spi = machine.SPI0
csPin = machine.D5
)
func main() {
spi.Configure(machine.SPIConfig{
Frequency: 115200,
SCK: machine.SPI0_SCK_PIN,
SDO: machine.SPI0_SDO_PIN,
SDI: machine.SPI0_SDI_PIN,
Mode: 0})
can := mcp2515.New(spi, csPin)
can.Configure()
err := can.Begin(mcp2515.CAN500kBps, mcp2515.Clock8MHz)
if err != nil {
failMessage(err.Error())
}
for {
err := can.Tx(0x111, 8, []byte{0x00, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA})
if err != nil {
failMessage(err.Error())
}
if can.Received() {
msg, err := can.Rx()
if err != nil {
failMessage(err.Error())
}
fmt.Printf("CAN-ID: %03X dlc: %d data: ", msg.ID, msg.Dlc)
for _, b := range msg.Data {
fmt.Printf("%02X ", b)
}
fmt.Print("\r\n")
}
time.Sleep(time.Millisecond * 500)
}
}
func failMessage(msg string) {
for {
println(msg)
time.Sleep(1 * time.Second)
}
}
動作させる
以下のコマンドにてマイコンボードへ書き込むと、MCP2515 が起動して送受信を開始します。
tinygo flash コマンドへ --monitor オプションを付与して実行すると、
TeraTerm 等を使用しなくとも、シリアル出力のモニターが出来るためとても便利です。
上手く通信できていれば、一方のノードが送信した情報が、他方のノードのモニターにて確認できます。
$ tinygo flash --target=feather-m4 --monitor ./main.go
Connected to COM3. Press Ctrl-C to exit.
0x111 8 0x00 0xAA 0x00 0xAA 0x00 0xAA 0x00 0xAA
0x111 8 0x00 0xAA 0x00 0xAA 0x00 0xAA 0x00 0xAA
0x111 8 0x00 0xAA 0x00 0xAA 0x00 0xAA 0x00 0xAA
0x111 8 0x00 0xAA 0x00 0xAA 0x00 0xAA 0x00 0xAA
.
.
まとめ
今回は MCP2515 と、それを TinyGo で使用する方法についてまとめました。
TinyGo では MCP2515 以外にも、沢山のドライバーを提供しているため、
色々なデバイスを動かしてみると面白そうです。
(そしてまだないデバイスがあれば是非ともコミットを!!!!)
それでは、最後までお読みいただきありがとうございました。
良い年末年始をお過ごしください。
