December 14, 2011ソフトウェアSPIが動かない (解決済)マイコンを使っていると、時々マイコンに組み込まれた周辺機能だけでは事が足りなくなって、汎用I/Oポートを使って、ソフトウェア的に機能を実現するということがよくあります。ポートのH/Lをコントロールしたり、はたまた汎用ポートをHi-Z(ハイインピーダンス)の状態にしてH/Lを読み込んだりすることで実現されます。よくやられるのが、ソフトウェアSPIやIソフトウェアUARTといったものです。最近、そのソフトウェアSPIを実装していて嵌りましたので、今回は僕の失敗談を披露したいと思います。 ソフトウェアSPIに限らず、ポートの状態の書き出しとポートの状態の読み込みを行うものでは起こりうる問題なので、せっかくなので一般化して話を進めたいと思います。汎用ポートは、多くの場合、複数のポートをひとまとめとして、1つのレジスタで扱われます。ここではP1というレジスタに8個の汎用I/O、すなわちP1.0からP1.7の8個が割り当てられていたとしましょう。その中でP1.0を状態の書き込みに、P.1.1を状態の読み込みに使うことにします。 たとえば、P1.0(出力)にP.1.1(入力)と同じ信号レベルを出したければ、次のようなコードを書いて実現することが多いかもしれません。 if(P1 & 0x02){P1 |= 0x01;}else{P1 &= ~0x01;}
ところが、このコード、特定のマイコンでは、一度P1.1がLになると、たとえ他のマイコン等から再びP1.1にHが出力されようとも以降はLが読み出され、二度とP1.0がHにならなくなりました。僕はC8051というSilicon Laboratoriesのマイコンで今回この失敗を経験しました。 原因はP1というレジスタの構成にありました。レジスタに複数の機能が割り当てられているのでした。ポートが出力として設定されている場合は、1や0を書き込むことでHやLが出力されます。また入力の場合は読み出すことで、ポートのHやLを1や0で返してくれます。 ところが入力の場合に書き込むとどうなるでしょう。C8051では、1を書き込むことによってHi-Zの状態、0を書き込むことによってGNDとショート(厳密にいうと、オープンドレインのFETがONになって、電流を引き込む)になるのです。そのため、P1.1に一度0が書き込まれてしまうと、他のマイコン等ががんばってHを出力しても、電流がどんどん吸い込まれLとなってしまうのでした。 『えっ、入力ポートに書き込んでないんじゃないの?』と思われた方(主に僕)、コードをよくご覧ください。演算子として、|= や &= が使われていますね。この演算子が意味するところは、一度読み出したレジスタを加工した上で、またレジスタに代入するということです。ということは入力ポートとして設定したP1.1にも、当然書き込み処理は行われているのです。これに気づくのにかなりの時間を要しましたorz 結果、僕が使っているC8051では、例題としてあげたコードは、次のコードに書き換える必要がありました。 if(P1 & 0x02){P1 = (P1 | 0x01) | 0x02;}else{P1 = (P1 & ~0x01) | 0x02;}
最後にですが、汎用ポートを動かす際、レジスタ単位ではなく、ピット単位で動かせるものは、今回のような誤動作を避けるためにもピット単位での操作(P1.0 = 1; P1.0 = 0;)をするべきたと思いました。 コメント
コメントする
|
検索君
スポンサード リンク
最近の記事 HDL-AAX2 シャットダウンスクリプ… 曜日を求める(8bit範囲で) Assisted GPS (A-GPS)… HDL-AAX2の修理 ExcelでMarkdownの表を編集 Rubyで確率分布の性質を求めるgem Windowsのcygwin/MSYS2… RubyでGPS姿勢推定 RubyでGPS受信機 boost::math::distrib… E-MailRelay本体更新(ver … RinRuby (Ruby gem fo… RSpecでのexample間共用のイン… 夏休みの工作: ソースコード公開 夏休みの工作: タッチセンサ GPD Pocketに増設したストレージ… GPD Pocketにストレージ増設 GPD Pocket 内蔵USBハブ基板… GPD Pocket 内蔵USBハブ基板 久しぶりの基板作成 自転車用六角穴付き特注ナット Xiaomi Mi Max (Hydro… Xiaomi Redmi Note 3 … Super Sylphide 進捗状況(… Super Sylphide 進捗状況(… かてごり~一覧 Aero & Astro (100) Computer (189) Embedded System (308) Info (14) Mountain (43) Movable Type (28) Movie & Animation (20) Music (9) Photo (47) Site Management (46) Timely (135) Tips (68) 今月かれんだ~ あ~かいぶ 最近のTrackback ダイナミックDNS 3domain.hk… @ 3年落ちのPCでまだまだがんばる日記 9X到着〜インプレ@ 艦船プラモとRCマイクロヘリが好き! USL-5P@ 谷岡のページ (PukiWiki/TrackBack 0.3) [mbed][猫カメラ]猫カメラつづき@ Embedded 脇見運転 [mbed][猫カメラ]mbed + 猫…@ Embedded 脇見運転 MT4 @ ダイナミックで動く画像リサイ…@ wed@ 私がAudionoではなくBlackfi…@ Blackfin空挺団::Blog 【Web】はぐれメタルできたよー@ I'm St'a'dying English ちっとも、作っていない@ 三D坊主 猫カメラ@ 脇見運転 To 『猫カメラ』 試作中 最近のこめんと いきなりのコメント申し訳ありません。
… by まろまろ先輩 @ GPD Pocket 内蔵USBハブ基板 音楽を読み取りする 説明して欲しいですby 榎本待子 @ iPodからPCに曲を転送 Arduino嫌いだわ。
あんなもの見…by Alice @ 僕がArduinoを使わないわけ やや遅い書き込みで失礼します。
別の機…by LOSスマホ @ Xiaomi Mi Max (Hydrogen) の MIUI8 FM Radio (stock) 日本バンド対応 >Bさま
確か当時、そこまで高くなかっ…by fenrir @ MKS Promenade-Ezy ケージ交換 お値段はおいくらでしたか?
私も曲げて…by Bさま @ MKS Promenade-Ezy ケージ交換 >forester3さん
お返事遅くな…by fenrir @ EZUSB Keilからsdccへ、EZUSB.lib等の移植 お世話になります。3年ほど前sdccの…by forester3 @ EZUSB Keilからsdccへ、EZUSB.lib等の移植 以下のものはどうですかねby て @ VBAで泣かないために >tomi9さん
コメント気づくのが遅…by fenrir @ TCM8240MD breakout (i2cで画像取得モジュール) 動作確認完了 りんく集 |