マイクロコントローラの異なるポートの個々のピンをレジスタにマッピングし、レジスタ値を変更するときにそれらの値を変更できますか?


12

Q:マイクロコントローラーの異なるポートの個々のピンをレジスタにマッピングし、レジスタ値を変更するときにそれらの値を変更できますか?

シナリオ:マイクロコントローラーの各ポート(8ビット)からいくつかのピンを使い果たしました。次に、8ビットバスを必要とするデバイス(D0〜D7 IN SEQUENCEを想定)をインターフェイスさせます。つまり、1対1で接続できるように、コントローラーから8ピンが必要です。

portx0  -> D0 // x is the name of port followed by bit location on that port
portx1  -> D1
...
portx7  -> D7

しかし、このデバイスと接続できる8ピンのポート全体ではなく、portxのピン、portyのピン、portzのピンがあります。新しい接続シナリオは次のとおりです(それぞれマイクロコントローラーからデバイスへの接続)。

portx0  -> D0
portx1  -> D1
portx2  -> D2
porty4  -> D3
porty5  -> D4
porty6  -> D5
porty7  -> D6
portz1  -> D7

この状態で値を送信したい場合は

unsigned char dataReg = 0xFA;

コントローラからデバイスに送信する値に対してビット単位の操作を実行し、レジスタの値に従って各ピンを個別に設定する必要があります。例えば

portx0 = ((dataReg & 0x01) >> 0 );  // Masking and shifting as bit position
portx1 = ((dataReg & 0x02) >> 1 );
portx2 = ((dataReg & 0x04) >> 2 );
porty4 = ((dataReg & 0x08) >> 3 );
porty5 = ((dataReg & 0x10) >> 4 );
porty6 = ((dataReg & 0x20) >> 5 );
porty7 = ((dataReg & 0x40) >> 6 );
portz1 = ((dataReg & 0x80) >> 7 );

さて、主な質問に来て、異なるポートの各ビットでこれらの個々の計算を避けるために、マイクロコントローラーの異なるポートの個々のピンをレジスタにマッピングし、レジスタ値を変更するときにそれらの値を変更できますか?


1
私は少し前に同じ考えを持っていました。:PICのでは、これは不可能であるmicrochip.com/forums/tm.aspx?high=&m=696277 -私はそれがどのマイクロでは可能だとは思いませんが、お使いのデバイスを一覧表示することは有用であろう。

回答:


6

あなたの質問は、ファームウェアに8ビット値があり、それをポートピンの任意のコレクションとの間で読み書きしたいということです。

これを行うハードウェアの直接的な方法はありません。2つのルーチンを作成する必要があります。1つは8ビット値を読み取り、もう1つは書き込みです。他の人はユニオンの使用に言及していますが、それは悪い考えです。ユニオンでは、すべてのビットを個別に処理する必要があり、コードはマイクロのビット順序に依存します。8ビットすべてが完全に独立して散らばっている場合、これはとにかく行く方法かもしれません。その場合、ビットごとに特別なコードを作成する以外にできることはほとんどありません。

これを行うためのより良い方法は、特に物理ポート上のいくつかの連続したチャンクにビットをグループ化できる場合、マスキング、シフト、ORを使用することです。たとえば、内部バイトの下位3ビットがポートのビット<6-4>にある場合、そのポート値を右に4シフトし、7とANDして、それらのビットを最終位置に配置します。他のポートからビットをシフトしてマスク(またはマスクしてシフト)し、結果をORすることで最終的な8ビットバイトを組み立てます。

この種の低レベルのビット調整は、Cよりもアセンブラで行う方が簡単です。おそらく、バイト読み取りおよび書き込みルーチンを単一のアセンブラモジュールに入れて、Cからインターフェイスを呼び出し可能にします。


6
私の答えは、アセンブリをまったく使用しないことを除いて、あなたの答えとほとんど同じです。ビット操作はCではささいなことです。コンパイラの特定のC呼び出し規約とリンカの実行方法を(再)学ぶのは頭痛の種になると思います。コンパイラとそれが物事をどの程度難しくするかに本当に依存しています。:
akohlsmith

@アンドリュー:マジで?呼び出し規約は、アセンブリコードとのインターフェイスが必要になる可能性のあるコンパイラマニュアルで明確に説明されています。ビット操作はCで記述するのは「簡単」かもしれませんが、これはコンパイラが恐ろしいコードを生成できる領域です。速度やコードスペースが問題にならない場合は、使いやすいものを使用してください。低レベルのビットをいじるのにアセンブラの方が使いやすいので、それを使用します。これが低レベルの速度重視のルーチンである場合は、アセンブラーで実行する必要があります。本当に簡単なはずです。
オリンラスロップ

1
私が言っているのは、ビット操作のように些細なことのためにそれをいじりまわさなければならないということは、それに対する非常に正当な理由がなければ私がすることではないということです。彼のパラレルバスの詳細はわかりませんが、ほとんどのバスにはすべてのバスピンの「アトミックな」更新の必要性を排除するストローブ信号があるため、アセンブリにドロップすることは不必要な最適化と不要な複雑さです簡単な)。
akohlsmith

@Andrew:自分が何をしているのかわからない場合にのみ、複雑になります。本当の問題は、一部の人々がアセンブラーを恐れており、それをよく知らないことだと思います。それは間違いです。ツールボックスですぐに使用できるツールである必要があります。あなたがそれをよく知らないか、それを不快に思っているなら、あなたは物事が他の方法でどうされるべきかを常に正当化するでしょう。アセンブラーとHLLを同じようによく知っていると、アセンブラーで簡単になることがあります。ほとんどの人はそうしませんが、それはアセンブラーの使用ではなく、彼らの問題です。
オリンラスロップ

2
私は多くのマイクロコントローラー/マイクロプロセッサーのアセンブリー言語に精通しています。私はそれがすぐに使えるツールであるべきだとは思わない。通常、非常に低レベルの初期化、タイミングまたはサイズが重要なコード、またはより一般的な場合、すでにボトルネックであると判断した領域の最適化のために、必要な場合にのみ慎重に使用する必要があります。アセンブリにジャンプする著者が、あまり明確でないコードを書いたり、アルゴリズムが誤って適用されていることを認識しないことが多いプロジェクトを見つけました。私はそれがあなただと具体的に言っているのではなく、もっと一般的な場合です。
akohlsmith

4

一般的にこれは不可能です。私の知る限り、PICでは不可能です。

これを実行できるマイクロコントローラはサイプレスPSoCのみです。高度に構成可能なシステムオンチップです。できることの多くは、文字通り独自のレジスタ(1〜8ビット)を定義して、好きなピンや内部回路に接続することです。

PSoC配線

たとえば、ここでは6ビットの制御レジスタを作成しました。5ビットはピンに直行し、6ビット目は7ピンからの入力とXORを使用しています。

PSoCピン

チップ上で、これらのピンを利用可能なGPIOピンのいずれかに割り当てることを選択できます。(画像の灰色のものです)


1
機能はピンに自由に割り当てることができるため、LPC800でも実行できるはずです。
スターブルー

-1

以下を試すことができます。2つのポート(使用される)のそれぞれのピンにマップする独自の構造を記述します。このレジスタの値を更新すると、これらの2ポートのピンが設定/リセットされます。試してみて、うまくいったかどうかを教えてください!!

これでうまくいくと確信しています。


2
Cでは、構造体をメモリ位置にマップでき、構造体のビット(ビットフィールド)をビットオフセットにマップできますが、コンパイラが「中間」ビットを乱すことを防ぐ方法はありません。 「全体」構造を単一の整数値で表示する方法。これは機能しません。
ウーターヴァンOoijen

-1

質問を正しく理解していれば、Cで十分簡単です。

ジェネリック型宣言は、任意のレジスタに再利用できます。

typedef union    // Generic 8-bit register Type
{
  uint8 reg; // Whole register
  struct
  {
    unsigned  bit7     : 1;  // Bit 7 
    unsigned  bit6     : 1;  // Bit 6 
    unsigned  bit5     : 1;  // Bit 5 
    unsigned  bit4     : 1;  // Bit 4 
    unsigned  bit3     : 1;  // Bit 3 
    unsigned  bit2     : 1;  // Bit 2 
    unsigned  bit1     : 1;  // Bit 1 
    unsigned  bit0     : 1;  // Bit 0 
  } bit;
} typ_GENERIC_REG8;

したがって、ポートを定義するには、次のように対処します。

#define MCU_GPO_PORTx   (*(volatile typ_GENERIC_REG8 *)(0x12345678)) // Number is address

そして、そのポートのピンを直接いじるには:

#define MCU_PORTx_PINn  (MCU_GPO_PORTx.bit.bit0)

コード内:

MCU_PORTx_PINn = 1; // Set pin high

登録全体:

MCU_GPO_PORTx.reg = 0xF; // All pins high

構造体、共用体、typedef、enumを読む価値は十分にあります。これらのすべてが、組み込みおよび一般的に非常に便利です!


OPは、異なるポートからの複数のビットを「1バイト」に結合したいと考えています。これがどうなるかわかりませんか?Olin Lathrop 、なぜそれが不可能なのかを説明します。

これは実際には問題に対処しておらず、コンパイラの「smrt」の程度によっては、デバッグするためのまったく新しいトラブルが発生する可能性があります。
akohlsmith
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.