Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:multiasm:exercisesbook:avr:sut:scenarios:avr5 [2026/05/04 12:34] pczekalskien:multiasm:exercisesbook:avr:sut:scenarios:avr5 [2026/05/04 13:27] (current) pczekalski
Line 10: Line 10:
 Create an application that toggles the built-in LED (GPIO 13) on permanently, and then uses a timer (Timer1, channel B) to control LED4 (GPIO 10). The LED4 should present a heartbeat pattern.  Create an application that toggles the built-in LED (GPIO 13) on permanently, and then uses a timer (Timer1, channel B) to control LED4 (GPIO 10). The LED4 should present a heartbeat pattern. 
  
-** Result **\\+In this example, we will build the code from the bottom up.
  
 +** Result **\\
 +Observe the heartbeat on LED4 (GPIO 10) and the solid LED on GPIO 13 (LED1, built-in). 
  
 ** Start **\\ ** Start **\\
Line 17: Line 19:
  
 ** Step 1 **\\ ** Step 1 **\\
-Compose a template for your application that includes declarations for GPIO and a timer. We use Timer1 (16-bit) in CTC mode:+Compose a template for your application that includes declarations for GPIO and a timer. We use Timer1 (16-bit) to generate PWM on GPIO 10 (channel B):
 <code asm> <code asm>
---- Register Address Mapping --- +.equ DDRB,   0x04   Port B Data Direction Register (I/O) 
-.equ SREG   0x3F      ; Status Register +.equ PORTB 0x05   Port B Data Register (I/O) 
-.equ SPH,     0x3E      ; Stack Pointer High +.equ SPCR,   0x2C   ; SPI Control Register (I/O) 
-.equ SPL    0x3D      Stack Pointer Low+.equ MCUSR,  0x34   ; MCU Status Register (I/O) 
 +.equ SPL,    0x3D   ; Stack Pointer Low (I/O) 
 +.equ SPH,    0x3E   ; Stack Pointer High (I/O) 
 +.equ WDTCSR0x60   Watchdog Timer Control Register (Memory) 
 +.equ TCCR1A, 0x80   ; Timer1 Control Register A (Memory) 
 +.equ TCCR1B, 0x81   ; Timer1 Control Register B (Memory) 
 +.equ OCR1BL, 0x8A   ; Timer1 Output Compare Register B Low 
 +.equ OCR1BH, 0x8B   ; Timer1 Output Compare Register B High
  
-.equ DDRB,    0x04      ; Data Direction Port B +; Bit Constants 
-.equ PINB,    0x03      ; Input Pins Port B (Toggle Shortcut) +.equ PB2,         ; Pin 10 
-.equ LED_PIN, 5         ; Built-in LED (Digital 13 / PB5)+.equ PB5,         ; Pin 13 
 +.equ COM1B1, 5 
 +.equ WGM10, 
 +.equ CS11,   1
  
-.equ RAMEND,  0x08FF +.section .text
-; --- Timer1 Register Mapping --- +
-.equ TCCR1A,  0x80      ; Timer1 Control A +
-.equ TCCR1B,  0x81      ; Timer1 Control B +
-.equ OCR1AH,  0x89      ; Output Compare High +
-.equ OCR1AL,  0x88      ; Output Compare Low +
-.equ TIMSK1,  0x6F      ; Timer1 Interrupt Mask +
-.equ TOP_VAL, 0x3D08    ; It is for 1s, adjust for 2s+
  
-.equ WGM12, 3           WGM12 is on bit 3 of the TCCR1B +========================================================== 
-.equ CS12,  2            CS12 is on bit 2 of the TCCR1B +CLASSICAL INTERRUPT VECTOR TABLE (104 Bytes) 
-.equ CS10,  0            CS10 is on bit 0 of the TCCR1B +==========================================================
- +
-.section .text+
 .org 0x0000 .org 0x0000
-    rjmp RESET           +    jmp RESET
-.org 0x002C             ; Assembler treats .org as bytes, use 0x002C +
-    rjmp TIMER_ISR +
-.org 0x0034             ; Jump past vectors to start logic +
  
 RESET: RESET:
- +....
-; --- Idle Main Loop --- +
-LOOP: +
-    rjmp LOOP+
 </code> </code>
  
 ** Step 2 **\\ ** Step 2 **\\
-Initialise stack (obligatory, we use ISR function calls) and configure BP5 (GPIO 13as output:+Initialise stack (obligatory, we use ISR function calls) and configure GPIOs 10 and 13 as outputs and enable GPIO 13 connected LED on:
 <code asm> <code asm>
 ... ...
-    ; Prepare stack 
    ldi r16, hi8(RAMEND)    ldi r16, hi8(RAMEND)
    out SPH, r16    out SPH, r16
Line 66: Line 61:
    out SPL, r16    out SPL, r16
  
-    ; Configure PB5 (built-in LEDGPIO 13as Output +    ; Setup Pins using Atomic 'sbi' (Set Bit in I/O) 
-    sbi DDRB, LED_PIN+    sbi DDRBPB5       ; Set Pin 13 as Output 
 +    sbi DDRB, PB2       ; Set Pin 10 as Output 
 +    cbi PORTB, PB5      ; Turn ON Pin 13
 ... ...
 </code> </code>
-Note the different method for setting GPIO 13 as an output compared to the [[avr1|]] scenario.\\ 
  
 ** Step 3 **\\ ** Step 3 **\\
-Configure timer and enable interrupts:+Configure timer for PWM (Timer1, channel B -> GPIO 10):
 <code asm> <code asm>
 ... ...
-    ; Set Timer1 in CTC Mode +    ldi r16, (1 << COM1B1(1 << WGM10)
-    ; Load the compare value for 1 second +
-    ldi r16, hi8(TOP_VAL) +
-    sts OCR1AH, r16 +
-    ldi r16, lo8(TOP_VAL) +
-    sts OCR1AL, r16 +
- +
-    ; TCCR1A: Default (0x00) +
-    ldi r16, 0x00+
     sts TCCR1A, r16     sts TCCR1A, r16
- +    ldi r16, (1 << CS11)
-    ; TCCR1B:  +
-    ; Bit 3 (WGM12) = 1 (CTC Mode) +
-    ; Bit 2 (CS12)  = 1 (Prescaler 1024) +
-    ; Bit 0 (CS10)  = 1 (Prescaler 1024) +
-    ldi r16, (1 << WGM12) | (1 << CS12) | (1 << CS10)+
     sts TCCR1B, r16     sts TCCR1B, r16
- +    ldi r16, 0 
-    ; 4. Enable Compare Match A Interrupt +    sts OCR1BH, r16 
-    ldi r16, (1 << 1)   ; OCIE1A bit +    sts OCR1BL, r16
-    sts TIMSK1, r16 +
- +
-    ; 5. Global Interrupt Enable +
-    sei+
 ... ...
  
Line 105: Line 84:
  
 ** Step 4 **\\ ** Step 4 **\\
-Your loop function remains idlebut you need an ISR implementatione.glike this:+NowAFTER the loop section (you perhaps don't have it yetso put a dummy one in the code, temporary, implement functions to delay and to blinkDelays based on timer tick counting, not a timer, because we use Timer1 for PWM generation. 
 +There are 3 functions: 
 +  * Function ''pulse'' modifies Timer1, channel B comparator value, thus changing the duty cycle of the PWM signal. Change is done every 1 ms. The duty cycle varies linearly. 
 +  * Function ''delay_1ms'' is argument-less and delays (block execution using a loop) for about 1ms.\\ 
 +  * Function ''delay_N_ms'' is just a wrap-arround over ''delay_1ms''
 <code asm> <code asm>
-TIMER_ISR+; void pulse(void) 
-    ; Toggle LED using the PINB write trick. +pulse
-    ; Since 'sbidoes not modify SREG flagswe do not need  +    ldi r18, 0 
-    ; to save/restore context (push/pop r16, etc). +fade_in: 
-    sbi PINB, LED_PIN +    sts OCR1BL, r18 
-    reti+    rcall delay_1ms 
 +    inc r18 
 +    brne fade_in 
 + 
 +    ldi r18, 255 
 +fade_out: 
 +    sts OCR1BL, r18 
 +    rcall delay_1ms 
 +    dec r18 
 +    brne fade_out 
 +     
 +    sts OCR1BL, r18  
 +    ret 
 + 
 +void delay_N_ms(uint8_t ms) 
 +; Expects argument 'ms' in r24 
 +delay_N_ms: 
 +    tst r24 
 +    breq dn_done 
 +dn_loop: 
 +    rcall delay_1ms 
 +    dec r24 
 +    brne dn_loop 
 +dn_done: 
 +    ret 
 + 
 +void delay_1ms(void) 
 +delay_1ms: 
 +    ldi r21, 21 
 +d1_loop: 
 +    ldi r22, 250 
 +d2_loop: 
 +    dec r22 
 +    brne d2_loop 
 +    dec r21 
 +    brne d1_loop 
 +    ret 
 +</code> 
 +<note tip>Remember that the ''delay_N_ms'' function operates on 8-bit argumentsso the maximum delay is 255ms. If you need a longer one, modify it so it works with 16-bit arguments (''r25:r24'')</note> 
 + 
 +** Step 5 **\\ 
 +Set the main loop. Here you're on your own, but the hint for the algorithm to have a real heartbeat is as follows: 
 +<code> 
 +loop infinitely: 
 +    // --- First beat (Lub) --- 
 +    pulse() 
 +    delay(200)   // Wait 200 milliseconds 
 + 
 +    // --- Second beat (Dub--- 
 +    pulse() 
 +    delay(750)   // Wait 750 milliseconds (250 + 250 + 250)
 </code> </code>
  
 ** Result validation **\\ ** Result validation **\\
-The LED should be flashing on an implemented time basis. Note that some irregularity may is observed due to the nature of video streaming over the network. It is natural and OK. If you want to measure more precise timing, increase the period, e.g. to 3s.+The LED4 should be flashing at a set interval (heartbeat), while LED1 (built-in) should be on. Note that some irregularity may is observed due to the nature of video streaming over the network. If you cannot clearly observe via the video stream, increase the heart rate via either the main loop or internally in the ''pulse'' function, e.g., by calling ''delay_N_ms'' with an appropriate parameter (''r24'') instead of ''delay_1ms''.
  
 ** FAQ **\\ ** FAQ **\\
 When using the printed version of this manual, please refer to the latest online version for the most up-to-date list of FAQs.\\ When using the printed version of this manual, please refer to the latest online version for the most up-to-date list of FAQs.\\
  
-**It does not flash**: Did you compile and upload to the device? Those are separate steps: it is not enough to just compile, but you also need to "flash" the MCU. Also, check your video stream if it "ticks" - the time embedded into the video stream should change. Your code may be working OK, but the video stream can be frozen, so you cannot see it working properly!+**It does not work at all**: Did you compile and upload to the device? Those are separate steps: it is not enough to just compile, but you also need to "flash" the MCU. Also, check your video stream if it "ticks" - the time embedded into the video stream should change. Your code may be working OK, but the video stream can be frozen, so you cannot see it working properly!\\ 
 +**Built-in LED is off**: Mind it is driven by zero, not by one.
  
-// 
  
  
en/multiasm/exercisesbook/avr/sut/scenarios/avr5.1777887291.txt.gz · Last modified: by pczekalski
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0