ピンの読み取り
ピンからデータを読み取る方法です。読み取りたいピンに対応するDIRレジスタのビットを0にすると、そのピンは入力として機能します。DIRレジスタに0を書き込むには、2通りの方法があります。
(方法1)単純にDIRレジスタを読み出し、その値にビット反転したパターンとのANDを取る方法です。(AVRマイコンにおけるピン設定と同じ方法)
PORT->Group[0].DIR.reg &= ~PORT_PA01; // PA01を入力に設定
(方法2)DIRCLRレジスタに1を書き込む方法です(こちらがお勧めです)
PORT->Group[0].DIRCLR.reg = PORT_PA01; // PA01を入力に設定
DIRCLRレジスタはDIRレジスタを設定するための特殊なレジスタです。DIRCLRレジスタに1を書き込むと、対応するDIRビットが0になります。0を書き込んだビットには何も変化は起きません。(そのため、|=や&=代入演算子ではなく、代入演算子=を使います。間違えやすいので注意)
DIRCLRレジスタを使うと、方法1と比べて高速(1サイクル)です。さらにソースコードの可読性も高くなります。なお、特定のビットを0ではなく1にしたい場合、DIRSETレジスタを使います。
PORT->Group[0].DIRSET.reg = PORT_PA01; // PA01を出力に設定
さて、DIRレジスタによりピンを入力方向に設定しただけでは読み取りはできません。ピンに対応するINENレジスタのビットを1にすることで読み取りが可能になります。
実際のピンの値を知るには、INレジスタを読み出します。
#include "sam.h"
main()
{
SystemInit();
PORT->Group[0].PINCFG[2].bit.PULLEN = 1; // PA02のプルアップ有効化
PORT->Group[0].DIRCLR.reg = PORT_PA02; // PA02を入力に設定
PORT->Group[0].PINCFG[2].bit.INEN = 1; // PA02の入力読み取りを有効化
uint32_t v = PORT->Group[0].IN.reg & PORT_PA02; // PA02の入力値
}
ピンの出力
ピンから出力する方法です。まずピンに対応するDIRレジスタのビットを1にします。DIRSETレジスタの当該ビットに1を書き込みます。次にOUTレジスタの当該ビットを書き換えることで出力が反映されます。Hを出力する場合にはOUTSETレジスタの当該ビットに1を書き込み、Lを出力する場合にはOUTCLRレジスタに0を書き込みます。
#include "sam.h"
main()
{
SystemInit();
PORT->Group[0].DIRSET.reg = PORT_PA02; // PA02を出力に設定
PORT->Group[0].OUTSET.reg = PORT_PA02; // PA02をHに設定
}
なお、DIR=1, INEN=1とすることで、ピンの出力と入力を同時に行うことも可能です。
読み込み遅延について
INレジスタの値は、INレジスタの読み出しが要求されたタイミングで、実際のピンの値がサンプリングされます。この時、クロックとの同期が取られるため、2クロックの時間がかかります。CTRLレジスタのSAMPLINGnビットを1にすることで、常に同期をとるようになり、遅延がなくなります。ただし、常にピン状態を読み取るようになるため、消費電流が増加します。