今回はタイマー割り込み(タイマ0)を使用して、LEDの点滅を行ってみたいと思います。
タイマ0関連で使用するレジスターは次のとおりです。
・ステータスレジスター (SREG)
・タイマ/カウンタ0 制御レジスタ (TCCR0)
・タイマ/カウンタ0 カウンタ (TCNT0)
・タイマ/カウンタ割り込み許可レジスタ (TIMSK)
・タイマ/カウンタ割り込み要求フラグレジスタ (TIFR)
最初にステータスレジスターのbit7(I)の全割り込み許可を行います。
ldi r16, 0x80 ;Global Interrupt Enable
out SREG, r16
タイマ/カウンタ0 制御レジスタでタイマ/カウンタ0に与えるクロックを選択します。
今回は、CPUクロックを1024分周したクロックを与えました。
CPUクロックは8MHzなので、8MHz/1024で約128uSとなります。
ldi r16, 0x05 ;Timer CK/1024 set(8MHz/1024=128uS)
out TCCR0, r16
タイマ/カウンタ0 カウンタでは、約10mSの時間稼ぎしたいのでタイマ/カウンタ0 カウンタ値は78(0x4e)となりました。(128uS*78=10mS)
ldi r16, 0x4e ;10mS Timer 0 set(128uS*78=10ms)
out TCNT0, r16
タイマ/カウンタ割り込み許可レジスタのbit1(TOIE0)でタイマ/カウンタ0溢れ割り込み許可を設定します。
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Enable
out TIMSK, r16
タイマ/カウンタ割り込み要求フラグレジスタのbit1(TOV0)でタイマ/カウンタ0溢れ割り込み要求フラグを設定します。タイマ/カウンタ0溢れ割り込み許可及びタイマ/カウンタ0溢れ割り込み要求フラグが設定されると該当の割り込みが発生します。ここではタイマ0を使用しているので、タイマ/カウンタ0の溢れ割り込みが発生ます。
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Flag
out TIFR, r16
rjmp reset ;reset
reti ;INT0
reti ;INT1
reti ;Timer/Counter1 CAPT1
reti ;Timer/Counter1 COMP1
reti ;Timer/Counter1 OVF1
rjmp Timer0 ;Timer/Counter0 OVF0
reti ;UART RX
reti ;UART UDRE
reti ;UART TX
reti ;Analog Comparator ANA_COMP
タイマ0の割り込みルーチンでは、10mSをカウントするレジスタr17を減算します。
(初期値10 100mS=10mS*10)
r17が0になったら、再度r17を初期化したのち、PB2に出力します。
再度、タイマ/カウンタ割り込み要求フラグレジスタを設定したのちリターンします。
Timer0:
dec r17
breq Timer0_0
reti
Timer0_0:
ldi r17, 0d10
in r16, PINB
eor r16, r18
out PORTB, r16
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Flag
out TIFR, r16
reti
全体のプログラムは下記の通りです。
;AT90S2313 LED Flashing (Exclusive OR and interrupt mode)
;
;; AT90S2313 cpu
;; rom 0000h -- 03ffh
;; ram 0000h -- 00dfh
;; eeprom 0000h -- 007fh
;; External clock 8MHz
;;
;;
;; assemblers ASxxxx and ASlink V5.40
;; file name 2313_led_flashing_eor_int.asm
;; $ asavr -l -s -o 2313_led_flashing_eor_int.asm
;; $ aslink -i 2313_led_flashing_eor_int
;; $ (sudo) avrdude -v -p 2313 -c usbasp -P usb -F -e -U flash:w:2313_led_flashing_eor_int.ihx
;I/O regster
SREG .equ 0x3f ;Status Register
SPL .equ 0x3d ;Stack Pointer Low
GIMSK .equ 0x3b ;General Interrupt MaSK register
GIFR .equ 0x3a ;General Interrupt Flag register
TIMSK .equ 0x39 ;Timer/Counter Interrupt MaSK register
TIFR .equ 0x38 ;Timer/Counter Interrupt Flag register
MCUCR .equ 0x35 ;MCU general Control Register
TCCR0 .equ 0x33 ;Timer/Counter 0 Control Register
TCNT0 .equ 0x32 ;Timer/CouNTer 0
TCCR1A .equ 0x2f ;Timer/Counter 1 Control Register A
TCCR1B .equ 0x2e ;Timer/Counter 1 Control Register B
TCNT1H .equ 0x2d ;Timer/CouNTer 1 High byte
TCNT1L .equ 0x2c ;Timer/CouNTer 1 Low byte
OCR1AH .equ 0x2b ;Output Compare Register 1 High byte
OCR1AL .equ 0x2a ;Output Compare Register 1 Low byte
ICR1H .equ 0x25 ;T/C Input Capture Register High byte
ICR1L .equ 0x24 ;T/C Input Capture Register Low byte
WDTCR .equ 0x21 ;WatchDog Timer Control Register
EEAR .equ 0x1e ;EEPROM Address Register
EEDR .equ 0x1d ;EEPROM Data Register
EECR .equ 0x1c ;EEPROM Control Register
PORTB .equ 0x18 ;Data Register, Port B
DDRB .equ 0x17 ;Data Direction Register, Port B
PINB .equ 0x16 ;Input Pins, Port B
PORTD .equ 0x12 ;Data Register, Port D
DDRD .equ 0x11 ;Data Direction Register, Port D
PIND .equ 0x10 ;Input Pins, Port D
UDR .equ 0x0c ;UART Data Register
USR .equ 0x0b ;UART Status Register
UCR .equ 0x0a ;UART Control Register
UBRR .equ 0x09 ;UART Baud Rate Register
ACSR .equ 0x08 ;Analog Comparator Control and Status Register
RAM .equ 0x60
RAMEND .equ 0xdf
.AT90S2313
start :
rjmp reset ;reset
reti ;INT0
reti ;INT1
reti ;Timer/Counter1 CAPT1
reti ;Timer/Counter1 COMP1
reti ;Timer/Counter1 OVF1
rjmp Timer0 ;Timer/Counter0 OVF0
reti ;UART RX
reti ;UART UDRE
reti ;UART TX
reti ;Analog Comparator ANA_COMP
reset:
ldi r16, RAMEND ;Stack pointer setting
out SPL, r16
ldi r16, 0x80 ;Global Interrupt Enable
out SREG, r16
ldi r16, 0b00000100 ;PB2 output setting
out DDRB, r16
ldi r16, 0x05 ;Timer CK/1024 set(8MHz/1024=128uS)
out TCCR0, r16
ldi r16, 0x4e ;10mS Timer 0 set(128uS*78=10ms)
out TCNT0, r16
ldi r17, 0d10 ;100mS counter at 10ms*
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Enable
out TIMSK, r16
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Flag
out TIFR, r16
ldi r18, 0b00000100 ;eor reg
loop:
rjmp loop
Timer0:
dec r17
breq Timer0_0
reti
Timer0_0:
ldi r17, 0d10
in r16, PINB
eor r16, r18
out PORTB, r16
ldi r16, 0x02 ;Timer/Counter0 Overflow Interrupt Flag
out TIFR, r16
reti
.end
アセンブリします。
$ asavr -l -s -o 2313_led_flashing_eor_int.asm
$ aslink -i 2313_led_flashing_eor_int
ASlink >> -i
ASlink >> 2313_led_flashing_eor_int
AT90S2313に焼き付けます。
$ sudo avrdude -v -p 2313 -c usbasp -P usb -F -e -U flash:w:2313_led_flashing_eor_int.ihx
[sudo] hogehoge のパスワード:
avrdude: Version 6.3-20171130
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/etc/avrdude.conf"
User configuration file is "/root/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : usb
Using Programmer : usbasp
AVR Part : AT90S2313
Chip Erase delay : 20000 us
PAGEL : P00
BS2 : P00
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 4 12 64 0 no 128 0 0 4000 9000 0x80 0x7f
flash 4 12 128 0 no 2048 0 0 4000 9000 0x7f 0x7f
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
fuse 0 0 0 0 no 1 0 0 0 0 0x00 0x00
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
Programmer Type : usbasp
Description : USBasp, http://www.fischl.de/usbasp/
avrdude: auto set sck period (because given equals null)
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.02s
avrdude: Device signature = 0x1e9101 (probably 2313)
avrdude: safemode: Fuse reading not support by programmer.
Safemode disabled.
avrdude: erasing chip
avrdude: auto set sck period (because given equals null)
avrdude: reading input file "2313_led_flashing_eor_int.ihx"
avrdude: input file 2313_led_flashing_eor_int.ihx auto detected as Intel Hex
avrdude: writing flash (76 bytes):
Writing | ################################################## | 100% 1.27s
avrdude: 76 bytes of flash written
avrdude: verifying flash memory against 2313_led_flashing_eor_int.ihx:
avrdude: load data flash data from input file 2313_led_flashing_eor_int.ihx:
avrdude: input file 2313_led_flashing_eor_int.ihx auto detected as Intel Hex
avrdude: input file 2313_led_flashing_eor_int.ihx contains 76 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.44s
avrdude: verifying ...
avrdude: 76 bytes of flash verified
avrdude: safemode: Sorry, reading back fuses was unreliable. I have given up and exited programming mode
avrdude done. Thank you.
書き込みが終了すると、約100mS周期で点滅します。