現在、UARTでディジーチェーンを使用して複数のデバイスを一本のUART回線で通信する試験をしています。
このUARTでのディジーチェーン、割とクセがあるようなので、今回僕がやったことを書いておこうと思います。
備忘録として書いておこうとは元々思っていましたが、技術相談させていただいたプロの方からブログにまとめてアップすることをお勧めされましたので、少し丁寧に噛み砕いて書いておこうと思います。
まず今回の動作試験に使用した環境をご紹介します。
今回のUARTのディジーチェーンでは、マスタデバイスを1つ、スレーブデバイスをいくつか接続することができます。
そのマスタデバイスとして、
・NUCLEO-F446RE (STM32 F446RE)
を使用しました。
また、スレーブデバイスとして、 
・A-Star 32U4 Micro  (Arduino Micro互換ボード、ATmega32U4)
・Arduino Mega 2560 (ATmega2560)
を使用しました。

回路は、最終的に以下のようなものに落ち着きました。
ちなみに、この回路ではノイズが乗りまくって信号が乱れます。
本当はRS485トランシーバチップなどを使用する必要がある回路ですが、今自分の家にそんなものはないので、同じような機能をトランジスタで簡易的に組みました。
ロボットに実装するときはきちんと組みます。
 Untitled
(注:回路図中のVCCは3.3Vとしました。)

通信のプロトコルは以下のようにしました。
 ① マスタがヘッダのデータを送信
 ② マスタがデータを要求するスレーブのアドレスを送信
 ③ スレーブがデータを送信
どうやら、これは小学校のホームルームに例えると分かりやすいらしいので、一応その書き方でも書いておきます。(マスタ=先生、スレーブ=児童、データ=返事)
 ① 先生が「みなさん静かにして、先生のお話をよく聞きましょうね」と児童に呼びかける
 ② 先生が児童を指名
 ③ 指名された児童が返事する

次にプログラムです。
https://drive.google.com/folderview?id=0Bxrh_mfNKfrNWjd3SVlRb3dHYkE&usp=sharing
ここのドライブに、サンプルプログラムを置いてあります。
マスタのプログラムはNUCLEO用のためmbedのプログラム、その他のものはArduinoのプログラムとなっています。
送られてきたアドレスを確認して、自分のアドレス(myaddress) と一致した場合のみトランジスタでマスタのRXへ自分のTXを接続するようにしています。
問題はないと思いますが、トランジスタの動作の遅延が通信に差し支えるといけないので、一応トランジスタで接続をONにしてから1マイクロ秒待つようにしてあります。
なくても動きました。

上記のようにすることで、一応ディジーチェーン接続できるかと思います。
大事なのでもう一度書きますが、 本当はRS485トランシーバチップなどを使用する必要がある回路です。
この回路ではノイズが乗りまくって信号が乱れてデータがきちんと読めない時があります。
あくまで即席で作った評価回路であることをご理解ください。 
こんな感じで波形が出ました。(水色波形の上辺=5V弱、底辺=1V弱)
(紫色の波形は無視して水色の波形のみ読んでください、デモ波形のようなものです)
FullSizeRender
この写真ではノイズが乗っているようにはあまり見えませんが、ちょくちょくノイズが乗って波形が乱れます。

(ここからは、プロの方に相談して発覚した原因を書いておきます。)
さて、なんで僕が「クセがある」って言うかというと、1つ目は回路図中のトランジスタを入れなきゃいけないことです。 
なぜこのトランジスタを入れたか。
このトランジスタを入れないと次のようなことが起きます。
 ① シリアル通信が有効化されたマイコンのTXピンは、常にHighレベルが出ている
 ② マスタに呼ばれたスレーブがデータを送るためTXピンからパルスを出力
 ③ 他の呼ばれていないスレーブが出力しているHigh電圧によって、パルスのLowレベルが底上げされる
 ④ 波形の底辺が十分に落ちきらず、マスタがパルスを読み取れない
実際の波形がこれです。(水色波形の上辺=4V弱、底辺=2V程)
 IMG_0774
小学校のホームルームで例えるなら、先生が「みなさん静かにして、先生のお話をよく聞きましょうね」と言っているにもかかわらず、喋っている児童がいる状況です。
これを解決するためには、プログラムでスレーブのTXのピンをハイインピーダンスにできればいいんですが、それをするためにはシリアル通信を無効化しないといけません。
(ArduinoでpinMode([TXのピン], INPUT);を実行しましたが、シリアル通信の設定の方が優先されてしまい、うまくいきませんでした)
そうすると、マスタからのヘッダのデータさえも受け付けなくなるので、通信が成り立たなくなります。
そのため、今回はスレーブのTXとマスタのRXの間にトランジスタを入れ、電気的に遮断することにしたわけです。 
 
クセがあると言う2つ目の理由、これはクセというより僕のプログラムのヘマなんですが、一応書いておきます。 

 if(Serial1.available()){ ・・・ } (ヘッダデータ1つ目を変数に代入)

 if(Serial1.available()){ ・・・ } (ヘッダデータ2つ目を変数に代入)

 if(Serial1.available()){ ・・・ } (アドレスのデータを変数に代入) 

スレーブのプログラムの、ループの最初によく似たif文が3つ並んでいると思います。
これはデータを受信していたら、バッファにあるデータを変数に代入する処理です。
このif文の内容を1つにまとめると、バッファにデータが3バイト分ないため、データの順番が入れ替わったり変なデータが入ったりします。
プログラムがスタートして1周目、マスタから受け取ったデータはスレーブでこんな感じに扱われます。
001
マスタから送られたデータはバッファに格納されるものの、それより先にバッファの中身をプログラムで読み出すので、バッファがからの時に代入される値は0あるいは予期していない値となります。
(上記の”変な値が入ったりする”の部分)
マスタが、"32" "64" "128"と送ったとすると、変数には"32" "0" "0"と代入されてしまいます。

先ほどの画像の後ろ2回分のデータがバッファに残った状態でプログラムの2周目に突入します。
002
バッファのデータは古い順に呼び出されてきて、変数に代入されていきます。
その結果、2周目の最初に受信した値は最初に代入されず、1周目に受信して変数に代入されなかった値が代入されることになります。
そのため、マスタが再度"32" "64" "128"と送ったとしても、変数には"64" "128" "32"と代入されてしまうことになります。
これでは順番もめちゃくちゃ、返ってくる値もめちゃくちゃで使い物になりません。
なので、バッファに変数に代入するデータがあるかどうか確認してから代入するようにしたのが、サンプルプログラムの状態です。

ここまでの長文で、大変読みにくかったと思いますが、夜中にお手伝いしていただきながら3時間弱もいろいろやってわかった結果です。
もし同じような状況で困っている方がおられて、参考になれば幸いです。   

2016.05.23 0:22 追記
今回お世話になった方から、「クセがあると言う2つ目の理由」の内容について、よりわかりやすくなる方法をお教えいただいたので、それを元に修正を加えました。
タイムチャートの画像を2枚追加しています。