Ja werd den Code nochmal posten. Ich glaub du meinst mit "halbe Stunde die Buchstaben ordnen", dass es kein CR gibt sondern nur LF (vom Linux). Werd nur den Assemberteil rauskopieren.
CTC Mode darf ich für dieses Teilbeispiel eben NICHT verwenden. Das PWM Signal soll auf 4 Arten erzeugt werden.
1) Busywait (funktionniert so wies soll)
2) Overflow (geht eben ned so gut)
3) CTC (funktionniert so wies soll)
4) FastPWM (funktionniert so wies soll)
Das ist eine Laborübung aber ich hab mir das Laborkit ausgeborgt um auch zuhause arbeiten zu können. Ich kann durch andere Kurse bedingt nicht imma hinschaun. Dort sind ausserdem auch nur Tutoren, da weiß der eine mal ein bisschen mehr, der andere weniger. Ich glaube aber auch, dass die Frage gar nicht so genau beantwortet gehört ("How long is the signal really high and low in each of these methods and why? How do you
compute the actual high- and low-times? Verify your calculations with the oscilloscope.") aber ich möchte es persönlich wissen.
Code (mit C-Code Kommentaren):
Code:
ISR_SIG_OVERFLOW1:
;__attribute__((naked)) SIGNAL(SIG_OVERFLOW1) {
; static uint8_t delay_select = 0;
; if(delay_select == 0) {
lds r18, 0x0060 ; # +2 cycles
and r18, r18 ; # +1 cycle
brne .+8 ; zu cbi # +2/1 cycles
; P_PORT |= (1<<P_NR);
sbi 0x12, 5 ; 18 # +2 cycles
; TCNT1 = PRELOAD_50US;
ldi r24, 0x9C ; 156 # +1 cycle
ldi r25, 0xFF ; 255 # +1 cycle
rjmp .+6 ; zum ersten out # +2 cycles
; } else {
; P_PORT &= ~(1<<P_NR);
cbi 0x12, 5 ; 18 ; # +2 cycles
; TCNT1 = PRELOAD_25US;
ldi r24, 0xCE ; 206 # +1
ldi r25, 0xFF ; 255 # +1
out 0x2d, r25 ; 45 # +1
out 0x2c, r24 ; 44 # +1
; }
; /* toggle delay_select */
; delay_select = 1 - delay_select;
ldi r24, 0x01
sub r24, r18
sts 0x0060, r24
; asm volatile("reti \n\t" ::);
reti
;}
MAIN:
;void main() {
; /* Pin P_NR as output, initially 0 */
; P_DDR |= (1<<P_NR);
; /* enable Idle sleep mode */
; MCUCR |= (1<<SE);
; /* turn off AC to reduce power consumption */
; ACSR |= (1<<ACD);
; /* Timer1 in Normal Mode
; * default, so nothing to do */
; /* Enable Timer1 overflow interrupt */
; TIMSK |= (1<<TOIE1);
; /* Preload Timer1 to get Interrupt after 25us */
; TCNT1 = PRELOAD_25US;
; /* Start TIMER1 clock F_CPU/8 */
; TCCR1B |= (1<<CS11);
; /* enable interrupts */
; sei();
ldi r28, 0x5F ; 95
ldi r29, 0x04 ; 4
out 0x3e, r29 ; 62
out 0x3d, r28 ; 61
sbi 0x11, 5 ; 17
in r24, 0x35 ; 53
ori r24, 0x40 ; 64
out 0x35, r24 ; 53
sbi 0x08, 7 ; 8
in r24, 0x39 ; 57
ori r24, 0x04 ; 4
out 0x39, r24 ; 57
ldi r24, 0xCE ; 206
ldi r25, 0xFF ; 255
out 0x2d, r25 ; 45
out 0x2c, r24 ; 44
in r24, 0x2e ; 46
ori r24, 0x02 ; 2
out 0x2e, r24 ; 46
sei
; while(1)
; asm volatile("sleep \n\t");
sleep
rjmp .-4 ; zu sleep
;}
Code (ohne C-Code Kommentare):
Code:
ISR_SIG_OVERFLOW1:
; if togglevariable == 0
lds r18, 0x0060 ; # +2 cycles
and r18, r18 ; # +1 cycle
brne .+8 ; zu cbi # +2/1 cycles
; LED setzen
sbi 0x12, 5 ; # +2 cycles
; preload 50us;
ldi r24, 0x9C ; 156 # +1 cycle
ldi r25, 0xFF ; 255 # +1 cycle
rjmp .+6 ; zum ersten out # +2 cycles
; LED löschen
cbi 0x12, 5 ; # +2 cycles
; preload 25us
ldi r24, 0xCE ; 206 # +1
ldi r25, 0xFF ; 255 # +1
; preloadwert schreiben
out 0x2d, r25 ; 45 # +1
out 0x2c, r24 ; 44 # +1
; toggle variable neu setzen
ldi r24, 0x01
sub r24, r18
sts 0x0060, r24
reti
MAIN:
ldi r28, 0x5F ; 95
ldi r29, 0x04 ; 4
out 0x3e, r29 ; 62
out 0x3d, r28 ; 61
sbi 0x11, 5 ; 17
in r24, 0x35 ; 53
ori r24, 0x40 ; 64
out 0x35, r24 ; 53
sbi 0x08, 7 ; 8
in r24, 0x39 ; 57
ori r24, 0x04 ; 4
out 0x39, r24 ; 57
ldi r24, 0xCE ; 206
ldi r25, 0xFF ; 255
out 0x2d, r25 ; 45
out 0x2c, r24 ; 44
in r24, 0x2e ; 46
ori r24, 0x02 ; 2
out 0x2e, r24 ; 46
sei
sleep
rjmp .-4 ; zu sleep
Lesezeichen