自社製品CanLine-2 の製作にあたり、STM32 マイコンを用いた CAN-FD 通信の設定方法 について整理しました。
本記事では STM32CubeMX(HAL ドライバ)を使用した CAN-FD 通信 を対象とし、初期設定から送受信までを順に説明します。
| 開発環境 | STM32CubeMX(Version 6.5.0)(無料) STM32CubeIDE(Version: 1.11.2)(無料) |
| デバッガ | J-Link Plus |
| ボード | 自社製品(CanLine-2)用ボード |
| マイコン | STM32G474CET6 |
| CANトランシーバ | MCP2542FD-E/SN |
初期設定
STM32でCAN-FD通信を行うため、CubeMXを使用してCANの初期設定を行います。
ピン設定
CAN-FDで使用するピンを以下のように設定します
- PA11→FDCAN1_TX
- PA12→FDCAN1_RX

各種パラメータの設定
CubeMXの画面左側のペリフェラル設定ツリーから「FDCAN1」を選択して、各種パラメータを設定します。

Frame Format
CAN-FDを使用する場合、「Frame Format」をFD mode with BitRate Switchingにします。
これはCAN-FD フレームを使用し、データフェーズでビットレートを高速化する設定になります。
| 設定項目 | 内容 |
| Classic Mode | 従来の Classic CAN 通信モード。 最大 8 バイト、単一ビットレートで通信します。 |
| FD mode without BitRate Switching | CAN-FD 通信(BRS 無効)。 最大 64 バイト、データフェーズも同一ビットレートで通信します。 |
| FD mode with BitRate Switching | CAN-FD 通信(BRS 有効)。 データフェーズのみ高速ビットレートで通信します。 |
通信速度の設定方法
CAN-FDのフレームは調停フェーズ(Nominal Phase) とデータフェーズ(Data Phase) の2つに分かれています。そのため、通信速度は調停フェーズ用 と データフェーズ用 をそれぞれ個別に設定する必要があります。
調停フェーズのパラメータ
- Nominal Prescaler
- Nominal Time Seg1
- Nominal Time Seg2
データフェーズのパラメータ
- Data Prescaler
- Data Time Seg1
- Data Time Seg2
これらのパラメータを理解するには、Time Quantum と 1ビット時間の構成 を知る必要があります。
Time Quantum(TQ)とは、
CANの1ビット時間を構成する最小単位です。
TQは以下の式で求められます。
Time Quantam = Prescaler÷FDCANクロック
FDCANクロックはCubeMXのClock Configurationタブで確認できます。

1ビット時間の構成は、以下の3つの区間で構成されます
- Sync Segment(固定:1TQ)
- Time Segment 1(TSeg1)
- Time Segment 2(TSeg2)
そのため、1ビット時間は次の式で表されます。
1ビット時間 = (1 + TSeg1 + TSeg2) × Time Quantum
設定例:調停フェーズ 500kbps(サンプリングポイント 80%)
ここでは以下の条件で設定します。
- 通信速度:500kbps
- サンプリングポイント:80%
- FDCANクロック:80MHz
手順① Time Quantumを求める
Prescaler を 8 に設定すると、
Time Quantum = 8 ÷ 80MHz = 100ns
手順② 1ビット時間を計算する
500kbps の 1ビット時間は、
1 ÷ 500kbps = 2µs
Time Quantum が 100ns のため、
2µs ÷ 100ns = 20TQ
つまり、
1ビット = 合計 20TQ になるように設定します。
手順③ TSeg1 / TSeg2 を決める(80%)
サンプリングポイントは次の式で求められます。
サンプリングポイント= (1 + TSeg1) ÷ (1 + TSeg1 + TSeg2)
合計20TQ、サンプリングポイント80%になるようにすると、
- TSeg1:15
- TSeg2:4
(1 + 15) ÷ (1 + 15 + 4)= 16 ÷ 20= 80%
調停フェーズ(Nominal)の設定値まとめ
- Nominal Prescaler:8
- Nominal Time Seg1:15
- Nominal Time Seg2:4
設定例:データフェーズ 2Mbps(サンプリングポイント 80%)
ここでは以下の条件で設定します。
- 通信速度:2Mbps
- サンプリングポイント:80%
- FDCANクロック:80MHz
手順① Time Quantumを求める
Prescaler を 4 に設定すると、
Time Quantum = 4 ÷ 80MHz = 50ns
手順② 1ビット時間を計算する
2Mbps の 1ビット時間は、
1 ÷ 2Mbps = 0.5µs(=500ns)
Time Quantum が 50ns のため、
500ns ÷ 50ns = 10TQ
つまり、1ビット = 合計 10TQ になるように設定します。
手順③ TSeg1 / TSeg2 を決める(80%)
サンプリングポイント= (1 + TSeg1) ÷ (1 + TSeg1 + TSeg2)
合計10TQ、サンプリングポイント80%になるようにすると、
- TSeg1:7
- TSeg2:2
(1 + 7) ÷ (1 + 7 + 2)= 8 ÷ 10= 80%
データフェーズ(Data)の設定値まとめ
- Data Prescaler:4
- Data Time Seg1:7
- Data Time Seg2:2
ポイントまとめ(理解のコツ)
- 最初に Time Quantum を決める
- 次に 1ビットあたりのTQ数 を決める
- 最後に TSeg1 / TSeg2 を割り振る
- サンプリングポイントは TSeg1の終端
「TQ → 合計TQ → サンプリングポイント」
の順で考えると迷いません。
CAN-FD送信
ここでは、STM32CubeMX で設定した FDCAN を使用してCAN / CAN-FD フレームを送信する方法を説明します。
送信処理の全体の流れ
CAN-FD の送信は、以下の手順で行います。
- FDCAN を開始する
- 送信ヘッダ(ID、DLC、FD/BRS設定)を準備する
- 送信データを設定する
- Tx FIFO に書き込んで送信する
① FDCAN の開始
CubeMX で初期化した後、以下の関数で通信を開始します。
HAL_FDCAN_Start(&hfdcan1);
※ 送信・受信ともに、この関数を呼び出す必要があります。
② 送信ヘッダの設定
送信フレームの情報は FDCAN_TxHeaderTypeDef 構造体で指定します。
FDCAN_TxHeaderTypeDef TxHeader;
TxHeader.Identifier = 0x123; // 送信ID
TxHeader.IdType = FDCAN_STANDARD_ID; // 標準ID
TxHeader.TxFrameType = FDCAN_DATA_FRAME; // データフレーム
TxHeader.DataLength = FDCAN_DLC_BYTES_8; // DLC
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // BRS設定
TxHeader.FDFormat = FDCAN_CLASSIC_CAN; // Classic / FD
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
③DLC と FD / BRS の関係
送信時は Frame Format と DLC の組み合わせに注意が必要です。
| 設定 | 内容 |
| FDCAN_CLASSIC_CAN | DLCは最大 8バイト |
| FDCAN_FD_CAN | DLCは最大 64バイト |
| BitRateSwitch = ON | データフェーズ高速化(CAN-FD) |
CAN-FD(64バイト+BRS ON)の例
TxHeader.FDFormat = FDCAN_FD_CAN;
TxHeader.BitRateSwitch = FDCAN_BRS_ON;
TxHeader.DataLength = FDCAN_DLC_BYTES_64;
④ 送信データの設定
uint8_t TxData[64] = {0};
Classic CAN(8バイト)の場合は、先頭 8 バイトのみ使用されます。
⑤Tx FIFO に書き込んで送信
準備したヘッダとデータを、Tx FIFO に登録します。
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData);
この関数を呼び出すことで、FDCAN コントローラが自動的に送信を行います。
送信前の注意点(重要)
Tx FIFO が空いているか確認する
高頻度送信を行う場合は、Tx FIFO の空き確認を行うと安全です。
if (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) > 0) {
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData);
}
まとめ(送信処理)
- HAL_FDCAN_Start() で通信開始
- 送信条件は FDCAN_TxHeaderTypeDef で指定
- DLC・FDFormat・BRS の組み合わせに注意
- HAL_FDCAN_AddMessageToTxFifoQ() で送信
CAN-FD 受信
- Rx FIFOを有効化する
- フィルタで Rx FIFO0 / FIFO1 を指定
- 割り込み(通知)を有効化
- Rx FIFO にデータが入る
- コールバック関数で受信処理を行う
①フィルタ設定(Rx FIFO指定)
受信処理では フィルタ設定が必須です。フィルタで「どのFIFOに入れるか」を指定します。
例:標準IDを FIFO0 に入れる設定
FDCAN_FilterTypeDef sFilter;
sFilter.IdType = FDCAN_STANDARD_ID;
sFilter.FilterIndex = 0;
sFilter.FilterType = FDCAN_FILTER_MASK;
sFilter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilter.FilterID1 = 0x000;
sFilter.FilterID2 = 0x000;
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilter);
※Maskモードで FilterID2=0x000 は“全ビットdon’t care”となるため 全IDを通す 例です
②割り込み(通知)の有効化
Rx FIFO にメッセージが入ったことを通知するため、以下の割り込みを有効にします。
HAL_FDCAN_ActivateNotification(
&hfdcan1,
FDCAN_IT_RX_FIFO0_NEW_MESSAGE,
0
);
③受信コールバック関数
Rx FIFO に新しいメッセージが入ると、以下のコールバック関数が自動的に呼ばれます。
void HAL_FDCAN_RxFifo0Callback(
FDCAN_HandleTypeDef *hfdcan,
uint32_t RxFifo0ITs)
{
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[64];
if (RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE)
{
HAL_FDCAN_GetRxMessage(
hfdcan,
FDCAN_RX_FIFO0,
&RxHeader,
RxData
);
// ここに受信処理を書く
}
}
④DLC とデータ長の注意点
受信時は、RxHeader.DataLength に**DLC(コード値)**が入ります。
実際のバイト数はDLC → バイト数変換が必要です。
uint32_t len = FdcanDlcToBytes(RxHeader.DataLength);
__STATIC_INLINE uint8_t FdcanDlcToBytes(uint32_t dlc)
{
switch (dlc) {
case FDCAN_DLC_BYTES_0: return 0;
case FDCAN_DLC_BYTES_1: return 1;
case FDCAN_DLC_BYTES_2: return 2;
case FDCAN_DLC_BYTES_3: return 3;
case FDCAN_DLC_BYTES_4: return 4;
case FDCAN_DLC_BYTES_5: return 5;
case FDCAN_DLC_BYTES_6: return 6;
case FDCAN_DLC_BYTES_7: return 7;
case FDCAN_DLC_BYTES_8: return 8;
case FDCAN_DLC_BYTES_12: return 12; // CAN-FD
case FDCAN_DLC_BYTES_16: return 16;
case FDCAN_DLC_BYTES_20: return 20;
case FDCAN_DLC_BYTES_24: return 24;
case FDCAN_DLC_BYTES_32: return 32;
case FDCAN_DLC_BYTES_48: return 48;
case FDCAN_DLC_BYTES_64: return 64;
default:
return 0; // 異常値ガード
}
}
まとめ(受信処理)
- 受信データは Rx FIFO に格納される
- フィルタで FIFO0 / FIFO1 を指定する
- 割り込み通知でコールバック処理を行う
- DLC と実データ長の違いに注意
おわりに
本記事では、STM32を用いたCAN-FD通信の基本設定や実装例について解説しました。
実際の現場では、これらの設定や動作検証を一つずつ行うのに、想像以上の時間と手間がかかります。
ヒトミソフト開発では、STM32ベースで Classic CAN / CAN-FD の実通信検証にすぐ使えるUSB-CANインターフェース「CanLine-2」 を開発・提供しています。
DLLも用意しているため、PCアプリケーションから直接CAN/CAN-FD通信を制御することが可能で、
独自のモニタリングソフトや評価用ツールの開発にも対応できます。
CAN-FD通信の評価やデバッグ、既存システムとの接続確認などを、より手軽に行いたい場合は、ぜひ CanLine-2 もご覧ください。

