So-net無料ブログ作成
検索選択

AVRアセンブラで配列的なもの [AVR]

アセンブラではレジスタに値を入れていろいろ計算することはわかった。
しかしレジスタだけでは足りない。高級言語で言うところの配列に相当する
のはなんだろう?

数値をバッファに格納していって平均値を計算するなどの処理はどうやるのか。
いろいろ調べてたどり着いたのがここ8 POINT MOVING AVERAGE (AVR 222)

SRAMに格納していけばよさそうな感じだ。SRAMへのアクセスはYレジスタを使っているので
まねしてみよう。上記サイトではSRAMのアドレスはハードコーディングだが、incファイル
見ると、開始アドレスはSRAM_STARTと定義されているようなので、そう書いておこう。

1.カウンターのr17をインクリメントしつつ4バイトリングバッファに格納
2.インクリメントするたびにリングバッファの平均を計算しr16に入れる
3.カウンターが9まで言ったら0に戻る

というプログラムを書いてみた。

.include "m168def.inc"

.org	0x0000	jmp reset   ;initialize
.equ	SIZE = 4
.def	acc = r16

;=============================================================
; 16bit divide by 2
; @0 : high address
; @1 : low address
;=============================================================
.macro Div16By2		; Div16By2 @0 @1
			mov		acc, @0
			lsr		@0
			andi	acc, 1
			lsr		@1
			sbrc	acc, 0
			ori		@1, 0b1000_0000
			nop
.endmacro

;=============================================================
; main
;=============================================================
reset:		ldi		r16, low(ramend)
			out		spl, r16
			ldi		r16, high(ramend)
			out		sph, r16
 
			; set y register sram start address
			ldi		yl, low(SRAM_START)
			ldi		yh, high(SRAM_START)

			clr		r17		; counter
			clr		acc
			rcall	store_acc	; reset buffer
			rcall	store_acc
			rcall	store_acc
			rcall	store_acc

loop:		mov		acc, r17
			rcall	store_acc
			rcall	average
			inc		r17
			cpi		r17, 10
			brlt	loop		; if r17 != 10, goto loop
			clr		r17			; else r17=0
			rjmp	loop

;=============================================================
; store_acc
; store acc valu into ring buffer
;=============================================================
store_acc:	st		y+, acc
			cpi		yl, low(SRAM_START)+SIZE
			breq	store_acc_resetpos
			rjmp	store_acc_ext
store_acc_resetpos:
			ldi		yl, low(SRAM_START)
			ldi		yh, high(SRAM_START)
store_acc_ext:
			ret
;=============================================================
; average
; take summation of ring buffer and divide by 4
;=============================================================
.def suml = r17
.def sumh = r18
average:
			push	yl
			push	yh
			push	suml
			push	sumh

			ldi yl, low(SRAM_START)
			ldi yh, high(SRAM_START)
			clr		suml
			clr		sumh

average_loop:
			ld		acc, y+
			add		suml, acc
			ldi		acc, 0
			adc		sumh, acc		; addition with carry
			cpi		yl, low(SRAM_START)+SIZE
			breq	avrage_div
			rjmp	average_loop
avrage_div:
			Div16By2	sumh, suml
			Div16By2	sumh, suml
			mov		acc, suml

			pop		sumh
			pop		suml
			pop		yh
			pop		yl
			ret



ループのたび(rcall average の後)に
(0+0+0+0)/4=0,
(0+1+0+0)/4=0,
(0+1+2+0)/4=0,
(0+1+2+3)/4=1
(4+1+2+3)/4=2,
(4+5+2+3)/4=3,
(4+5+6+3)/4=4,
(4+5+6+7)/4=5,
(8+5+6+7)/4=6,
(8+9+6+7)/4=7,
(8+9+0+7)/4=6,
(8+9+0+1)/4=4,
(2+9+0+1)/4=3
...
という計算結果がaccに入っているので一応動いているようだ。

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。