本講座は、ルネサスエレクトロニクス社(以降、ルネサス)のArm® Cortex®-Mプロセッサ内蔵マイコン RAファミリを使った初心者向けのマイコン入門講座であり、超基本的なマイコンに関する知識を既に習得されている方を対象としています。
超基本的なマイコンに関する知識を学ぶ場合は、APSのWebinar「 マイコンとは何?|マイコン超入門【第1部】」から始めて、「 テキスト応用実習|マイコン超入門【第5部】」までを学習してください。
本講座のゴール
- マイコンの基本的な使い方を理解する。
- マイコンの基本的な仕組みを、周辺機能ごとに理解する。
- マイコンの基本的な動作を、周辺機能ごとに理解する。
本講座の構成
第1回:開発ツール
第2回:CPU(Cortex-M)
第3回:汎用I/O
第4回:割り込み
第5回:汎用タイマ
第3回:汎用I/Oの内容
- 汎用I/Oの構成を理解する。
- 汎用I/Oの電気的特性を理解する。
- 汎用I/Oの使い方を習得する。
使用機材のご案内
本ハンズオンワークショップを実機にて体験いただくためには、EK-RA6M5 評価キットとPCが必要となります。
汎用I/Oとは
汎用I/Oとは、General Purpose Input/Output(汎用入出力端子)の事で、GPIO、汎用ポートなどと呼ばれることもあります。マイコンメーカによって、呼び名や表記が異なります。
マイコンの外部に接続されたデバイスから信号を受け取ったり、信号を出力したりするのが主な仕事です。内部は、入力部、出力部、制御部および周辺機能用の回路で構成されています。ソフトウェアにより任意に入出力方向や電圧レベルを設定できます。

図2:汎用I/Oとは?
汎用I/Oの用途について解説します。
最初は、電圧出力です。マイコンの電源電圧または汎用I/O専用電源電圧に準じた電圧を出力することができます。逆に、グランドレベル、すなわち0Vを出力することもできます。この機能を使うと汎用I/Oに接続されたLEDを点灯させたり、消灯させたりすることができます。
次に、入力電圧レベルの検知機能が挙げられます。下図の真ん中の図では、スイッチが入っていると汎用I/Oの電位は電源電圧と同じになり、入っていないと0Vになります。このように汎用I/Oに印加されている電圧を検知し、スイッチの状態を知ることができます。
入力電圧レベルの検知機能と電圧出力機能を使うと、汎用I/Oの入力信号に応じて、出力信号を変化させることができるので、例えば、スイッチを押すとLEDが点灯するというような制御が可能です。
すこし高級な機能では、周辺デバイスとのインタフェースを取ることに使います。例えば、通信機能やモーター制御やLCD表示などを汎用I/Oを使って行うことができます。

図3:汎用I/Oの用途
汎用I/Oの構成
下図に、一般的な汎用I/Oのブロック図を示します。
上部は入力回路で下部は出力回路です。端子の直近に保護回路があり、プルアップ/プルダウン抵抗は入出力で共通です。入力信号は入ってすぐにデジタル信号とアナログ信号に分かれます。
アナログ信号は入力電圧値が変わらないように直接A-Dコンバーターやオペアンプ(Operational amplifier)などのアナログ周辺回路へ入ります。デジタル信号は、さらにCPUへ行く信号と周辺機能へ行く信号に分かれます。多くの場合は、いったんレジスタなどの回路でラッチされて、処理されます。ラッチとはデータを一時的に保存することです。
出力信号も、デジタル信号とアナログ信号で経路が異なります。デジタル信号はCPUから来る信号と周辺機能から来る信号で経路が異なりますが、出力制御回路を経て、出力バッファから出力されます。アナログの出力信号はデジタル回路を経由せずに直接I/O端子につながりますので、出力電圧が変わらずそのまま出力されます。
それぞれの回路は、電源を含め独立していて、相互に干渉しないように作られているため、多くの機能を1つのI/O端子に担わせても問題は発生しません。
端子を入ってすぐのところには、保護回路用のダイオードが付いています。これは、EOS(Electrical Over Stress)やESD(Electro Static Discharge)からマイコンを守るためのものです。
一般的には、正電位の高電圧ノイズが入った場合は電源電圧側へ、負電位の場合は、GND側へノイズを逃がす方向にダイオードが付けられています。
しかし、最近のマイコンの汎用I/Oには、5V耐圧の端子があって、電源電圧を3V近辺で使用しても、端子には5Vを印加できます。この場合下図に記載している保護ダイオードでは、端子の5V電源から、マイコンの3V電源に電流が流れてしまいます。そこで、5V耐圧端子の保護ダイオードは一般的な保護回路とは異なる方式を採用しています。具体的な方式は、各マイコンメーカで異なる上に、企業秘密なので詳しく説明できませんが、電源側の保護ダイオードを、端子に5V以上が印加されるまではオフのままにしておき、5V以上のノイズ電圧が印加された場合にオンにすることで、電源またはGNDに逃がして端子を保護します。
この図では、内蔵のプルアップ/プルダウン抵抗を、スイッチと抵抗の等価回路で記述しましたが、実際はプルアップ抵抗にはPMOS、プルダウン抵抗にはNMOSを使います。どちらのMOSもオン抵抗が数百から数十オームになるような特性に設計しておけば、オンオフのできる抵抗がMOS単体で実現できます。

図4:汎用I/Oの内部構成
I/O端子から入ってきた信号はアナログ信号(A-Dコンバーターやオペアンプの入力など)とデジタル信号(CPUと周辺機能用)で、経路が分かれます。
アナログ入力信号は主にA-Dコンバーターやオペアンプやコンパレーターの入力端子として使用する場合です。途中でデジタル回路が入ると、電圧が変わってしまうので、端子から直接アナログ回路へ入ります。
デジタル信号は、入力バッファ経由で、CPUまたは周辺機能の入力データレジスタへ入るか、直接、周辺機能へ入ります。
入力バッファは、シュミットトリガタイプのインバーターで記述しましたが、いろいろな種類の入力バッファがあります。また、必ずしもシュミットトリガ特性を持っているとは限りません。実際の入力バッファについては、各マイコンのマニュアルやデータシートなどを参照してください。
入力バッファを通った後の信号は、CPUと周辺機能の2つの経路に分かれます。端子を周辺機能の端子として使っている場合は、周辺機能に入ります。
CPUが信号を汎用I/Oの入力データとして読み込む場合は、いったんレジスタ(汎用I/Oデータレジスタ)で保持されます。そのレジスタは、データバス経由で読むことができます。

図5:汎用I/Oの入力部の構成
周辺機能へ行く信号は、周辺機能によって保持される方式が変わります。
UARTやSPI(シリアルペリフェラルインタフェース:Serial Peripheral Interface)などの通信機能の場合、信号は入力データバッファレジスタなどのレジスタで一度保持されてから処理されます。また、タイマの入力キャプチャー信号などは、エッジのタイミングが変わらないように、そのままカウンターの値をキャプチャーするトリガ信号として使われます。

図6:実際の通信機能(SPI)の入力回路
出力部も、デジタル系(CPUと周辺機能用)とアナログ系(D-Aコンバーターやオペアンプの出力など)に分かれます。アナログ出力信号では、D-Aコンバーターやオペアンプの出力端子として使用している場合、入力部と同様、電圧が変わらないように、デジタル回路を経由しないで、直接端子につながります。デジタル出力信号の経路はCPUと周辺機能からの2経路あります。
出力制御回路は出力バッファのPMOSとNMOSを制御して、High(ハイレベル)、Low(ロウレベル)、H-Z(ハイインピーダンス)を選択します。最近のマイコンは、ほとんどの端子が大電流を流せる仕様になっているので、出力バッファのPMOSとNMOSは駆動能力が高いMOSが使われます。
汎用I/Oとして使われる場合、CPUはソフトウェアに従って、出力データを内部データバス経由で、出力データレジスタへ入れます。データを入れる前に、端子を出力端子に設定(各端子の出力制御レジスタを設定)しておくと、出力データレジスタを書いた直後に端子から、データが出力されます(通常は、同時または1システムクロックサイクル後)。
また、データレジスタを書いた後に出力端子に設定すると、出力端子に設定した直後に、端子からデータが出力されます。どちらにするかは、ユーザーが選べます。
周辺機能の出力データとしてはUARTやSPIの通信機能の出力データやタイマのPWM出力信号などがあります。UARTやSPIなどの通信機能の場合は、出力データをバッファレジスタなどのレジスタで一度保持し、その後通信をスタートさせると、データが端子から出力されます。タイマのPWM出力信号などは、エッジのタイミングが変わらないように、そのままデジタル値として出力されます。

図7:汎用I/Oの出力部の構成
下図に、RA6M5のSPIの出力信号の経路を示します。ここで、出力データを一度保持するレジスタはシフトレジスタになります。SPIは1ビットずつシフトしながら出力し、シフトして空いたビットに入力データの1ビットが順次入るので、入力データレジスタと出力データレジスタは、シフトレジスタで兼用することになります。

図8:実際の通信機能(SPI)の出力回路
汎用I/Oの使い方
汎用I/Oだけでなく、マイコンに内蔵されている機能は、レジスタという記憶回路に決められた値を書き込む操作と、レジスタを読み出す操作で制御します。
汎用I/Oであれば、汎用I/Oを制御するレジスタと、出力値を設定するレジスタと、I/O端子から読み込んだ値を保存するレジスタがあり、それらに適切な値を書き込んだり、読み出したりして制御します。
SPIのような通信機能であれば、SPIを制御するレジスタがあり、そのレジスタを設定することにより。通信のモード、通信速度などを設定します。また、送信するデータを設定するレジスタや、読み込んだデータを保存するレジスタがあります。
少し細かくなりますがI/Oポート(汎用I/Oの論理回路部)の構造を説明します。I/Oポートは2つのMOS(Metal Oxide Semiconductor)で構成されます。MOSとはトランジスタの一種でスイッチング素子です。
スイッチング素子は外部につないだ機械的スイッチと同じ役目を果たします。電気信号が入るとONしたりOFFしたりします。すなわち、人がスイッチを押す動作を電気信号で行うことができます。マイコンの中の電源とマイコンの端子につながったLEDの間に入ってLEDをON、OFFします。
MOSには2種類あって、電源側のスイッチングをするPMOSとグランド側のスイッチングをするNMOSですPMOSがONするとLEDは電源に接続され点灯します。NMOSがONするとLEDはGNDに接続され消灯します。I/Oポートは それを制御するレジスタを持っています。ここではMOSをONしたりOFFしたりするのに使われます。
では、LEDを点滅させる動作を、順を追って説明します。まず、ユーザーはフラッシュ・メモリにプログラムを書き込みます。そのプログラムは I/Oポートのレジスタに決められた値を書き込むプログラムです。
フラッシュ・メモリに書かれたプログラムはCPUによって読み出されます。そして、CPUは、そのプログラムに従ってI/Oポートのレジスタに決められた値を書き込みます。
最初にCPUはレジスタに「1」を書きます。すると、レジスタはI/OポートのPMOSがON、NMOSがOFFする電気信号を送ります。そのため、PMOSからLEDに電源が供給され、LEDは点灯します。次に、CPUはレジスタに「0」を書きます。レジスタはI/OポートのPMOSがOFF、NMOSがONする信号を送ります。こんどは、PMOSからLEDに電源が供給されなくなるのでLEDは消灯します。
これを繰り返すとLEDは点滅動作します。さらに点灯と消灯の間にCPUは時間を稼ぐプログラムを入れると、一定間隔で点滅を繰り返します。

図9:I/O端子を出力として使う仕組み
次に、I/O端子を入力として使う仕組みを説明します。
CPUは、ユーザーが作ったプログラムに従って、汎用I/Oのレジスタに決められた値を書き込み、入力に設定します。入力に設定されたI/O端子の電位を取り込んで、入力データを保存するレジスタに取り込んだ電位に相当するデジタル値(1また0)を保存します。
CPUは、そのレジスタは値を読むと、I/O端子のデータを得ることができます。

図10:I/O端子を入力として使う仕組み
次に、SPIの入力端子として使う場合を例にして、I/O端子を周辺機能用端子として使う仕組みを解説します。
CPUは、ユーザーが作ったプログラムに従って、SPIのレジスタに決められた値を書き込み、SPIの機能設定をします。同じように、CPUは、汎用I/Oのレジスタに決められた値を書き込み、I/O端子をSPI用の入力端子に設定します。
CPUはSPIを起動します。SPIは、入力に設定したI/O端子経由で、入力データを取り込んで、入力データを保存するレジスタに保存します。CPUは、そのレジスタは値を読むと、SPIの入力のデータを得ることができます。

図11:I/O端子を周辺機能用端子として使う仕組み
汎用I/Oの電気的特性
「しきい値(Threshold)」とは、デジタル論理回路でハイレベルとロウレベルの2値の境をきめる値です。マイコンでは、一般的にMOSがオンする、またはオフする電圧を言います。
CMOSの場合は、特に論理しきい値と呼びます、PMOS、NMOS単独の場合は規定された電流値が流れる時のゲート電圧を言います。マイコンを使う際には、主に汎用I/Oの特性として使われます。データシートでは、電気的特性の中の、DC特性の汎用I/OのVIHとVILとして示されています。

図12:入力レベルVIH、VIL(しきい値)
VIHとVILは、データシートで規定されていますが、時々データシートの記述を誤解されているユーザーがいるので、ここで、RA6M5の特性を使って簡単に説明します。
まずVIHです。VIH Minの意味は、この電圧以上をハイレベルと認識する最低電圧という意味です。したがって、ここではVCC×0.7(V)以上を入力しないと、汎用I/Oはハイレベルと認識しません。VCCが3Vの場合に、VIH Minは3V×0.7=2.1Vになります。
次にVILです。VIL Maxの意味は、この電圧以下をロウレベルと認識する最高電圧という意味です。したがって、ここではVCC×0.3(V)以下を入力しないと、汎用I/Oはロウレベルと認識しません。VCCが3Vの場合に、 VIL Maxは3V×0.3=0.9Vになります。
理論的には、 VIHとVILは同じ電圧ですが、実際は若干差があります。データシートでは余裕度を考慮していますので、若干の差があります。ここでは0.4Vです。
VIHとVILに、意図的に差を持たせた端子をシュミットトリガ入力端子と言います。

図13:VIHとVILの定義
ロウレベルからハイレベルのしきい値と、ハイレベルからロウレベルのしきい値が異なることを、シュミットトリガ特性と言います。シュミットトリガ特性を持つ端子をシュミットトリガ入力端子と呼びます。
ハイレベルのしいき値とロウレベルのしきい値の差をヒステリシス特性と呼びます。データシートではΔVTで表記されています。ヒステリシス特性は、主に耐ノイズ性を高めるために用いられます。
リセット端子や割込み端子などで、ノイズ、すなわち電圧変動、チャタリングなどによる誤動作を防止するために用います。

図14:シュミットトリガ特性のしきい値
実習
押しボタンを使ってLEDを点滅させる。
実習内容を説明します。
I/O端子につながれたユーザーボタンS1(P005)を押すとI/O端子はロウレベルになります。CPUはI/O端子のロウレベルを検知すると、LEDがつながっているI/O端子をロウレベルにしてLEDを消灯させます。
また、ユーザーボタンS1(P005)を離すとI/O端子はハイレベルになります。CPUはI/O端子のハイレベルを検知すると、LEDがつながっているI/O端子をハイレベルにしてLEDを点灯させます。
プログラムとしては、汎用I/Oの電圧を読み込み、その値を、そのまま出力すると、ユーザーボタンを使って、LED点灯させたり消灯させたりすることができます。

図15:実習内容
プログラムのフローはいたって簡単です。「ユーザーボタン(P005)の情報を読み込む動作」と「ユーザーボタン(P005)の情報をP006に出力し、LEDを点灯/消灯させる動作」を繰り返せば良いだけです。

図16:プログラムフロー
I/Oポートの初期設定については、統合開発ツール(e2 studio)がすべて行ってくれますので、出力値を設定するHAL(抽象化レイヤ)関数だけを使います。
最初にI/Oポートのレベルを決めるLevelという変数を定義して、ロウレベルに初期化します。変数の定義には 「static bsp_io_level_t 」という関数を使い、この後ろに変数の名前levelを書けば定義されます。記述としては、次のようになります。
static bsp_io_level_t level
次に、levelの初期値をロウレベルに設定します。ロウレベルを表すHAL関数は、「 BSP_IO_LEVEL_LOW」 ですハイの場合は「BSP_IO_LEVEL_HIGH」です。
先ほどのlevelを定義した記述と等号(=)を使って、一度に初期値も定義できます。
記述は、次のようになります。
static bsp_io_level_t level = BSP_IO_LEVEL_LOW;
次にI/Oポートに「level」の値を出力する記述を作ります。
今回使う評価キットは、ルネサスエレクトロニクス社のEK-RA6M5評価キットです。e2 studioのGUIでEK-RA6M5評価キットを選択するとデフォルトでR_IOPORT_OpenとR_IOPORT_Closeの関数を組み込んでくれますので、ユーザーが記述する必要はありません。
汎用I/Oを読み取って、「level」にその値を保存する関数はR_IOPORT_PinReadです。
この関数はe2 studioの持つ「Developer Assistance」という機能で簡単に入力できます。記述は、次のようになります。
R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05 ,&level);
この1行の記述だけでI/OポートのP005の値を読み込んで「level」に保存します。
もし、「level」がハイレベルならば、LEDを点灯させるので、P006に「level」の値を出力すればLEDは点灯します。また、 「level」がロウレベルならば、LEDを消灯させるので、P006に「level」の値を出力すればLEDは消灯します。
したがって、常にP006に「level」の値を出力すれば、「level」がハイレベルならばLEDを点灯、「level」がロウレベルならばLEDを消灯させることができます。
P006に「level」の値を出力する関数はR_IOPORT_PinWriteです。記述は、次のようになります。
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06 , level );
プログラムを無限に繰り返すにはwhile(1)文を使います。while(1)の中括弧の中にP005を「level」に読み込んで、それをP006へ出力する記述を並べます。
while(1)
{
R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05 ,&level);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06 , level );
}
したがって、全プログラムの記述は、次のようになります。
static bsp_io_level_t level = BSP_IO_LEVEL_LOW;
while(1)
{
R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_05 ,&level);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_06 , level );
}
/* TODO: add your own code here */から下に、この記述を書き込みます。
では、実際にプロジェクトを作っていきましょう。
ここからは、「ルネサスRAファミリ マイコン入門講座:第2回 CPU編」と同じ手順で、プロジェクトの作成からコード生成まで行います。今回は、ワークスペースのフォルダをGPIO_trialとします。そして、「Welcome to e2 studio」の画面を隠して、「e2 studioのスタート画面」を表示します。
プロジェクトが出来たら/* TODO: add your own code here */の下に、さきほどのコードを書き込みます。
「 static bsp_io_level_t level = BSP_IO_LEVEL_LOW;」と「 while(1) { }」は手で入力して、「R_IOPORT_PinRead」と「R_IOPORT_PinWrite」はDeveloper Assistanceを使います。

図17:ユーザーコードの記述
左のプロジェクトエクスプローラーの中の[Developer Assistance]を開けて、さらに[HAL/Common]を開けます。その中のg_ioportI/O Port(r_ioport)を開けるとfsp_err_t R_IOPORT_PinRead(ioport_ctrl_t….)という記述があります。
さらに開けるとCall R_IOPORT_PinRead ()という関数があります。
Call R_IOPORT_PinRead ()を、while文の中括弧の中にDrag&Dropします。
すると、status = R_IOPORT_PinRead(&g_ioport_ctrl, pin, p_pin_value);という記述が入りますので、最初のstatus =を削除して、pinをBSP_IO_PORT_00_PIN_05に、valueを&levelに書き換えます。
R_IOPORT_PinWriteも同じようにfsp_err_t R_IOPORT_PinWrite (ioport_ctrl_t….)を開けて、Call R_IOPORT_PinWrite ()という関数をR_IOPORT_PinRead()の下にDrag&Dropします。すると、 status = R_IOPORT_PinWrite(&g_ioport_ctrl, pin, level);という記述が入りますので、最初のstatus =を削除して、pinをBSP_IO_PORT_00_PIN_06に、valueをlevelに書き換えます。levelには&が付きませんので、注意してください。

図18:「R_IOPORT_PinRead」と「R_IOPORT_PinWrite」の入力
上部のツールバーにある小さな「ハンマー」記号をクリックするとプロジェクトがビルドされます。
ビルドが完了すると ビルド結果がステータスとして表示されます。エラーがないことを確認します。これでプロジェクトを実行する準備が整いました

図19:プロジェクトのビルド
PCとEK-RA6M5評価ボードをUSBケーブルで接続すると、USBから給電されて、ボードが起動します。

図20:EK-RA6M5評価キットとPCの接続
デバッグ記号の横にある小さな矢印をクリックし ドロップダウンリストボックスから[デバッグの構成]を選択します。「構成の作成、管理、および実行」の画面で左側のツリービューのRenesas GDB Hardware Debuggingの下の今回のプロジェクトの名前を選択します。下部の[デバッグ]をクリックするとデバッガが起動します。

図21:デバッグの構成
[パースペクティブ切り替えの確認]ダイアログが表示されたら、[切り替え]を選択します。
しばらくするとデバッグ画面が開きます。再開ボタンをクリックすると プログラムはmain()関数のhal_entry()の呼び出し行まで実行されます。再開ボタンをもう一度クリックするとプログラムは実行を継続します。

図22:プログラムの実行
プログラムが実行されると、ユーザーボタンS1を押すとLEDは消えます。離すと点きます。

図23:LEDの点滅
プログラムを停止するには「停止ボタン」をクリックします。
デバッガとEK-RA6M5評価キットを切り離すには「切り離しボタン」をクリックします。
プログラムを停止しデバイスをデバッガから切り離したい時は「切り離しボタン」だけをクリックします。
e2 studioを終了するには、メニューからファイルを選んで終了を選択します。

図24:終了画面
「第3回:汎用I/O」は、以上です。汎用I/Oの構成や電気的特性、使い方が詳しくお分かりいただけたと思います。
次回は「第4回:割り込み」です。そもそも割り込みとは何か?そして種類と使い方を解説します。
さらに、サンプルプログラムをe2 studioに取り込む方法も説明します。








