Forum: Mikrocontroller und Digitale Elektronik ATMega168: kein SPIF nach SPI-Transfer


von Anton Hermann S. (antonhermann)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hab das Problem bei einer SPI-Übertragung, dass nach dem Versenden 
des ersten Bytes das SPIF-Flag nicht gesetzt wird und somit auch nicht 
in die ISR verzweigt wird.

Eigentlich hatte das Programm schon auf einem ATMega 8 problemlos 
funktioniert. Ich musste aber aus Speicherplatzgründen auf einen ATMega 
168 umsteigen und seit dem nehmen die Probleme keine Ende :-(

Zum Testen habe ich folgendes kleine Testprogramm eingefügt:
1
.ifdef DEBUG_FLAG
2
.cseg
3
; Set SCK, MOSI and SS1 as output, MISO as input, other don't care
4
  ldi r17, 0b1010_1111  ; PB5=SCK; PB4=MISO; PB3=MOSI; PB2=/SS1; PB1= /SS2;
5
  out DDRB,r17
6
  ldi r17, 0b1000_0111  ; 
7
  out PORTB, 17                
8
9
; Enable SPI, Master, set clock rate fck/16
10
  ldi r17,INIT_SPCR  ; 0b1101_1110
11
  out SPCR,r17    
12
13
  sbi PORTB, BIT_SPI_SS_DAC  ; Slave-Select DAC rücksetzen 
14
15
DBG_LOOP:
16
  cbi PORTB, BIT_SPI_SS_DAC     ; Slave-Select DAC setzen 
17
  ; Start transmission of data (r16)
18
  ldi r16,0xA5                  ; Beispielwert
19
  out SPDR,r16
20
Wait_Transmit:
21
  ; Wait for transmission complete
22
  in r17, SPSR
23
  call DEBUG_BYTE               ; Byte auf dem LA ausgeben (b7...b0)
24
  sbrs r17, SPIF
25
  rjmp Wait_Transmit
26
  sbi PORTB, BIT_SPI_SS_DAC     ; Slave-Select DAC rücksetzen 
27
  cbi PORTB, BIT_SPI_SS_DAC     ; Slave-Select DAC erneut setzen 
28
  ldi r16,0x5A                  ; zweiter Beispielwert
29
  out SPDR,r16
30
Wait_Transmit1:
31
  in r17, SPSR
32
  sbrs r17, SPIF
33
  rjmp Wait_Transmit1
34
  sbi PORTB, BIT_SPI_SS_DAC     ; Slave-Select DAC rücksetzen 
35
  rjmp DBG_LOOP
36
.endif

Meine Erwartungshaltung ist, dass auf dem SPI zuerst der Wert 0xA5 und 
danach der 0x5A ausgegeben wird. Leider sehe ich nur den ersten Wert 
(siehe beiliegenden Screenshot vom LA). Offensichtlich wird das 
SPIF-Flag nicht gesetzt (der erste braune Trace: nach einem kurzen 
Startimpuls werden vom SPSR b7...b0 ausgegeben. Es sitzt nur das SPX 
Bit).
Mir ist nicht klar warum ...
Recherchen im Formum haben ergeben, dass der SS-Pin PB2 ist als Ausgang 
konfiguriert sein muss. Das solle gegeben sein und der /SS Pin wechselt 
auch wie erwartet seinen Wert (Im Bild der rote Trace (A1), ist auf dem 
LA aber invertiert dargestellt).
Was übersehe ich ?

Schon mal vielend Dank vorab für die Hilfe.

Viele Grüße,
Anton

von c-hater (Gast)


Lesenswert?

Anton Hermann S. schrieb:

> ich hab das Problem bei einer SPI-Übertragung, dass nach dem Versenden
> des ersten Bytes das SPIF-Flag nicht gesetzt wird und somit auch nicht
> in die ISR verzweigt wird.

Das kann nicht sein. Vollkommen unmöglich.

> Eigentlich hatte das Programm schon auf einem ATMega 8 problemlos
> funktioniert. Ich musste aber aus Speicherplatzgründen auf einen ATMega
> 168 umsteigen

Dann stimmt wohl einfach der Vector nicht.

von S. Landolt (Gast)


Lesenswert?

Also ich weiß ja nicht: für uns unsichtbare Parameter, ebenfalls 
unsichtbar die Routine DEBUG_BYTE, und das hier wird garantiert nicht 
assembliert:

>   out PORTB, 17

von Anton Hermann S. (antonhermann)


Lesenswert?

Hallo,

das war es !
Der ATMega 8 belegt nur ein Wort pro Vektor, der ATMega 168 aber zwei.
Bei den nicht benötigten Vektoren stand nur RETI. Dieser Befehl belegt 
aber nur ein Wort im Interrupt-Vektor. Ein NOP nach jedem RETI hat's 
dann gerichtet:
1
                               ; Interrupt Vektoren AT-MEGA 168 Sprungverteiler
2
000000 940c 04a4    jmp START  ; 01: Reset-Vektor (extern, intern, Watch-Dog-Reset)
3
000002 9518         reti       ; 02: EXT_INT0 externer Interrupt 0
4
000003 0000         nop
5
000004 9518         reti       ; 03: EXT_INT1 externer Interrupt 1
6
000005 0000         nop
7
000006 9518         reti       ; 04: PCINT0
8
000007 0000         nop
9
000008 9518         reti       ; 05: PCINT1
10
000009 0000         nop
11
00000a 9518         reti       ; 06: PCINT2
12
00000b 0000         nop
13
00000c 9518         reti       ; 07: WDT
14
00000d 0000         nop
15
00000e 940c 017b    jmp ISR_TIM2_CMA ; 08: TIMER2_CMPA Timer 2 Compare match A
16
000010 9518         reti       ; 09: TIMER2_CMPB Timer 2 Compare match B
17
000011 0000         nop
18
000012 9518         reti       ; 10: TIMER2_OVF Timer 2 Overflow
19
000013 0000         nop
20
000014 9518         reti       ; 11: TIMER1_CPE Timer 1 Capture Event
21
000015 0000         nop
22
000016 9518         reti       ; 12: TIMER1_CMPA Timer 1 Compare Match A
23
000017 0000         nop
24
000018 9518         reti       ; 13: TIMER1_CMPB Timer 1 Compare Match B
25
000019 0000         nop
26
00001a 9518         reti       ; 14: TIMER1_OVF Timer 1 Overflow
27
00001b 0000         nop
28
00001c 9518         reti       ; 15: TIMER0_CMPA Timer 0 Compare Match A
29
00001d 0000         nop
30
00001e 9518         reti       ; 16: TIMER0_CMPB Timer 0 Compare Match B
31
00001f 0000         nop  
32
000020 940c 00f7    jmp ISR_TIM0_OVR ; 17: TIMER0_OVF Timer 0 Overflow
33
000022 940c 01ce    jmp ISR_SPI_STCP ; 18: SPI_STC Serial Transfer complete          
34
000024 9518         reti       ; 19: USART RX_CP USART Rx complete          
35
000025 0000         nop
36
000026 9518         reti       ; 20: USART UDRE  USART Data Register Empty
37
000027 0000         nop
38
000028 9518         reti       ; 21: USART TX_CP USART Tx complete  
39
000029 0000         nop        
40
00002a 940c 0258    jmp ISR_ADC_CCP  ; 22: ADC_CP ADC Conversion complete
41
00002c 9518         reti       ; 23: EEP_RDY EEPROM Ready
42
00002d 0000         nop
43
00002e 9518         reti       ; 24: ANALOG_COMP Analog Comperator   
44
00002f 0000         nop
45
000030 9518         reti       ; 25: TWI I2C Serial Interface
46
000031 0000         nop
47
000032 9518         reti       ; 26: SPM_RDY Store Program Memory Ready
48
000033 0000         nop

Dass sich das Testprogramm auch merkwürdig verhalten hatte, konnte ich 
dann auch nachvollziehen:

Die Interrupts waren aktiv (SEI), was dazu führte dass der Int-Vektor 
richtig angesprungen wurde. Dadurch wurde das SPIF-Flag von der Hardware 
gelöscht und nach RETI, das dort durch die Verschiebung 
fälschlicherweise stand, war es nach der Rückkehr ins Testprogramm beim 
Lesen des SPSR natürlich nicht mehr gesetzt.

Besten Dank für den Tipp und noch ein schönes Wochenende !

Viele Grüße,
Anton

von Franz M. (elmo64)


Lesenswert?


von Falk B. (falk)


Lesenswert?

Anton Hermann S. schrieb:
> Der ATMega 8 belegt nur ein Wort pro Vektor, der ATMega 168 aber zwei.
> Bei den nicht benötigten Vektoren stand nur RETI. Dieser Befehl belegt
> aber nur ein Wort im Interrupt-Vektor. Ein NOP nach jedem RETI hat's
> dann gerichtet:

Naja, eher ein Workaround. Wenn man es richtig und solide machen will, 
nimmt man eine Vektortabelle mit den vordefinierten Namen, siehe 
m168def.inc. Oder wenigstens die Adressen für die benutzten Vektoren.
1
.cseg
2
.org 0
3
     rjmp  start
4
.org OC2Aaddr
5
    jmp ISR_TIM2_CMA
6
7
start:

von Anton Hermann S. (antonhermann)


Lesenswert?

Hallo,

A. M. schrieb:
> https://ww1.microchip.com/downloads/en/appnotes/doc2554.pdf

Das Dokument beschreibt mein Ungemach hinreichend gut. Mein Pech, es lag 
mir leider bisher nicht vor. Ich hatte mich zu sehr auf das erste 
Dokument versteift...

S. Landolt schrieb:
> unsichtbar die Routine DEBUG_BYTE, und das hier wird garantiert nicht
> assembliert:
>
>>   out PORTB, 17

Nur der Vollständigkeit halber: Die Routine DEBUG_BYTE gibt auf einem 
freien Pin das übergeben Byte seriell aus (ein Überbleibsel aus dem 
ATMega8 als Debug-Hilfe). Vermutlich bin ich beim Übertragen des 
Listing-Auszugs auf die Entf - Taste gekommen, weshalb das r vor der 17 
fehlte. Assembliert hatte es...

Falk B. schrieb:
> Naja, eher ein Workaround. Wenn man es richtig und solide machen will,
> nimmt man eine Vektortabelle mit den vordefinierten Namen, siehe
> m168def.inc. Oder wenigstens die Adressen für die benutzten Vektoren.

Ich belasse es aktuell noch beim Workaround, der bez. Namen dem 
Umschreiben vom ATMega8 auf den 168er geschuldet ist. Wenn mal alles 
wieder läuft, gehts ans Aufhübschen...

An der Stelle nochmal Dank an alle für die Hinweise, Tipps und 
Unterstützung.

Viele Grüße,
Anton

von S. Landolt (Gast)


Lesenswert?

> beim Übertragen des Listing-Auszugs auf die Entf - Taste gekommen
Auch bei dem für uns unsichtbaren Befehl sei? Denn:

> dann auch nachvollziehen:
> Die Interrupts waren aktiv (SEI), was dazu führte ...

Hätte das sei im Programm gestanden, wäre natürlich sofort die Frage 
nach den Interruptvektoren plus ISRs gekommen.

Fazit:
Von den Wahrsager-Fähigkeiten eines c-haters abgesehen, ist es schwer, 
fundierte Aussagen zu treffen ohne sehen zu können, was beim 
Fragesteller realiter vorliegt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.