kumanさんのブログでmikujiさんが質問していたInterrupt処理のasm Programを研究してみる事にした。
asmでは、動作しない事が予想されるので(良く理解していないので)まずCで組む事を考えた。
kumanさんのProgram Libの中から探しても良いのだが、Net検索したらTIMER1_CMPA使用の例題が見つかった。
C Programは下記(出典先のアドレスを記述する事を忘れた。)
実行の結果割り込みが正常動作している事を確認した。
次に、C Programを見ながら、asm で Programを書き、RUNしたが、動作しなかった。
studio4 のdebugを起動してdebugを勉強した。だいたい操作方法は、理解した。
asm Program main の waitloop 内に、割り込みvectにJMP命令を挿入し実行したら、目標の動作を
している事の確認が出来た。
TIMER/COUNTER 1の設定、起動が悪い事が判った。
;*******************************
; timer1 interrupt program asm
;---------------------------------
; CPU: ATMEGA168P
; CLOCK: Internal RC OSC 1MHz
; Event Input:
; TIMER1_COMPA_vect: 100x1024=102,400us (102 ms) 200ms/cycle
; Output:
; Target: PB0 timer1 output
; Debug: PB7 interrupt check
; TIMER1(16bit)
; TIMER0( 8bit)
;--------------------------------------
; ATMEGA168P
; PB0 14 15 PB1
; PD7 13 16 PB2
; PD6 12 17 PB3
; PD5 11 18 PB4
; PB7 10 19 PB5
; PB6 9 20 AVCC
; GND 8 21 AREF
; VCC 7 22 GND
; PD4 6 23 PC0
; PD3 5 24 PC1
; PD2 4 25 PC2
; PD1 3 26 PC3
; PD0 2 27 PC4
; *RESET/PC6 1___---____28 PC5
; asm Instraction
;AND Rd,Rr
;ANDI Rd,K
;OR Rd,Rr
;ORI Rd,K
;EOR Rd,Rr Ex-OR
;ORI Rd,K
;COM Rd 1 Compliment
;NEG Rd 2 Compliment
;SBI P,b IO bit set
;CBI P,b IO bit clear
;MOV Rd,Rr Rd<--Rr
;LD Rd,x Rd<--(x) x: x reg
;ST X,Rr (x)<--Rr x reg InDirect
;STS k,Rr (k)<--Rr SRAM Direct
;IN Rd,P Rd <--P
;OUT P,Rd P <--Rd
;RET PC<--STACK
;RETI PC<--STACK
;--------------------------
.include "m168pdef.inc"
;---------------------------
.org $00
;---------------------------
reset:
jmp start ; go start
jmp EX_INT0 ; EX_INT0
jmp EX_INT1 ; EX_INT1
jmp reset ; timer1_capt ;タイマ/カウンタ1捕獲(キャプチャ)発生
jmp TIMER1_COMPA ; timer1_compa ;タイマ/カウンタ1比較A一致
jmp TIMER1_OVF ; timer1_ovf ;タイマ/カウンタ1オーバーフロー
jmp reset ; timer0_ovf ;タイマ/カウンタ0オーバーフロー
jmp reset ; usart_rxc ;USART受信完了
jmp reset ; usart_udre ;USART送信バッファ空き
jmp reset ; usart_tx ;USART送信完了
jmp reset ; ana_comp ;アナログ比較器出力遷移
jmp reset ; pcint ;ピン変化割り込み要求
jmp reset ; timer1_compb ;タイマ/カウンタ1比較B一致
jmp reset ; timer0_compa ;タイマ/カウンタ0比較A一致
jmp reset ; timer0_compb ;タイマ/カウンタ0比較B一致
jmp reset ; usi_strt ;USI開始条件検出
jmp reset ; usi_ovf ;USIカウンタオーバーフロー
jmp reset ; ee_rdy ;EEPROM操作可
jmp reset ; wdt_ovf ;ウォッチドッグ計時完了
start:
jmp start1
;------------------------
; TIMER1_COMPA INTERRUPT
;------------------------
TIMER1_COMPA:
RCALL wait_300m ;
SBIS PORTC, 0 ; if PC0=1? skip
JMP FPC0_01 ;
CBI PORTC, 0 ; PC0 1 to 0
JMP CBJE
FPC0_01: ;
SBI PORTC, 0 ; PC0 0 to 1
CBJE:
RETI
;********************
TIMER1_OVF: ; Overflow Interrupt
;********************
mov r16, r30 ; timer set
sts TCNT1H, r16 ;↑
mov r16, r31 ;↑
sts TCNT1L, r16 ;↑
inc r3 ; interrupt FLAG r3=1
RETI ;
;*******************
; EX_INT1
;********************
EX_INT1:
cli ; interrupt disable
clr r5 ; flag
jmp wait_100m ; chatring remove
sbrs r4, 0 ; Rb(b)=1, PC<--PC + 2or3
jmp time_100mset ; timer2( 34958 )
sbrs r5, 0 ; Rb(b)=1, PC<--PC + 2or3
jmp time_300mset ; timer3( 64740 )
clr r5
RETI
; subroutine
;----------------
Timer1_init: ;
;----------------
;OCR1A = 100 ;
ldi r16, 0 ;
sts OCR1AH, r16 ;
ldi r16, 100 ; 7654 3210
sts OCR1AL, r16 ; 0b0110 0100 OCR1A=100 100x1024=102,400us (4.88Hz)
; ++---------COM1A1:COM1A0 00 (OC1A cut)
;TCCR1A=0 ; ||++-------COM1B1:COM1B0 00 (OC1B cut)
ldi r16, 0 ; |||| ++--WGM11,10 00(WGM 4bit(1:0)
STS TCCR1A, r16 ; 0b0000 0000
;TCCR1B=0x0D ; 0b0000 1101
ldi r16, 0 ; || | |+++--CS12,11,10 101 1/1024
STS TCCR1B, r16 ; || +-+-----WGM13,12 01(WGM 4bit(3:2) CTC TOP
; ++---------ICNC1,ICES 00
;TIMSK1=0x02 ; 0b0000 0010
ldi r16, 2 ; +-- compA interrupt enable
STS TIMSK1, r16 ;
RET
start1:
;--------------------
ldi r16,low(ramend) ; RAM End Address set to SPL
out spl,r16 ;
;--------------------
ldi r16, 0xFF ; PB output
out DDRB, r16 ;
ldi r16, 0x3F ; 7654 3210
out DDRC, r16 ; PC5-0 output 0011 1111
;--------------------
ldi r16, 0xFF ; PD output
out DDRD, r16 ;
;--------------------
ldi r16, 0 ;
out PORTB, r16 ; PB=0
ldi r16, 5 ;
out PORTC, r16 ; PC=0
ldi r16, 0 ;
out PORTD, r16 ; PD=0
;****************************
main:
;****************************
ldi r16, 0x01 ;
out DDRC, r16 ; PC0: output
ldi r16, 0x01 ; PC0=1
out PORTC, r16 ;
RCALL timer1_init;
sei
mloop:
NOP
NOP
RCALL TIMER1_COMPA
NOP
NOP
JMP mloop
;-----------------------
; execute LED
;-----------------------
asmendchk:
SBI PORTB, 4 ; PB4
RCALL wait_1m
CBI PORTB, 4
RCALL wait_1m
RET
;--------------------
; EX_INT1_LED
;--------------------
EX_INT1_LED:
SBI PORTB, 6 ; PB6
RCALL wait_1m
CBI PORTB, 6
RCALL wait_1m
RET
;--------------------
; TIMER1 OVF LED
;--------------------
TIMER1_OVF_LED:
SBI PORTB, 7 ; PB7=1
RCALL wait_1m
CBI PORTB, 7
RCALL wait_1m
RET
;*********************
; EX_INT0 LED
;*********************
EX_INT0:
RETI
;*******************
; LED for Debug
;-------------------
PB7_ON:
SBI PORTB,7 ; PB7=1
RCALL wait_1m ;
CBI PORTB,7 ; PB7=0
RCALL wait_1m ;
RET
;--------------------
; time300mset
;--------------------
time_300mset:
ldi r30, 0x88 ;
ldi r31, 0x8e ; 65536-34958=30578 305μ
inc r4 ;
inc r5 ;
ret
;--------------------
; time100mset
;--------------------
time_100mset:
ldi r30, 0xfc ;
ldi r31, 0xe4 ; 65536-64740=826 82 μ
clr r4 ;
inc r5 ;
ret
;*******************
wait_300m: ; 300 ms wait(1MHzクロック時)
;-------------------
LDI R18,3
wait_300m2:
;-------------------
RCALL wait_100m ; <00ms sub>
DEC R18
BRNE wait_300m2
RET
;*******************
wait_100m: ; 100 ms wait(1MHzクロック時)
;-------------------
LDI R19,100
wait_100m2:
;-----------------------
RCALL wait_1m ; <ms sub>
DEC R19
BRNE wait_100m2
RET
;*******************
wait_10m: ; 100 ms wait(1MHzクロック時)
;-------------------
LDI R19,10
wait_10m2:
;-----------------------
RCALL wait_1m ; <ms sub>
DEC R19
BRNE wait_10m2
RET
;********************
wait_1m: ; 1ms wait(1MHzクロック時)
;-----------------------
LDI R20,250
wait_1m2:
;-----------------------
NOP ; 4 clock
DEC R20 ;
BRNE wait_1m2
RET
//************************
; C Program
;************************
; TIMER1 LED_On/Off Test
;---------------------------
CPU: ATMEGA168P
CLOCK: Internal RC OSC 1MHz
Input:
Output:
Test_LED:
PB7: INT1 ↓
*/
//****************************
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//------------------------
ISR(TIMER1_COMPA_vect)
{
PORTB ^= 0x01;
LIT_7_ON(); // for Interrupt check
}
//-----------------------
void timer_init(unsigned t)
{
OCR1A = t;
TCCR1A = 0;
TCCR1B = 0x0D;
TIMSK1 = 0x02;
//sei(); // no interrupt check
sei();
}
//--------------------------
LIT_7_ON() // Interrupt check LED for debug
{
PORTB |= _BV(7);
_delay_ms(10); //10ms on
PORTB &= ~_BV(7);
_delay_ms(10); //10ms off
}
//****************************
int main()
{
DDRB = 0x81; // modify from 0x01
PORTB = 0x01;
timer_init(100);
while(1);
}
asmでは、動作しない事が予想されるので(良く理解していないので)まずCで組む事を考えた。
kumanさんのProgram Libの中から探しても良いのだが、Net検索したらTIMER1_CMPA使用の例題が見つかった。
C Programは下記(出典先のアドレスを記述する事を忘れた。)
実行の結果割り込みが正常動作している事を確認した。
次に、C Programを見ながら、asm で Programを書き、RUNしたが、動作しなかった。
studio4 のdebugを起動してdebugを勉強した。だいたい操作方法は、理解した。
asm Program main の waitloop 内に、割り込みvectにJMP命令を挿入し実行したら、目標の動作を
している事の確認が出来た。
TIMER/COUNTER 1の設定、起動が悪い事が判った。
;*******************************
; timer1 interrupt program asm
;---------------------------------
; CPU: ATMEGA168P
; CLOCK: Internal RC OSC 1MHz
; Event Input:
; TIMER1_COMPA_vect: 100x1024=102,400us (102 ms) 200ms/cycle
; Output:
; Target: PB0 timer1 output
; Debug: PB7 interrupt check
; TIMER1(16bit)
; TIMER0( 8bit)
;--------------------------------------
; ATMEGA168P
; PB0 14 15 PB1
; PD7 13 16 PB2
; PD6 12 17 PB3
; PD5 11 18 PB4
; PB7 10 19 PB5
; PB6 9 20 AVCC
; GND 8 21 AREF
; VCC 7 22 GND
; PD4 6 23 PC0
; PD3 5 24 PC1
; PD2 4 25 PC2
; PD1 3 26 PC3
; PD0 2 27 PC4
; *RESET/PC6 1___---____28 PC5
; asm Instraction
;AND Rd,Rr
;ANDI Rd,K
;OR Rd,Rr
;ORI Rd,K
;EOR Rd,Rr Ex-OR
;ORI Rd,K
;COM Rd 1 Compliment
;NEG Rd 2 Compliment
;SBI P,b IO bit set
;CBI P,b IO bit clear
;MOV Rd,Rr Rd<--Rr
;LD Rd,x Rd<--(x) x: x reg
;ST X,Rr (x)<--Rr x reg InDirect
;STS k,Rr (k)<--Rr SRAM Direct
;IN Rd,P Rd <--P
;OUT P,Rd P <--Rd
;RET PC<--STACK
;RETI PC<--STACK
;--------------------------
.include "m168pdef.inc"
;---------------------------
.org $00
;---------------------------
reset:
jmp start ; go start
jmp EX_INT0 ; EX_INT0
jmp EX_INT1 ; EX_INT1
jmp reset ; timer1_capt ;タイマ/カウンタ1捕獲(キャプチャ)発生
jmp TIMER1_COMPA ; timer1_compa ;タイマ/カウンタ1比較A一致
jmp TIMER1_OVF ; timer1_ovf ;タイマ/カウンタ1オーバーフロー
jmp reset ; timer0_ovf ;タイマ/カウンタ0オーバーフロー
jmp reset ; usart_rxc ;USART受信完了
jmp reset ; usart_udre ;USART送信バッファ空き
jmp reset ; usart_tx ;USART送信完了
jmp reset ; ana_comp ;アナログ比較器出力遷移
jmp reset ; pcint ;ピン変化割り込み要求
jmp reset ; timer1_compb ;タイマ/カウンタ1比較B一致
jmp reset ; timer0_compa ;タイマ/カウンタ0比較A一致
jmp reset ; timer0_compb ;タイマ/カウンタ0比較B一致
jmp reset ; usi_strt ;USI開始条件検出
jmp reset ; usi_ovf ;USIカウンタオーバーフロー
jmp reset ; ee_rdy ;EEPROM操作可
jmp reset ; wdt_ovf ;ウォッチドッグ計時完了
start:
jmp start1
;------------------------
; TIMER1_COMPA INTERRUPT
;------------------------
TIMER1_COMPA:
RCALL wait_300m ;
SBIS PORTC, 0 ; if PC0=1? skip
JMP FPC0_01 ;
CBI PORTC, 0 ; PC0 1 to 0
JMP CBJE
FPC0_01: ;
SBI PORTC, 0 ; PC0 0 to 1
CBJE:
RETI
;********************
TIMER1_OVF: ; Overflow Interrupt
;********************
mov r16, r30 ; timer set
sts TCNT1H, r16 ;↑
mov r16, r31 ;↑
sts TCNT1L, r16 ;↑
inc r3 ; interrupt FLAG r3=1
RETI ;
;*******************
; EX_INT1
;********************
EX_INT1:
cli ; interrupt disable
clr r5 ; flag
jmp wait_100m ; chatring remove
sbrs r4, 0 ; Rb(b)=1, PC<--PC + 2or3
jmp time_100mset ; timer2( 34958 )
sbrs r5, 0 ; Rb(b)=1, PC<--PC + 2or3
jmp time_300mset ; timer3( 64740 )
clr r5
RETI
; subroutine
;----------------
Timer1_init: ;
;----------------
;OCR1A = 100 ;
ldi r16, 0 ;
sts OCR1AH, r16 ;
ldi r16, 100 ; 7654 3210
sts OCR1AL, r16 ; 0b0110 0100 OCR1A=100 100x1024=102,400us (4.88Hz)
; ++---------COM1A1:COM1A0 00 (OC1A cut)
;TCCR1A=0 ; ||++-------COM1B1:COM1B0 00 (OC1B cut)
ldi r16, 0 ; |||| ++--WGM11,10 00(WGM 4bit(1:0)
STS TCCR1A, r16 ; 0b0000 0000
;TCCR1B=0x0D ; 0b0000 1101
ldi r16, 0 ; || | |+++--CS12,11,10 101 1/1024
STS TCCR1B, r16 ; || +-+-----WGM13,12 01(WGM 4bit(3:2) CTC TOP
; ++---------ICNC1,ICES 00
;TIMSK1=0x02 ; 0b0000 0010
ldi r16, 2 ; +-- compA interrupt enable
STS TIMSK1, r16 ;
RET
start1:
;--------------------
ldi r16,low(ramend) ; RAM End Address set to SPL
out spl,r16 ;
;--------------------
ldi r16, 0xFF ; PB output
out DDRB, r16 ;
ldi r16, 0x3F ; 7654 3210
out DDRC, r16 ; PC5-0 output 0011 1111
;--------------------
ldi r16, 0xFF ; PD output
out DDRD, r16 ;
;--------------------
ldi r16, 0 ;
out PORTB, r16 ; PB=0
ldi r16, 5 ;
out PORTC, r16 ; PC=0
ldi r16, 0 ;
out PORTD, r16 ; PD=0
;****************************
main:
;****************************
ldi r16, 0x01 ;
out DDRC, r16 ; PC0: output
ldi r16, 0x01 ; PC0=1
out PORTC, r16 ;
RCALL timer1_init;
sei
mloop:
NOP
NOP
RCALL TIMER1_COMPA
NOP
NOP
JMP mloop
;-----------------------
; execute LED
;-----------------------
asmendchk:
SBI PORTB, 4 ; PB4
RCALL wait_1m
CBI PORTB, 4
RCALL wait_1m
RET
;--------------------
; EX_INT1_LED
;--------------------
EX_INT1_LED:
SBI PORTB, 6 ; PB6
RCALL wait_1m
CBI PORTB, 6
RCALL wait_1m
RET
;--------------------
; TIMER1 OVF LED
;--------------------
TIMER1_OVF_LED:
SBI PORTB, 7 ; PB7=1
RCALL wait_1m
CBI PORTB, 7
RCALL wait_1m
RET
;*********************
; EX_INT0 LED
;*********************
EX_INT0:
RETI
;*******************
; LED for Debug
;-------------------
PB7_ON:
SBI PORTB,7 ; PB7=1
RCALL wait_1m ;
CBI PORTB,7 ; PB7=0
RCALL wait_1m ;
RET
;--------------------
; time300mset
;--------------------
time_300mset:
ldi r30, 0x88 ;
ldi r31, 0x8e ; 65536-34958=30578 305μ
inc r4 ;
inc r5 ;
ret
;--------------------
; time100mset
;--------------------
time_100mset:
ldi r30, 0xfc ;
ldi r31, 0xe4 ; 65536-64740=826 82 μ
clr r4 ;
inc r5 ;
ret
;*******************
wait_300m: ; 300 ms wait(1MHzクロック時)
;-------------------
LDI R18,3
wait_300m2:
;-------------------
RCALL wait_100m ; <00ms sub>
DEC R18
BRNE wait_300m2
RET
;*******************
wait_100m: ; 100 ms wait(1MHzクロック時)
;-------------------
LDI R19,100
wait_100m2:
;-----------------------
RCALL wait_1m ; <ms sub>
DEC R19
BRNE wait_100m2
RET
;*******************
wait_10m: ; 100 ms wait(1MHzクロック時)
;-------------------
LDI R19,10
wait_10m2:
;-----------------------
RCALL wait_1m ; <ms sub>
DEC R19
BRNE wait_10m2
RET
;********************
wait_1m: ; 1ms wait(1MHzクロック時)
;-----------------------
LDI R20,250
wait_1m2:
;-----------------------
NOP ; 4 clock
DEC R20 ;
BRNE wait_1m2
RET
//************************
; C Program
;************************
; TIMER1 LED_On/Off Test
;---------------------------
CPU: ATMEGA168P
CLOCK: Internal RC OSC 1MHz
Input:
Output:
Test_LED:
PB7: INT1 ↓
*/
//****************************
#define F_CPU 1000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//------------------------
ISR(TIMER1_COMPA_vect)
{
PORTB ^= 0x01;
LIT_7_ON(); // for Interrupt check
}
//-----------------------
void timer_init(unsigned t)
{
OCR1A = t;
TCCR1A = 0;
TCCR1B = 0x0D;
TIMSK1 = 0x02;
//sei(); // no interrupt check
sei();
}
//--------------------------
LIT_7_ON() // Interrupt check LED for debug
{
PORTB |= _BV(7);
_delay_ms(10); //10ms on
PORTB &= ~_BV(7);
_delay_ms(10); //10ms off
}
//****************************
int main()
{
DDRB = 0x81; // modify from 0x01
PORTB = 0x01;
timer_init(100);
while(1);
}