Search code examples
assemblytimeravr

AVR Timer interrupts


I don't understand hwo to work with interrupts and timer. Can you explain how to? I read man's but didn't understand nothing. This is the code:

    .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

My led didn't blink. [Connection][1] [1]: https://i.sstatic.net/0EUSG.png


Solution

  •   ;====================================================================
    ; 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 $000        ; (RESET) 
             RJMP   RESET
             .ORG $002
             RETI             ; (INT0) External Interrupt Request 0
             .ORG $004
             RETI             ; (INT1) External Interrupt Request 1
             .ORG $006
             RETI             ; (TIMER2 COMP) Timer/Counter2 Compare Match
             .ORG $008
             RETI             ; (TIMER2 OVF) Timer/Counter2 Overflow
             .ORG $00A
             RETI             ; (TIMER1 CAPT) Timer/Counter1 Capture Event
             .ORG $00C 
             RETI             ; (TIMER1 COMPA) Timer/Counter1 Compare Match A
             .ORG $00E
             RETI             ; (TIMER1 COMPB) Timer/Counter1 Compare Match B
             .ORG $010
             RETI             ; (TIMER1 OVF) Timer/Counter1 Overflow
             .ORG $012
             RETI ; (TIMER0 OVF) Timer/Counter0 Overflow
             .ORG $014
             RETI           ; Timer1 Capture
             .ORG $016
             RJMP   Timer1_IRQ           ; Timer1 compare A
             .ORG $018
             RETI            ;Compare B
             .ORG $01A
             RETI           ; Timer1 overflow
             .ORG $01C
             RETI             ; (ADC) ADC Conversion Complete
             .ORG $01E
             RETI             ; (EE_RDY) EEPROM Ready
             .ORG $020
             RETI            ; (ANA_COMP) Analog Comparator
             .ORG $022
             RETI             ; (TWI) 2-wire Serial Interface
             .ORG $024
             RETI             ; (INT2) External Interrupt Request 2
             .ORG $026
             RETI             ; (TIMER0 COMP) Timer/Counter0 Compare Match
             .ORG $028
             RETI             ; (SPM_RDY) Store Program Memory Ready
            .ORG $02A
             RETI 
             .ORG $02C
             RETI 
             .ORG $02E
             RETI 
             .ORG $030
             RETI 
             
             .ORG $032
             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
    

    MAIN Steps to make it works: 1)Make handlers to all we need interrupt registers. To other write RETI.

    2)Stack register interrupt must be initialised. (RJMP RESET)

    3)Write handler Timer.

    4)Make used bits to the used ports with DDR(A/B/C/D). 1 - output, 0 - input.

    5)Configure Timers TCCR1B (for 1 timer) 0000_0101 - 1024 prescaler Works once becaule times becomes overflow. Table can be found in net. 0000_1101 - Same but after 1st interrupt next will be start automatically by clear overflow timer.

    6)TCCR1A 0000_0000 if u don't want to use special pin to see timer condition.

    7)if u use interrupt with compare A (B) u should enable it interrupts in register TIMSK1 (for 1 timer). Its table can be found in net. F.e. OCIE1A makes compare A interrupt enable.

    8)Write A constant to the OCR1A (for 1 timer) register.

    9)Start global interrupt

    10)Make Loop sycle.

    It sounds horrible but maybe this can help people like me.