CAN通信

STM32でCANを使う


こちらに STM32用のArduino Coreライブラリが公開されています。
STM32でもArduino-IDEを使って開発することができます。

STM32の多くの機種は標準でCAN-Interfaceを内蔵しています。
こちらに canardライブラリを使ったSTM32+ArduinoのCAN通信サンプルが公開されています。

CANのパケットは最大8バイトまでのデータを送ることができます。
canardライブラリは、送信データが8バイト以上の時は、データを複数のパケットに分割して送信し、
受信したパケットをライブラリ内部でマージすることで8バイト以上のデータ送受信に対応しています。
送信データが8バイトの時も、7バイトと1バイトの2つのパケットに分割されてしまうので、他のライブラリとの互換性が有りません。

そこで、8バイトまでのパケットに限定したサンプルをこ ちらで公開 し ています。
パケットの分割やマージの機能は無いので、ArduinoやRaspberryなど他のライブラリと相互に通信することができます。
STM32F103、STM32F303、STM32F407で動作を確認しました。

Arduino-DUEと同様に、MCP2551の様なCAN Transceiverが必要になります。
MCP2551は5Vでしか動かないので、5Vを供給できないときは、
SN65HVD230の様な3.3Vで動くCAN Transceiverが必要になります。

Arduino-UNOと通信するときの結線は以下となります。

5Vを供給できる場合


3.3Vしか供給できない場合
BlackPillは5Vポートが有りません。
またBluePillもST-Linkポートから電源を供給しているときは5Vは給電できません。


Arduino-UNO Arduino-DUE ESP8266 RaspberryPiなどと相互に通信することができます。



こちら
にライブラリを一切使わずに、レジスター操作だけでCAN通信を行うサンプルが公開されています。
何も説明がないですが、STM32F103を使ってCAN_RX=PB8 CAN_TX=PB9で動きます。
GPIOの初期設定のやり方と、CAN関係のレジスターの使い方が良く分かります。
そこで、これを元に拡張FRAMEと、ポートのREMAPに対応したサンプルを作りました。
ソースはこ ちらで 公 開しています。

レジスターの使い方が分かったので、STM32F103もSTM32F303も、3つのポートから使用するポートを選ぶことができます。

CAN_REMAP="00"
CAN_REMAP="10"[2]
CAN_REMAP="11"[3]
CAN_RX
PA11
PB8
PD0
CAN_TX
PA12
PB9
PD1

[2]36-Pinパッケージのみ有効
[3]100-Pin または 144-Pinパッケージのみ有効

STM32F407/F466ではCAN1とCAN2の2つのポートを同時に使うことができるようにしました。

CAN_REMAP="00"
CAN_REMAP="10"[2]
CAN_REMAP="11"[3]
CAN1_RX
PA11
PB8
PD0
CAN1_TX
PA12
PB9
PD1
CAN2_RX
PB5
PB12
PB12
CAN2_TX
PB6
PB13
PB13

[2]36-Pinパッケージのみ有効
[3]100-Pin または 144-Pinパッケージのみ有効

STM32は多くの機種でCAN(bxCAN)をサポートしていますが、機種によりレジスターの使用方法が微妙に違います。
STM32は1つのピンに複数の機能を持たせていて、レジスター操作でピンの役割を変えること(GPIOのAtrernative Functionと呼びます)ができます。
CANとして使るポートはデフォルトでは普通のGPIOとなっていて、必ずAtrernative FunctionでGPIO→CANに設定変更を行う必要が有りますが、
CANとして使るポートが、ほぼモデル毎に異なります。
また、BitRateに応じてタイミングレジスターの値を変更する必要が有りますが、クロック周波数により設定する値が変わります。
厄介なのは、STM32F103を使う場合、BluePillやBlackPillのボード名称(Board Part Number)でビルドした時と、
GenericF103のボード名称でビルドした時では、クロック周波数が変わります。
さらに、一部のモデルはFDCANに対応していて、FDCAN対応機種はレジスターの使用方法がbxCANとは別物です。

STMにはArduino環境で簡単にCANが使えるような、機種に依存しない汎用ライブラリを提供してくれるようにリクエストを出しています が、
おそらく実現しないでしょう。



STM32のCAN(bxCAN)には受信フィルターの機能が有ります。
リファレンスマニュアルに説明が有りますが、フィルターは以下の4つのモードに切り替えることができます。
・32-Bit Filter - Identifier Mask
・32-Bit Filter - Identifier List
・16-Bit Filter - Identifier Mask
・16-Bit Filter - Identifier List

STM32には受信用のFIFOバッファが2つあり、それぞれのバッファで3つのストアを持っています。
受信フィルターを適切に設定すると、必要なデータだけを受信し、不要なデータはマイコン内部で捨てることができるので、
相手が高速にデータを送信したときに取りこぼすことが無くなります。
また、受信したIDに応じてFIFO-0に格納するか、FIFO-1に格納するかを選ぶことができます。
優先度の高いメッセージはFIFO-0、低いメッセージはFIFO-1など、かなり柔軟な受信ができるようになります。
公開しているサンプルでは、全てのメッセージをFIFO-0に格納するフィルターを1つだけ定義しています。



この様なUSB-CAN Adapterを入手しました。
一見別物の様ですが、ファームは同一のファームが書かれています。
上のモジュールが$11、下のモジュールが$15でした。
ケースに入っていましたが、実装されている部品とCAN-H/Lを確認するために、ケースから出しています。


どちらもMCUにはSTM32F103、CAN TransceiverにはTJA1050(5V仕様)が使われています。
上のモジュールには裏面にCH340、下のモジュールは表面にCP2102のUSB-TTL変換チップが実装されています。
BluePillやBlackPillと違って、クリスタルは12MHzです。

上のモジュールはCAN-HとCAN-Lの間にダイオードらしきものが実装されていて、50オームの終端抵抗が実装されています。
ダイオードらしきものの意味は不明です。

下のモジュールはCANコネクターの下のジャンパで120オームの終端抵抗(R7)を有効にすることができます。

こちらの中国語 のページの中に「ourdev_627692IXWNNX.rar」のリンクが有り、これがWindowsアプリケーションです。
解凍すると以下の2つのアプリが現れます。

・EmbededConfig.exe
最初にこのツールでCAN Bit Rateと受信フィルターを設定します。
「配置波特率」がCAN Bit Rateの指定、その右のボタンが工場出荷時の状態に初期設定するボタンですが、
チェックボックスの意味は全く分かりません。
序番1がStandard Frameに対するフィルター設定、序番2がExtended Frameに対するフィルター設定で、
どちらもIDとマスクがオール0なので全てのIDを受信する設定です。


・EmbededDebug 2.0.exe
CAN Bit Rateが正しければ、こちらのツールで受信データをモニターすることができます。
こちらのページ によれば、特定のIDを選んでグラフ表示などもできるみたいですが、中国語なので操作方法が分かりません。


こちらのページ の中に「ourdev_627693HY5ECP.rar」のリンクが有り、これがSTM32側のソースコードです。
KEILのuVision4を使って開発されています。
STM32側のソースコードを解析したら、USBの通信仕様が分かりましたので、こちらで このモジュールを操作するpythonコードを公開しています。
受信Frameのモニターだけでなく、CAN Frameの送信とフィルター設定に対応しています。
USBの通信仕様が判明しているので、頑張ればWindowsアプリケーションを作ることもできます。

この手のモジュールはものすごく高価なものが多いのですが、受信したCAN Frameをモニターするだけなら、
このアダプターで十分です。



この様な開発ボードを入手しました。
MCUにはSTM32F103VET6が実装されています。


CAN、RS232C、RS485のコネクターが出ています。
これらは全て2線式の通信ですが、通信仕様が違います。
CAN Transceiverには5V仕様のTJA1050が使われていて、終端抵抗(R3)は120オームです。
CA_RXはPB8、CAN_TXはPB9に繋がっています。
左側の端子にある赤いジャンパーはSP3232EEN(RS232C Transceiver)のVCCを3.3V/5Vに切り替えるためのジャンパーです。


こちらのコー ドが一発で動きました。
終端抵抗の有効/無効を切り替えられないのが少し残念です。



この様なトランシーバモジュールを入手しました。


裏側にはSN65HVD230と2つのチップ抵抗が実装されています。
SN65HVD230は3.3Vで駆動することができます。
右側のチップ抵抗が終端抵抗(120Ω)、左側のチップ抵抗(10KΩ)でRsピンをPullDownしています。
Rsピンはモード切替用のピンですが、PullDownでHigh Speedモードになります。


1つのCAN Bus上で、5V CAN Bus Transceiverと3.3V CAN Bus Transceiverは混在して使うことができますが
混在して使う場合、終端抵抗を120Ωから150Ωに変更しないと送信が動きませんでした。
モジュールから左側のチップ抵抗(終端抵抗)を外して、150Ωの抵抗を使いました。