AVR 定时器中断
AVR Timer interrupts
我不明白如何使用中断和定时器。你能解释一下怎么做吗?
我读了人的,但什么也不懂。这是代码:
.include "C:\Users\user\Downloads/m328Pdef.inc"
.MACRO INVBM
.if @0 < 0x40
PUSH R16
PUSH R17
IN R16,@0
LDI R17,1<<@1
EOR R17,R16
OUT @0,R17
POP R17
POP R16
.else
PUSH R16
PUSH R17
LDS R16,@0
LDI R17,1<<@1
EOR R17,R16
STS @0,R17
POP R17
POP R16
.endif
.ENDM
.ORG 0
ON_RESET:
ldi R16, 0b1000_0001
OUT DDRB, R16
LDI R16, 0b0100_0010 ; CTC mode Timer1
STS TCCR1A, R16 ;SET FLAG ON COMPARE MATCH
LDI R16, 0x0D ; maybe change to 0x05 0b0000_0101
STS TCCR1B, R16 ;SET PRESCALER TO /1024
LDI R16, 0 ; value to compare 0*16+255
STS OCR1AH, R16
LDI R16, 255
STS OCR1AL, R16
MAIN_LOOP:
INVBM PINB, 0
RCALL PAUSE
RJMP MAIN_LOOP
PAUSE:
PLUPE:
IN R16, TIFR0
CPI R16, 0b0000_0010
BRNE PLUPE
LDI R16, 0b0000_0010
OUT TIFR0, R16
RET
我的 LED 没有闪烁。
[连接][1]
[1]: https://i.stack.imgur.com/0EUSG.png
;====================================================================
; Main.asm file generated by New Project wizard
;
; Created: Ср апр 7 2021
; Processor: ATmega328P
; Compiler: AVRASM (Proteus)
;====================================================================
.include "C:\Users\user\Downloads\m328Pdef.inc"
;====================================================================
; DEFINITIONS
.list
.def temp=r16
.MACRO INVBM
.if @0 < 0x40
PUSH R16
PUSH R17
IN R16,@0
LDI R17,1<<@1
EOR R17,R16
OUT @0,R17
POP R17
POP R16
.else
PUSH R16
PUSH R17
LDS R16,@0
LDI R17,1<<@1
EOR R17,R16
STS @0,R17
POP R17
POP R16
.endif
.ENDM
.MACRO PUSHF
PUSH R16
IN R16,SREG
PUSH R16
.ENDM
.MACRO POPF
POP R16
OUT SREG,R16
POP R16
.ENDM
.MACRO SETB
.if @0 < 0x20 ; Low IO
SBI @0,@1
.else
.if @0<0x40 ; High IO
IN @2,@0
ORI @2,1<<@1
OUT @0,@2
.else ; Memory
LDS @2,@0
ORI @2,1<<@1
STS @0,@2
.endif
.endif
.ENDM
.dseg
.cseg
.ORG [=10=]0 ; (RESET)
RJMP RESET
.ORG [=10=]2
RETI ; (INT0) External Interrupt Request 0
.ORG [=10=]4
RETI ; (INT1) External Interrupt Request 1
.ORG [=10=]6
RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match
.ORG [=10=]8
RETI ; (TIMER2 OVF) Timer/Counter2 Overflow
.ORG [=10=]A
RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event
.ORG [=10=]C
RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A
.ORG [=10=]E
RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B
.ORG 0
RETI ; (TIMER1 OVF) Timer/Counter1 Overflow
.ORG 2
RETI ; (TIMER0 OVF) Timer/Counter0 Overflow
.ORG 4
RETI ; Timer1 Capture
.ORG 6
RJMP Timer1_IRQ ; Timer1 compare A
.ORG 8
RETI ;Compare B
.ORG A
RETI ; Timer1 overflow
.ORG C
RETI ; (ADC) ADC Conversion Complete
.ORG E
RETI ; (EE_RDY) EEPROM Ready
.ORG 0
RETI ; (ANA_COMP) Analog Comparator
.ORG 2
RETI ; (TWI) 2-wire Serial Interface
.ORG 4
RETI ; (INT2) External Interrupt Request 2
.ORG 6
RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match
.ORG 8
RETI ; (SPM_RDY) Store Program Memory Ready
.ORG A
RETI
.ORG C
RETI
.ORG E
RETI
.ORG 0
RETI
.ORG 2
RETI
.ORG INT_VECTORS_SIZE
Timer1_IRQ:
CLI
INVBM PORTB, 0
SEI
RETI
;====================================================================
; CODE SEGMENT
;====================================================================
Reset: LDI R16,Low(RAMEND) ; Инициализация стека
OUT SPL,R16 ; Обязательно!!!
LDI R16,High(RAMEND)
OUT SPH,R16
Start:
ldi temp, 0b1111_1111 ; Устанавливает биты в 1 на выход
out DDRB, temp; OUTPUT PORTB0
clr temp
LDI temp,0x0C
STS TCCR1B, temp
LDI temp,0x00
STS TCCR1A, temp
;LDI temp, 0b1000_0000
;OUT SREG, temp
;SETB TIMSK1,TOIE1,R16
SETB TIMSK1,OCIE1A,R16
;LDI temp, 0b0000_0001 ; TOIE in TISK1 OVERFLOW INTERRUPT ENABLE TIMER1 INT ENABLE
;STS TIMSK1, temp
LDI temp, 0x1E
STS OCR1AH, temp
LDI temp, 0x84
STS OCR1AL, temp
SEI
Loop:
;ldi temp, 1 ;Загрузить константу в регистр
;out PortB, temp
;clr temp
;out PortB, temp
;LDI temp,0x0F
;STS OCR1AH, temp
;LDI temp,0xFF
;STS OCR1AL, temp
rjmp Loop
使其工作的主要步骤:
1)处理我们需要的所有中断寄存器。给其他人写RETI。
2)堆栈寄存器中断必须初始化。 (RJMP 重置)
3)写入处理程序定时器。
4)使用DDR(A/B/C/D)将使用过的位转换为使用过的端口。 1 - 输出,0 - 输入。
5) 配置定时器 TCCR1B(对于 1 个定时器)0000_0101 - 1024 预分频器工作一次因为时间溢出。 Table 可以在net中找到。 0000_1101 - 相同,但在第一个中断之后,下一个将由清除溢出定时器自动启动。
6)TCCR1A 0000_0000 如果您不想使用特殊引脚查看定时器状态。
7) 如果您将中断与比较 A (B) 一起使用,您应该在寄存器 TIMSK1 中启用它中断(对于 1 个定时器)。它的 table 可以在 net 中找到。 F.e。 OCIE1A 使比较 A 中断使能。
8)写一个常量到OCR1A(for 1 timer)寄存器
9)启动全局中断
10)制作循环。
这听起来很可怕,但也许这可以帮助像我这样的人。
我不明白如何使用中断和定时器。你能解释一下怎么做吗? 我读了人的,但什么也不懂。这是代码:
.include "C:\Users\user\Downloads/m328Pdef.inc"
.MACRO INVBM
.if @0 < 0x40
PUSH R16
PUSH R17
IN R16,@0
LDI R17,1<<@1
EOR R17,R16
OUT @0,R17
POP R17
POP R16
.else
PUSH R16
PUSH R17
LDS R16,@0
LDI R17,1<<@1
EOR R17,R16
STS @0,R17
POP R17
POP R16
.endif
.ENDM
.ORG 0
ON_RESET:
ldi R16, 0b1000_0001
OUT DDRB, R16
LDI R16, 0b0100_0010 ; CTC mode Timer1
STS TCCR1A, R16 ;SET FLAG ON COMPARE MATCH
LDI R16, 0x0D ; maybe change to 0x05 0b0000_0101
STS TCCR1B, R16 ;SET PRESCALER TO /1024
LDI R16, 0 ; value to compare 0*16+255
STS OCR1AH, R16
LDI R16, 255
STS OCR1AL, R16
MAIN_LOOP:
INVBM PINB, 0
RCALL PAUSE
RJMP MAIN_LOOP
PAUSE:
PLUPE:
IN R16, TIFR0
CPI R16, 0b0000_0010
BRNE PLUPE
LDI R16, 0b0000_0010
OUT TIFR0, R16
RET
我的 LED 没有闪烁。 [连接][1] [1]: https://i.stack.imgur.com/0EUSG.png
;====================================================================
; Main.asm file generated by New Project wizard
;
; Created: Ср апр 7 2021
; Processor: ATmega328P
; Compiler: AVRASM (Proteus)
;====================================================================
.include "C:\Users\user\Downloads\m328Pdef.inc"
;====================================================================
; DEFINITIONS
.list
.def temp=r16
.MACRO INVBM
.if @0 < 0x40
PUSH R16
PUSH R17
IN R16,@0
LDI R17,1<<@1
EOR R17,R16
OUT @0,R17
POP R17
POP R16
.else
PUSH R16
PUSH R17
LDS R16,@0
LDI R17,1<<@1
EOR R17,R16
STS @0,R17
POP R17
POP R16
.endif
.ENDM
.MACRO PUSHF
PUSH R16
IN R16,SREG
PUSH R16
.ENDM
.MACRO POPF
POP R16
OUT SREG,R16
POP R16
.ENDM
.MACRO SETB
.if @0 < 0x20 ; Low IO
SBI @0,@1
.else
.if @0<0x40 ; High IO
IN @2,@0
ORI @2,1<<@1
OUT @0,@2
.else ; Memory
LDS @2,@0
ORI @2,1<<@1
STS @0,@2
.endif
.endif
.ENDM
.dseg
.cseg
.ORG [=10=]0 ; (RESET)
RJMP RESET
.ORG [=10=]2
RETI ; (INT0) External Interrupt Request 0
.ORG [=10=]4
RETI ; (INT1) External Interrupt Request 1
.ORG [=10=]6
RETI ; (TIMER2 COMP) Timer/Counter2 Compare Match
.ORG [=10=]8
RETI ; (TIMER2 OVF) Timer/Counter2 Overflow
.ORG [=10=]A
RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event
.ORG [=10=]C
RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A
.ORG [=10=]E
RETI ; (TIMER1 COMPB) Timer/Counter1 Compare Match B
.ORG 0
RETI ; (TIMER1 OVF) Timer/Counter1 Overflow
.ORG 2
RETI ; (TIMER0 OVF) Timer/Counter0 Overflow
.ORG 4
RETI ; Timer1 Capture
.ORG 6
RJMP Timer1_IRQ ; Timer1 compare A
.ORG 8
RETI ;Compare B
.ORG A
RETI ; Timer1 overflow
.ORG C
RETI ; (ADC) ADC Conversion Complete
.ORG E
RETI ; (EE_RDY) EEPROM Ready
.ORG 0
RETI ; (ANA_COMP) Analog Comparator
.ORG 2
RETI ; (TWI) 2-wire Serial Interface
.ORG 4
RETI ; (INT2) External Interrupt Request 2
.ORG 6
RETI ; (TIMER0 COMP) Timer/Counter0 Compare Match
.ORG 8
RETI ; (SPM_RDY) Store Program Memory Ready
.ORG A
RETI
.ORG C
RETI
.ORG E
RETI
.ORG 0
RETI
.ORG 2
RETI
.ORG INT_VECTORS_SIZE
Timer1_IRQ:
CLI
INVBM PORTB, 0
SEI
RETI
;====================================================================
; CODE SEGMENT
;====================================================================
Reset: LDI R16,Low(RAMEND) ; Инициализация стека
OUT SPL,R16 ; Обязательно!!!
LDI R16,High(RAMEND)
OUT SPH,R16
Start:
ldi temp, 0b1111_1111 ; Устанавливает биты в 1 на выход
out DDRB, temp; OUTPUT PORTB0
clr temp
LDI temp,0x0C
STS TCCR1B, temp
LDI temp,0x00
STS TCCR1A, temp
;LDI temp, 0b1000_0000
;OUT SREG, temp
;SETB TIMSK1,TOIE1,R16
SETB TIMSK1,OCIE1A,R16
;LDI temp, 0b0000_0001 ; TOIE in TISK1 OVERFLOW INTERRUPT ENABLE TIMER1 INT ENABLE
;STS TIMSK1, temp
LDI temp, 0x1E
STS OCR1AH, temp
LDI temp, 0x84
STS OCR1AL, temp
SEI
Loop:
;ldi temp, 1 ;Загрузить константу в регистр
;out PortB, temp
;clr temp
;out PortB, temp
;LDI temp,0x0F
;STS OCR1AH, temp
;LDI temp,0xFF
;STS OCR1AL, temp
rjmp Loop
使其工作的主要步骤: 1)处理我们需要的所有中断寄存器。给其他人写RETI。
2)堆栈寄存器中断必须初始化。 (RJMP 重置)
3)写入处理程序定时器。
4)使用DDR(A/B/C/D)将使用过的位转换为使用过的端口。 1 - 输出,0 - 输入。
5) 配置定时器 TCCR1B(对于 1 个定时器)0000_0101 - 1024 预分频器工作一次因为时间溢出。 Table 可以在net中找到。 0000_1101 - 相同,但在第一个中断之后,下一个将由清除溢出定时器自动启动。
6)TCCR1A 0000_0000 如果您不想使用特殊引脚查看定时器状态。
7) 如果您将中断与比较 A (B) 一起使用,您应该在寄存器 TIMSK1 中启用它中断(对于 1 个定时器)。它的 table 可以在 net 中找到。 F.e。 OCIE1A 使比较 A 中断使能。
8)写一个常量到OCR1A(for 1 timer)寄存器
9)启动全局中断
10)制作循环。
这听起来很可怕,但也许这可以帮助像我这样的人。