2019年07月20日 | 更新。 |
GPIOとは、汎用入出力ともいい、マイコンなどのICやその他電子機器のデジタル入出力ピンの内、特定の用途が決まっておらず、ソフトウェアの指示により様々な機器との信号のやり取りに使える物です。通常は設定により、ピン単位(ビット単位)で入力ピン、出力ピンのいずれにも設定できます。また設定により、プルアップ抵抗やプルダウン抵抗を接続したり、入力信号の論理の変化により割り込みを発生させる事ができる様になっている場合もあります。
複数のGPIOピンの信号の入力や出力をまとめて行う構造になっている場合、入力や出力の単位になるGPIOピンのまとまりをGPIOポートと呼びます。GPIOポートのピン数は、CPUのデータバスのバス幅に合わせてある場合が多いです。
以下の説明では、主にマイコンのGPIOについて説明します。
入力と出力を組み合わせて入出力あるいはI/Oといいます。I/OはInput/Outputの略です。
また、何らかの信号(あるいは情報)を、入出力するためのピンを入出力ピンあるいはI/Oピンといいます。
狭義では信号の入力と出力のどちらにも使えるピンの事を入出力ピンといいます。
広義には、入力と出力の両方に使われるピンと、もっぱら入力に使われるピン(入力ピン)と、もっぱら出力に使われるピン(出力ピン)の3種類のピンの総称として入出力ピンという言葉が使われます。
デジタル信号(論理信号)の入出力に使われるピンをデジタル入出力ピンといい、アナログ信号の入出力に使われるピンをアナログ入出力ピンといいますが、GPIOはデジタル入出力ピン(あるいは複数のデジタル入出力ピンの集まり)の一種です。
参考:ただし、A/D変換器の入力など、アナログ入出力の機能と、GPIOの機能が、同一のピンに多重化される事もあります。
マイコンやFPGAなど、情報や信号を処理するためのデジタルICの場合、それらのピンのほとんどが、入出力ピンです。逆に入出力以外に使われるピンは、電源ピン、クロック信号の発振のために水晶発振子などが接続されるピンなど、一部のピンになります。
ICの動作モードの設定のためにプルアップやプルダウンされるピンや、リセット信号を入力するピン、ICの基本クロックとなるクロック信号を入力するピン(外部のICとの通信の際の同期クロック信号の入力用のピンは除く)、A/D変換器あるいはD/A変換器の基準電圧を入力するピンなどは、信号を入力するためのピンではありますが、それらのピンに入力された信号をICが積極的に処理をする訳ではないので、通常は、入力ピンあるいは入出力ピンとはみなされません。
マイコンの場合、CPUにはタイマ、UARTインターフェース、SPIインターフェース、I2Cインターフェースなど、色々な周辺回路を内蔵しています。そして、それらの周辺回路が使う入出力ピンは、特定のピン番号に割り当てられている場合がほとんどです。(GPIOも周辺回路の一種ではありますが、ここでいう周辺回路からは除外して考えています)
周辺回路を通じて入出力ピンで信号をやり取りする場合、CPUが初期設定をすると、後の複雑な処理は、その周辺回路が自動的にやってくれます。例えば、SPIバスに8ビットの信号を送信したい場合、CPUがSPIインターフェースに送信したい8ビットの情報を設定すれば、その後はSPIインターフェースが情報を1ビットずつ自動的に送信してくれます。
この事により、マイコンのプログラムが簡略化されたり、CPUと周辺回路の並列処理が可能になったりしますが、一方で、周辺回路に割り当てられた入出力ピンは、特定の処理にしか使えません。
GPIOの場合は、CPUが入力値を読み込むように指令した時に入力値を読み込み、CPUがHを出力する様に指令した時にHを出力し、CPUがLを出力する様に命令した時にLを出力します。プログラム次第で、LEDの点滅やタクトスイッチの状態の取得の様な簡単な処理も行えるますし、SPIバスを経由して他のICと通信を行うといった高度な処理まで、色々な用途にGPIOを使う事ができます。これが汎用入出力の「汎用」の意味なのです。
GPIOは汎用ですから、もちろんSPIバスに信号を送信する事もできますが、1ビットずつ信号を送信するループをプログラムで記述する必要があります。また、1ビット信号を送信するにも、クロック信号の制御と出力信号の制御の両方をCPUが行う必要があります。この様に、GPIOを用いて複雑な制御を行うと、ソフトウェアも複雑になります。
さらに、GPIOで通信などの時間がかかる処理を行う場合、その処理をしている間はCPUがその処理に専念しなければならないため、SPIバスで信号を送信している間にCPUが別の計算を行うといった、並列処理が行えません。この様に、GPIOで処理を行うと、柔軟に色々な用途に使える反面、処理速度が出にくい問題があります。
ほとんどのマイコンでは、入出力ピンの機能が多重化されており、1つの入出力ピンに複数の機能が割り当てられています。入出力ピンに割り当てられた機能のうち、実際にどの機能が有効になるかは、マイコンの設定によります。
現在生産されているマイコンでは、ほとんどの場合、ほぼ全ての入出力ピンは、GPIOと他の周辺回路とで共有されています。その事を表したのが図1です。
図1は架空のマイコンの内部構成を示しています。
実際のマイコンでは、プログラムを動作させるためのメモリ(フラッシュメモリやRAM等)が内蔵されていますし、クロック発振回路がなければCPUが動作しません。しかしこの図では、入出力ピンの多重化の説明に関係のない要素は省略し、極力単純化されています。
図1のマイコンでは、GPIO、SPIインターフェース(以下、単にSPIとよびます)、およびUARTインターフェース(以下、単にUARTと呼びます)の3つの周辺回路が内部バスを通じてCPUに接続されています。
GPIOは8本、SPIは4本、UARTは4本の入出力ピンをそれぞれ利用します。これを単純に実現しようとすると、合計で16本の入出力ピンが必要になります。しかしICは、入出力ピンの本数が多くなるほど製造コストが上昇しますので、できるだけ入出力ピンを少なくしたいのです。
参考:ICの価格を決める一番大きな要素は、ICチップの面積です。大雑把に言えば、面積にほぼ比例する製造コストがかかると考えてもいいでしょう。技術の進歩により以前より配線のピッチが微細化し、同一の面積でも、大規模な回路が詰め込めるようになりました。よって、コストを上げずに複雑な機能が実現する様になってきているのですが、入出力ピンについては話が別です。入出力ピンの制御回路は、出力時に大きな電流を扱う関係で、細い配線がICに作りこめる様になっても、小さくする事ができないのです。よって、配線の微細化技術の進歩にかかわらず、入出力ピン1本あたりの製造コストは下がりません。
そこで、図1の様に、GPIOのP0~P3の4本の信号は、SPIの信号(SCLK、MISO、MOSI、およびSS)と同じ入出力ピンに割り当て、GPIOのP4~P7の4本の信号はUARTの信号(RX、TX、RTS、およびCTS)と同じ入出力ピンに割り当てれば、合計で8本の入出力ピンに抑えられます。
GPIOのP0信号に関して言えば、UARTのSCLK信号と同じ入出力ピンに割り当てられています。そこで、その入出力ピンには、割り当てられた2つの信号名を並記して、P0/SCLKという名称が付けられています。
P0/SCLKピンにおいて、P0の機能とSCLKの機能は排他的です。つまり、P0の機能とSCLKの機能は同時には使えず、どちらかを選択して使わなければなりません。
その選択機能を実現するのがマルチプレクサです。マルチプレクサは、制御信号により、P0とSCLKの2つの信号の内1つを選択して、P0/SCLKピンに接続します。P0とSCLKのどちらの信号を選択するかを決める制御信号は、SPIのCTRL信号です。
注:ここでは、マルチプレクサとしてアナログスイッチを用いた双方向的のマルチプレクサを仮定しています。デジタル回路を用いた単方向のマルチプレクサを使うなら、入出力ピンを入力モードで使うか、出力モードで使うかを設定する信号線が、追加で必要になります。
マイコンにリセットがかかった直後の初期状態では、通常、GPIO以外の入出力ピンを使う周辺機能(図1ではSPIとUART)は無効化されており、マルチプレクサはGPIOの信号(P0/SCLKピンにおいてはP0信号)を入出力ピンと接続する様に設定されています。
しかし、GPIO以外の周辺回路(P0/SCLKピンにおいてはSPI)がCPUの指令により有効化されると、マルチプレクサの制御信号(CTRL信号)が変化して、GPIO以外の周辺回路の信号(P0/SCLKピンにおいてはSCLK信号)が入出力ピンと接続される様になります。
この様にして、I/OピンがGPIOと他の周辺回路とで共有されています。
もちろん、図1の回路ではGPIO、SPI、UARTの3つの周辺回路の機能を、全部同時に有効にする事ができません。
SPIとUARTが共に無効の場合は、全ての入出力ピンがGPIOに割り当てられます。
SPIが有効でUARTが無効の場合は、P0/SCLK、P1/MISO、P2/MOSI、およびP3/SSの4つの入出力ピンはSPIに割り当てられ、P4/RX、P5/TX、P6/RTS、およびP7/CTSの4つの入出力ピンはGPIOに割り当てられます。
SPIが無効でUARTが有効の場合は、P0/SCLK、P1/MISO、P2/MOSI、およびP3/SSの4つの入出力ピンはGPIOに割り当てられ、P4/RX、P5/TX、P6/RTS、およびP7/CTSの4つの入出力ピンはUARTに割り当てられます。
SPIとUARTが共に有効の場合は、P0/SCLK、P1/MISO、P2/MOSI、およびP3/SSの4つの入出力ピンはSPIに割り当てられ、P4/RX、P5/TX、P6/RTS、およびP7/CTSの4つの入出力ピンはUARTに割り当てられます。
この様に、同時に使える機能に制限が生じてしまいますが、マイコンの全ての周辺回路を同時に使う事は少ないので、図1の様に入出力ピンの機能を多重化する方法は、コストと柔軟性のバランスが取れた、良い方法なのです。
図1では、話を簡単にするために、1本の入出力ピンに2つの機能を割り当てていますが、現実のマイコンでは、1本の入出力ピンに、3種類以上の機能を割り当てる事もよくあります。
ArduinoにおけるGPIOの扱いについて説明します。
Arduinoにおいては、各GPIOピンに0番から始まる数字が付いています。
GPIOピンの入出力の向きを指定するには、pinMode関数を使います。pinMode関数には2つの引数があり、1番目の引数はピンの番号を、2番目の引数は入出力の向きを表わします。
例えば次の様にすれば、3番ピンを入力ピンにする事を表わします。
pinMode(3,INPUT);
pinMode関数の第2引数に使う定数の一覧を、表1に示します。
定数 | 意味 |
---|---|
INPUT | 入力(プルアップ抵抗なし) |
INPUT_PULLUP | 入力(プルアップ抵抗あり) |
OUTPUT | 出力 |
入力に設定されたGPIOピンから信号を読み出すには、digitalRead関数を使います。digitalRead関数の引数は一つで、その引数はピン番号を表わします。
例えば次の様にすれば、変数iに、3番ピンの論理レベルが読み出せます。
int i=digitalRead(3);
digitalRead関数の返り値は定数HIGHまたは定数LOWになります。それぞれの定数は、表2の様に定義されています。これらの定数は、後述するdigitalWrite関数でも用います。
定数 | 意味 |
---|---|
HIGH | 論理レベルのH(または1)。 |
LOW | 論理レベルのL(または0)。 |
出力に設定されたGPIOピンに信号を出力するには、digitalWrite関数を使います。digitalWrite関数には引数が2つあり、1番目の引数はピン番号、2番目の引数は出力する論理レベル(HIGHまたはLOW)を表わします。
例えば次の様にすれば、3番ピンにHを出力します。
digitalWrite(3,HIGH);