R8C/M12でのポート入出力設定について

R8C/M12を趣味で使っております。

今回、ポートの入出力で、想定外の動作をしたので、質問させて頂きます。
条件として、
P1-3ポートは、オープンドレインで外部プルアップ
P1-7ポートは、オープンドレインで外部プルアップ
で、それに合わせてレジスタの設定を行っています。

ここで、

bclr 3\,PD1  ;input-dir
bclr 7\,PD1

bclr 3\,P3 ;out-data-set
bclr 7\,P3

bset 3\,PD1 ;output-dir
bset 7\,PD1
bclr 3\,PD1 ;input-dir
bclr 7\,PD1
bset 3\,PD1
bset 7\,PD1
bclr 3\,PD1
bclr 7\,PD1

と記述した時、P1-3の出力ラッチレジスタの内容が1に
変化している様な動作をします。
(この時、P1-3のポートレベルは1です。)
端子レベル強制読み出しビットは0で変更していません。

P1-7など1ビット単体で変更する際に、変更する以外のビットでは出力レジスタの値でなく、入力レジスタの値が反映される様な気がします。

お手数ですが、ご教示ください。
マニュアルの注意記述など指示頂ければ幸いです。
  • さるさん

    R8C/M12aのポートは入力読み出しと出力設定が共通(ポートレジスタ)になっています。従って、さるさんの操作を行った場合、(外部プルアップされていることから)入力に切り替わった時点でP1.xはSETされます。再度出力に替えた時、前回のP1.xはSETのためHIGHが出力されます。

    ; pull-upによりP1.3\,P1.7がhigh
    bclr 3\,PD1 ;input-dir
    bclr 7\,PD1

    bclr 3\,P3 ;out-data-set
    bclr 7\,P3

    ; P1.3\,P1.7がhighのため、O.D.highを出力
    ; 以降、P1.3\,P1.7は常にhigh
    bset 3\,PD1 ;output-dir
    bset 7\,PD1
    bclr 3\,PD1 ;input-dir
    bclr 7\,PD1
    bset 3\,PD1
    bset 7\,PD1
    bclr 3\,PD1
    bclr 7\,PD1

    入力と出力でレジスタが分かれているマイコンでは起きない現象です。

    すと@embedded property
  • すとさん

    早急なご回答ありがとうございます。
    入力と出力のレジスタが一緒だと言うことで了解しました。

    混乱した原因は、
    bclr 3\,PD1  ;input-dir
    bclr 3\,P1 ;out-data-set
    bset 3\,PD1 ;output-dir
    bclr 3\,PD1 ;input-dir
    bset 3\,PD1
    bclr 3\,PD1

    とした際に、P1.3はHi-Low出力します。

    ですが、
    bclr 3\,PD1  ;input-dir
    bclr 3\,P1 ;out-data-set
    bclr 7\,P1 ;(btst 7\,P1でも同じ)
    bset 3\,PD1 ;output-dir
    bclr 3\,PD1 ;input-dir
    bset 3\,PD1
    bclr 3\,PD1

    と記述すると、ご教授頂いた通り、P1.3はHi固定になります。

    これから入出力バッファの変更タイミングは、設定レジスタを入力に変更タイミングですぐに変更されるわけで無く、設定レジスタを変更した後に、該当の入出力レジスタをR/Wした時に同時に反映される様です。

    原因が判ってスッキリしました。
    ありがとうございました。
  • ちょっと心配し過ぎなんですが、

    ポートの出力値を設定(レジスタPxに記述)してから、入出力設定を変更(PDxを出力に変更)する際に、
    Px記述→PDx記述までの間に、割り込みが発生し、割り込み先で、Pxの読み出しを行うと、先に記述したPxの内容が変化するって事ですね。

    ポートの入出力設定は頻繁に行いませんが、入出力設定を出力にする際には、入出力設定の前後で出力値を記述するのが良さそうですね。
    もしくは割り込み禁止状態で記述するのが良さそうです。

    でも気にし過ぎかなぁ。

  • スタッフのチョコです。

    さる様の「Re:R8C/M12でのポート入出力設定について」にコメントさせていただきます。

    最初のスレッドの処理と内容が異なっているようです。この処理であれば,以下のように説明は可能です。

    > 混乱した原因は、
    > bclr 3\,PD1  ;input-dir
    > bclr 3\,P1 ;out-data-set
    > bset 3\,PD1 ;output-dir
    > bclr 3\,PD1 ;input-dir
    > bset 3\,PD1
    > bclr 3\,PD1
    >
    > とした際に、P1.3はHi-Low出力します。

    この処理では,入力に設定している状態でラッチに0を書いたため,p1.3を出力にするとLowとなり,入力にするとプルアップ抵抗でHiになります。

    > ですが、
    > bclr 3\,PD1  ;input-dir
    > bclr 3\,P1 ;out-data-set
    > bclr 7\,P1 ;(btst 7\,P1でも同じ)
    > bset 3\,PD1 ;output-dir
    > bclr 3\,PD1 ;input-dir
    > bset 3\,PD1
    > bclr 3\,PD1

    > と記述すると、ご教授頂いた通り、P1.3はHi固定になります。

    これは,2つ目でラッチに0を書いていますが,入力に設定されているので,ラッチのデータは出力されません。
    3つ目で同じポートのほかのビットに対してビット操作を行ったことで,p1.3の内容(この場合には端子の状態Hi)が読まれてタッチに書き戻されたことで,ラッチの内容が0から1に書き変わってしまいます。
    そのため,p1.3を入力にするとプルアップ抵抗でのHiが,出力にしてもラッチの値が出力されてHiがp1.3端子に現れることになります。
    (スレッドの最初の記述内容では出力データの設定がp1ではなくp3に対して行われていたので,納得できる説明が見つかりませんでした。)
  • スタッフのチョコです。

    さる様の「極端な例として」にコメントさせていただきます。

    先ほど,回答番号4でコメントさせていただきましたが,若干混乱があるようなので追加でコメントいたします。

    > Px記述→PDx記述までの間に、割り込みが発生し、割り込み先で、Pxの読み出しを行うと、先に記述したPxの内容が変化するって事ですね。

    いいえ,Pxの読み出しだけでは変化いたしません。

    正しくは,「ポートのビットが入力になっている状態で,同じポートの異なるビットに対する操作(設定)を行うと,入力になっているビットのラッチの値は端子の状態に書き変わります。」です。

    これは,ポートに対するビット操作命令が専用のハードウェアでの実現ではなく,ポートに対するリード・モディファイ・ライトで処理されるためです。




  • さるさん

    どういった状況で使われるか?にもよるのではないでしょうか。

    非割込みと割込みでアクセスすることがあるなら、さるさんが仰るようにDI/EIによる挟み込みが有効ですよね。

    一方でI2Cの様な通信ライン制御を自前でやる場合、割込み処理内でR/Wを切り替えることもあると思います。そんな時は仕様上でタイミングチャートやフローを明記し視覚化をしておけば機能品質は保障しやすくなり、テストも実施しやすくなるのではないでしょうか。

    コスト要求や用途にもよると思いますが、ハード要件のハードルを上げ過ぎるとソフトが苦しくなります。ある程度のマイコン資源は確保できるといいですね。

    すと@embedded property
  • チョコさん

    ご回答ありがとうございます。

    ご指摘の通り最初のスレッドではP1とP3を間違って記述しました。
    状況はご指摘の通りで、現在では正常に動作しております。

  • チョコさん

    下記の説明がわかりやすくて助かりました。

    >正しくは,「ポートのビットが入力になっている状態で,同じポートの異なるビットに対する操作(設定)を行うと,入力になっているビットのラッチの値は端子の状態に書き変わります。」です。

    >これは,ポートに対するビット操作命令が専用のハードウェアでの実現ではなく,ポートに対するリード・モディファイ・ライトで処理されるためです。

    btst(読み出し)で変化した気がしたんですが、再度確認した限りでは、ご指摘の通り変化しませんでした。
  • すとさん

    やはりI2Cだと判りますか。
    そうですよね。

    出来るだけ転送レートを上げようとして、入出力設定だけを操作すればACKの確認と、クロックストレッチの確認を削減出来ると考えたんです。

    結果、ズルは出来ないって事ですね。

    ご教授ありがとうございました。
  • スタッフのチョコです。

    さる様の「Re:極端な例として」にコメントさせていただきます。

    > bclr 3\,P1 ;out-data-set
    > bclr 7\,P1 ;(btst 7\,P1でも同じ)
    この処理だけが問題であれば,以下のようにすることでp1.3とp1.7を同時に0にできます。(ほかのビットの値が問題になる場合には直接ポートに演算するだけでは済みませんが。)

    and.b #01110111b\,P1 ;out-data-set


    後は,ほかの処理でp1.3とp1.7のラッチの値を1にしないように注意しておけば,p1.7とp1.3の制御はPD1レジスタに対するビット処理で可能です。(こちらは,ほかのビットを気にする必要はありません。)

    なお,ラッチの値を0にしておいて,入出力の方向切り替えで,オープンドレイン出力を制御するのはよくやる方法です。
    ただし,ポートを入力に切り替えても,すぐに端子の電圧が立ち上がるわけではありません。信号線の浮遊容量とプルアップ抵抗の値で決まる時定数で立ち上がっていきます。つまり,入力に切り替えてすぐに正しい値が読めるわけではないことには注意が必要です。