見出し画像

マイコンde学習しよう(レッスン1)AVR128DA28

「ピン操作」


<目的>
・ポートの設定方法について学ぶ。
・ビット操作について学ぶ。

<動作概要>
・SW1 が押されたらLED1 を点灯させる。
・SW2 が押されたらLED2 を点灯させる。

<ポイント>
・PORTx.DIR はデータ方向レジスタ。
・PORTx.OUT はデータ出力レジスタ。
・PORTx.IN はデータ入力レジスタ。
・PORTx.DIRSET、PORTx.DIRCLR、PORTx.DIRTGL はデータ方向レジスタのセット、クリア、トグルを行うレジスタ。
・PORTx.OUTSET、PORTx.OUTCLR、PORTx.OUTTGL はデータ出力レジスタのセット、クリア、トグルを行うレジスタ。

<レジスタ説明>

ポートピン構造図

「ポートピン構造図」の図中Aにおいて、入出力ピンPxnのxはポート名を表し本マイコンではA,C,D,Fです。またnはビット位置(0〜7)を表します。Pxnを入力、出力のどちらにするかはDIRレジスタにより決定します。
出力にした場合は図中Bの部分で出力をHigh、LowのどちらにするかがOUTレジスタにより決定します。
入力にした場合は図中Cの部分でPINnCTRLレジスタのPULLUPENビットが1であればPxnピンはプルアップされます。
またINレジスタに入力値が格納されますが、入力信号変化が図中Dの部分でPINnCTRLレジスタのISC[2:0]ビットの割込み許可条件に一致するとINTFLAGSレジスタの該当ビットがセットされます。
下記が関係するレジスタです。PORT 単位で用意されています。
例えば、PORTAであればPORTA.DIR、PORTBであればPORTB.DIRなどとなります。
PINnCTRLはポートの0~7の各ビット毎に用意されたレジスタです。
例えば、PORTAであればPORTA.PIN0CTRL~PORTA.PIN7CTRL、PORTBであればPORTB.PIN0CTRL~PORTB.PIN7CTRLとなります。


DIRレジスタ

DIRセットレジスタ

DIRクリアレジスタ

DIRトグルレジスタ

OUTレジスタ

OUTSETレジスタ

OUTクリアレジスタ

OUTトグルレジスタ

INレジスタ

PINnCTRL(ピン制御)レジスタ

INVEN:入出力反転 1:反転
PULLUPEN:プルアップ許可  1:許可
ISC[2:0]:割込み条件 (レッスン2で解説します)


<プログラム>

// 名称			: ピン操作
// ファイル名	: main.c
/*
<目的>
・ポートの設定方法について学ぶ。
・ビット操作について学ぶ。

<動作概要>
・SW1が押されたらLED1を点灯させる。
・SW2が押されたらLED2を点灯させる。

<ポイント>
・PORT*.DIRはデータ方向レジスタ。
・PORT*.OUTはデータ出力レジスタ。
・PORT*.INはデータ入力レジスタ。
・PORT*.DIRSET、PORT*.DIRCLR、PORT*.DIRTGLはデータ方向レジスタのセット、クリア、トグルを行うレジスタ。
・PORT*.OUTSET、PORT*.OUTCLR、PORT*.OUTTGLはデータ出力レジスタのセット、クリア、トグルを行うレジスタ。

*/

#include <avr/io.h>

//*******************************************************************************
// 各種定義
//*******************************************************************************

//*******************************************************************************
// メインルーチン(MAIN)
//*******************************************************************************
int main(void)
{
	/* SWを入力に設定 */
	PORTA.DIRCLR = PIN0_bm | PIN1_bm ;

	/* SWの内部プルアップを許可 */
	PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
	PORTA.PIN1CTRL = PORT_PULLUPEN_bm;

	/* LEDを出力として構成設定 */
	PORTD.DIRSET = PIN0_bm |PIN1_bm;

	/* LEDをOFF */
	PORTD.OUTSET = PIN0_bm | PIN1_bm;

	/* 未使用ピン設定 */
	PORTD.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc;		// PD4
	PORTD.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc;		// PD5
	PORTF.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc;		// PF0
	PORTF.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;		// PF1
	PORTF.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc;		// PF6

	while (1)
	{
//---- SW1判定 ----//

		if (!(PORTA.IN & (PIN0_bm)))		// SW1が押されているか
			PORTD.OUTCLR = PIN0_bm;			// 押されているのでLED1点灯
		else
			PORTD.OUTSET = PIN0_bm;			// 押されていないのでLED1消灯

//---- SW2判定 ----//

		if (!(PORTA.IN & (PIN1_bm)))		// SW1が押されているか
			PORTD.OUTCLR = PIN1_bm;			// 押されているのでLED1点灯
		else
			PORTD.OUTSET = PIN1_bm;			// 押されていないのでLED1消灯
	}
}

<プログラム説明>

プログラムは、ioavr128da28.h で定義された名前を使って記述しています。
詳しくは、「マイコンde学習しよう(プログラム記述編)」の記事を参照ください。

/* SW を入力に設定 */
PORTA.DIRCLR = PIN0_bm | PIN1_bm ;
上記は、SW1 およびSW2 がそれぞれPA0、PA1 ピンに接続されているので、入力に設定しています。
DIR レジスタ、DIRSET レジスタ、DIRCLR レジスタの関係ですが、DIRSET の指定ビットのセットでDIR レジスタの指定ビットがセット、DIRCLR の指定ビットのセットでDIR レジスタのクリアが行われます。
DIR レジスタは値が0 で入力、1 で出力に設定されます。
(DIR レジスタを直接セット、クリアしても同様の結果となりますが、それよりも間接的に行うほうが分かりやすいので本プログラムではこのやり方で行います)
/ SW の内部プルアップを許可 /
PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
PORTA.PIN1CTRL = PORT_PULLUPEN_bm;
上記は、SW1 およびSW2 が接続されたPA0、PA1 ピンのプルアップを行い、スイッチが押されていないときは入力レベルがHigh になるようにします。

/ LED を出力として構成設定 /
PORTD.DIRSET = PIN0_bm |PIN1_bm;
LED1(PD0 ピン)、LED2(PD1 ピン)を出力に設定します。
/ LED をOFF /
PORTD.OUTSET = PIN0_bm | PIN1_bm;

LED は電流吸い込みで点灯するので、消灯時はHigh を出力させるためOUT レジスタの指定ビットをセットします。
下記は、SW 入力判定と、LED のピン設定の部分です。

//---- SW1判定 ----//
if (!(PORTA.IN & (PIN0_bm))) // SW1が押されているか
PORTD.OUTCLR = PIN0_bm; // 押されているのでLED1点灯
else
PORTD.OUTSET = PIN1_bm; // 押されていないのでLED1 消灯

PORTA.IN & (PIN0_bm)のところですが、PIN0_bm というのは0x01 と同義ですので、PORTA.IN レジスタの0 ビット目との1 のアンドをとることになります。
SW1 が押されていれば、ピンはGND と導通するのでPORTA のビット0 は0 となり、1 とのアンドで0 となりますが、頭に!(反転記号)をつけたことで計算結果は1 となり、if 文の条件が満足されたことになります。

本基板には、未使用の開放ピンが5 ピンあります。
これらについては、割込みと入力を禁止する処置をします。
/ 未使用ピン設定 */
PORTD.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc; // PD4
PORTD.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc; // PD5
PORTF.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc; // PF0
PORTF.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc; // PF1
PORTF.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // PF6

ここから先は

0字
単体で有料公開している記事を集めていますので、まとめてご覧いただくとおトクです。

AVRマイコンプログラミング入門用として、レッスン形式にまとめました。 マイコンの機能の理解にも役立ちます。 トレーニング用の基板頒布も行…

期間限定 PayPay支払いすると抽選でお得に!

この記事が気に入ったらサポートをしてみませんか?