プログラミングと工作と

PythonとかPascalとかAVRマイコンとか、コンパイラつくったり電子工作なんかを楽しんでいるおっさんの記録

AVRマイコン アセンブリ言語入門 ― 外部割込み

前回、割込み動作の説明をやったついでに、外部割込みの説明をします。

  • 外部割込みってなんだよ?

たいていのマイコンは、外部割込み端子ピンを持っています。
AVRmega48/88/168/328シリーズだと、INT0, INT1 の2本の端子があり、ピン4,5番端子がそれにあたります。
このピンに、外部から変化をあたえると、割込み動作をさせることが出来ます。
例えば、外部割込み端子にスイッチをつないでおくと、スイッチ入力に使えます。

 

  • 外部割込みってどうやって使うの?

AVRマイコンの各機能を使うには、それぞれの設定レジスタに値を設定するんでしたね。
外部割込みには、2つの設定内容(レジスタ)があります。

  1. 外部割込み条件の設定
  2. 外部割込みの許可を設定

1の外部割込み条件とは、外部割込み端子をどういう状態にすれば割込みを発生させるかを設定します。
「どういう状態」には4種類あり、以下になります。


 1.端子をLowにする
 2.端子に変化を与えた時(Low→High,またはHigh→Low)
 3.端子をHigh→Lowにする下降エッジで発生
 4.端子をLow→Highにする上昇エッジで発生

 

2の許可の設定は、そのままの意味で、外部割込みの使用を許可するための設定です。

設定レジスタの一覧を下に示します。

f:id:takashira:20151212214325p:plain

はい、外部割込みの設定はたったこれだけです。
簡単ですね。


では、ちょっと簡単なプログラムをつくってみます。
つくるのは、外部割込み端子0をHigh→Lowにすると、PortBのビット0端子に接続したLEDが反転する、というものにします。

 

上の表から、
EICRAレジスタのISC01,ISC00ビットを '10' へ、
EIMSKレジスタのINT0ビットを '1' へ
セットすればいいことがわかりますね。

で、プログラムが以下になります。

/*
 * EINT1.asm
 *
 *  Created: 2015/12/12 20:24:42
 *   Author: Takachiho
 */ 

.include "m168pdef.inc"

;************************************************
; 各種定義
;************************************************
;--------------------
; 汎用レジスタ
;--------------------

.def	STACK = R16     ;汎用レジスタR16に'STACK'という名前をつける

;--------------------
; 割り込みベクタ定義
;--------------------

.CSEG
		RJMP	MAIN
.ORG	0x0002          ;外部割込み0発生で
		RJMP	EINT0   ;ラベルEINT0へジャンプする。

;************************************************
;  割り込みルーチン 外部割込み0
;************************************************

EINT0:
;------- ステータスレジスタの内容を退避  --------

		IN	STACK,	SREG

;------- LED ON/OFF を切り替え ------------------

		IN  	R17,	PORTB       ;PortBの内容をR17へコピーする
		LDI 	R18,	0x01        ;R18へ値0x01 = 0b00000001を代入
		EOR 	R17,	R18         ;R17とR18の排他的ORの結果をR17へ
		OUT 	PORTB,	R17         ;R17の結果をPortBへ代入する
		
		;8bitタイマの時と同じ処理

;------- ステータスレジスタの内容を復帰  --------

		OUT		SREG,	STACK

		RETI

;************************************************
;  メイン・ルーチン (MAIN)
;************************************************
MAIN:

;------- 全割り込み禁止 -------------------------

		CLI

;------- PORT 設定  -----------------------------

		LDI		R17,	0b11111111  ;ポートBは全て出力に設定
		OUT		DDRB,	R17
		LDI		R17,	0b00000001  ;bit0以外すべて'0'出力
		OUT		PORTB,	R17

		LDI		R17,	0b11111111  ;ポートCは全て出力に設定
		OUT		DDRC,	R17
		LDI		R17,	0b00000000  ;すべて'0'出力
		OUT		PORTC,	R17

		LDI		R17,	0b11111011  ;PD2(INT0 pin)を入力に設定
		OUT		DDRD,	R17
		LDI		R17,	0b00000100  ;PD2はプルアップ設定
		OUT		PORTD,	R17

;------- 外部割込み0レジスタ設定 ---------------

    ;-------  外部割込み条件 設定  -------

		LDI		R17,	0b00000010	;下降エッジで割込み指定
		STS		EICRA,	R17

    ;-------  割込み許可 設定  -------

		SBI		EIMSK,	INT0		;INT0ビットを'1'へ

;-------  全割り込み許可  -----------------------

		SEI


MAIN01:
		RJMP	MAIN01

こまかいことを言うと、スイッチのチャタリング処理をちゃんとしないときれいに反転しないのですが、割込みが働いているのは良くわかります。