www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega32 - Timer0 spinnt bei UART Empfang


Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle zusammen,

Problem kurz umrissen:
Unten gezeigter Code generiert ein PWM auf PortA, sobald stress am UART 
ist (viele Daten schnell hintereinander) - spinnt das PWM (wird länger, 
kürzer)

Zur Schaltung:
Seriell daten komemn vom Rechner BAUD 9600, über Max232 Schaltung - da 
diese mit einem anderen UC Prima zusammen arbeitet, schließe ich sie als 
Fehlerquelle aus.

Der Atmega ist standartmäßig beschaltet mit nem externen Quarz 16 Mhz, 
Pullup am Reset.

Atmegas hab ich auch schon 3 Kollegen durch - also wirds an ihm selber 
wohl auch nicht liegen.



Für die dies genauer Intressiert:

Das ganze soll ne PWM schaltung für Servos werden. Mithilfe des Atmegas. 
Da der gute Atmega teuer ist soll er 4 oder mehr Servos ansteuueren, 
wodurch die "interne" PWM lösung wegfällt.

Ich habe mir also eine eigene Variante gebaut die mit Hilfe der Timer im 
CTC Modus die PWM Modulation übernimmt. Das ganze funktioniert im auch 
sehr schön. Die beim reset gesetzten Daten werden als PWM moduliert und 
an den PINS auf PORT A ausgegeben. Nun sollte per UART die Position 
gesetzt werden. Funktionuierte auch sehr gut solange langsam einzellne 
Werte gesetzt werden - sobald aber richtig stress am UART war haben die 
Servos angefangen rumzuspinen - das Oszi zeigte die PWM Signale sind 
hinüber.
Also dachte ich: okay irgendwo in der Laufzeit der ISRs verrechnet und 
habe das Problem immer weiter runtergebrochen und bin bei untem 
gezeigtem Code gelandet: Der Gag - sobald Stress am UART ist spinnt das 
PWM signal auf PORTA.

Irgend jemand ne Idee woran das liegen kann. Nutzen Uart und der Timer 
irgendwas gemeinsam wovon ich nichts weiß...


.include "m32def.inc"

.def tmpwork=r16

.org 0
rjmp rst_handler
.org T0OVFaddr
rjmp t2_handler



t2_handler:
  CLI
  PUSH  tmpwork
  IN    tmpwork, PORTA  ; complement Pins on PortA
  COM    tmpwork
  OUT    PORTA, tmpwork
  COM    tmpwork
  POP    tmpwork
  RETI



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; "Main"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rst_handler:
  CLI
  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Init Ports
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork,0xFF      ; Port A as output
  OUT  DDRA, tmpwork
  OUT  PORTA, tmpwork
  OUT  DDRB, tmpwork
  OUT  PORTB, tmpwork

  OUT  DDRC, tmpwork
  OUT  PORTC, tmpwork

  LDI  tmpwork, 0x00
  OUT PORTA, tmpwork

  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Init Stack
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork,HIGH(MAXRAM)  ; Setting up Stack
  OUT  SPH,tmpwork
  LDI  tmpwork,LOW(MAXRAM)  ; Setting up Stack
  OUT  SPL,tmpwork


  ;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Init Timer
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork, (1<<CS00)
  OUT  TCCR0, tmpwork
  LDI     tmpwork, (1<<TOIE0)      ; TOIE0: Interrupt bei Timer Overflow
    OUT    TIMSK, tmpwork

  SEI

hang:
  SEI
  RJMP  hang

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Der Gag - sobald Stress am UART ist spinnt das
>PWM signal auf PORTA.

Kann nicht sein. Dein Code benutzt keinen UART.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Hilft dir zwar nicht bei deinem Problem:

>t2_handler:
>  CLI                --> Unnötig
>  PUSH  tmpwork
>  IN    tmpwork, PORTA  ; complement Pins on PortA
>  COM    tmpwork
>  OUT    PORTA, tmpwork
>  COM    tmpwork     --> Sinnlos
>  POP    tmpwork
>  RETI

MfG Spess

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß das der Code kein UART benutzt - ich habe es ja alles 
rausgehauen. Deswegen war meine Vermutung das da irgendwelche Register 
oder weiß der Geier was zusammen genutzt werden.

das ich CLI und den zweiten CMP nich brauche is klar - nur wenn so 
seltsame Fehler auftreten dann versucht man alles...

Achso nochwas wenn ich den RXC Pin auf out stelle hat sich das Problem - 
nur bringt mich das ja nicht weiter weil ich den UART ja eigentlich 
benutzen will.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Deswegen war meine Vermutung das da irgendwelche Register
>oder weiß der Geier was zusammen genutzt werden.

Mit diesem 'temp...'-Gedödel kann das eh niemand sagen. Ausserdem, wobei 
das auch nicht die Ursache sein kann, solltest du dir angewöhnen in der 
Interruptroutine SREG zu sichern.

>Achso nochwas wenn ich den RXC Pin auf out stelle hat sich das Problem -
>nur bringt mich das ja nicht weiter weil ich den UART ja eigentlich
>benutzen will.

Das das obige Programm durch einen RXD als Eingang gestört wird, halte 
ich für unwahrscheinlich.

MfG Spess

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nutzen Uart und der Timer irgendwas gemeinsam wovon ich nichts weiß...
Die Versorgungsspannung und den uC.
Zeig doch mal den Schaltplan...

Autor: Öpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Friedrich

Es grundsätzlich eine gute Idee genau den Code zu posten, der das 
Problem zeigt. Es sei denn Du willst uns sagen, das unabhängig davon, ob 
der UART-Code enthalten ist oder nicht, die PWM sich verändert sobald 
Zeichen an RX ankommen, was ich aber nicht vermute.

Jedenfalls kannst Du Dir so die leicht säuerliche Reaktion erklären.

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich wollte hier niemanden verärgern oder vor den Kopf stoßen. 
Schuldigung wenn ich es doch getan habe.
 Es sei denn Du willst uns sagen, das unabhängig davon, ob
der UART-Code enthalten ist oder nicht, die PWM sich verändert sobald
Zeichen an RX ankommen, was ich aber nicht vermute.

Doch genau das will ich sagen - der Code oben ist genau der (nichts dazu 
oder so) den ich auf dem chip habe. Und wenn ich am UART terror mache 
dann schwankt das PWM Signal.

Deswegen ist die Frage nach dem Schaltplan wohl sehr berechtigt. 
Solangsam glaube ich auch das ich mich da irgendwo verbaut habe.
Bevor ich anfange die Schaltung auseinander zu nehmen wollte ich halt 
vorallem sicher gehen das ich keinen Blödfehler in der Programmierung 
habe.
Ich werde mich gleich mal ran machen ne Schaltplan zu machen und euch zu 
zeigen.

SREG sichern werd ich machen - danke

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Doch genau das will ich sagen - der Code oben ist genau der (nichts dazu
>oder so) den ich auf dem chip habe. Und wenn ich am UART terror mache
>dann schwankt das PWM Signal.

Sicher? Ich habe auch schon mal einen halben Tag vergeudet, nur weil das 
falsche File im Programmer stand.

MfG Spess

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Allgemeiner Tip zum Ansteuern mehrerer Servos:
http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html
Schmeiß das Tasten- und ADC-Geraffel raus und verwalte die Positionen in 
einem Array. Dies kannst Du dann per UART-Polling in der Mainloop mit 
neuen Daten befüllen.

...

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Link ich werd ihn mir am WE mal zu gemüte führen.

Habe mittlerweile rausgefunden das der terror am UART den Effekt (PWM 
Signal spinnt) nur verstärkt. Er aber auch auftritt wenn man am UART 
nichts macht, nur dann eben deutlich seltener.

Zeichnung muss wohl bis nach dem WE warten, da ich jetzt wahrscheinlich 
mehr Fehler zeichnen würde als drin sind.

Danke euch schonmal - ich werd auf jeden Fall berichten wenn ich neue 
weiß.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code-Ausschnitt oben ist fürn Popo...
Poste einen mit sämtlichen Fehlern und lass die Kritik über dich 
ergehen.
So wird das nur wieder ein Kristallkugelbefragen...

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde vermuten das die Stromversorgung nicht das gelbe vom Ei ist... 
Abblockkondesatoren dran?

Autor: Ulf Rolf (roolf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
spess53 schrieb:
> Hi
>
> Hilft dir zwar nicht bei deinem Problem:
>
>>t2_handler:
>>  CLI                --> Unnötig
>>  PUSH  tmpwork
>>  IN    tmpwork, PORTA  ; complement Pins on PortA
>>  COM    tmpwork
>>  OUT    PORTA, tmpwork
>>  COM    tmpwork     --> Sinnlos
>>  POP    tmpwork
>>  RETI

COM setzt das Carry, was das Hauptprogramm (welches wir immer noch nicht 
gesehen haben) vermutlich nicht erwartet.

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hauptprogramm ist hang

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Code-Ausschnitt oben ist fürn Popo...
Der Code ausschnitt ist kein Ausschnitt sondern der ganze Code (... 
wieso glaubt mir das keiner...). Mit genau diesem Code auf dem Atmega 
und Habe ich PWM Signale die nicht konstant sind. Diese veränderung am 
PWM passiert selten einfach so und mit 100 % Sicherheit wenn ich an den 
UART Port Signale sende

Aber vielleicht bin ich ja komplett auf der falschen fährte - deswegen 
hier der ursprüngliche Code (also der der die ganzen PWM Signale für die 
Servos richtig generiert etc)

@Stromversorgung: Die ist ordentlich Stabil und entpuffert. Ist eine die 
ich mir auf Lochraster gelötet habe und mit der ich schon einige Ucs am 
laufen hatte. Laut Oszi bricht die Spannung auch nicht ein oder 
ähnliches.
Ich bin natürlich nicht gegen Fehler gefeit, aber die Versorgung wäre 
eine der letzten Fehlerquellen die ich mir anschauen würde weil eben 
andere UCs mit ihr ihren Dienst tun

So hier nun wie versprochen der Ursprüngliche Code:
Auch hier der Fehler die PWM generation funktioniert, und fänngt an zu 
zicken (Bleibt teilweise für mehrere Sekunden auf high oder toggled im 
usek takt) Wenn ich am UART schnell nacheinandern Daten anlege.

Ich hatte zuerst vermutet das die UART ISR dann zuoft aufgerufen wird 
und die Timer ISR nicht zum zuge kommt aber zwischen zwei Zeichen 
müssten bei Baud 9600 mehr als 1000 Takte Zeit sein (es sei denn ich hab 
mich Gnadenlos verrechnet)

Schaltung folgt später - danke für eure Hilfe!

.include "m32def.inc"

.def tmpwork=r16
.def tmpwork2=r17
.def serialcount=r18
.def count=r23
.def mode=r24

.equ SCALE_64=(1<<CS22)
.equ SCALE_1=(1<<CS20)
.equ HIGH_TIME=0
.equ HIGH_TIME_SCALER=SCALE_64
.equ INDV_TIME=1
.equ INDV_TIME_SCALER=SCALE_1
.equ LOW_TIME=2
.equ LOW_TIME_COUNT=35
.equ LOW_TIME_SCALER=SCALE_64
.equ BAUD=103 ; 16MHz
;.equ BAUD=95 ; 14.7456MHz


.equ NUM_PWM=4
.equ BYTES=1
.equ RESERVED=NUM_PWM*BYTES
.equ LISTSTART=MAXRAM-RESERVED

.equ CID=0b00000  ; ChipID
.equ S_BITS=2
.equ S_CID=(CID << S_BITS)  ; shifted chipid for comparison
.equ SID_MASK=((1<<S_BITS)-1)  ; ServoID mask
.equ CID_MASK=~(SID_MASK)  ; chipID mask
.cseg
.org 0
rjmp rst_handler
.org T2CMPaddr
rjmp t2_handler
.org URXCaddr
rjmp rxc_handler


high_handler:  ; Handles T2CMP if mode=LOW_TIME
  LDI  mode, INDV_TIME  ; switch to next mode
  LDI  count, 255  ; reset count for next mode (+1 will be added 
@pre_end)
  IN  tmpwork, TCCR2
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
  ORI  tmpwork, INDV_TIME_SCALER
  OUT  TCCR2, tmpwork
  RJMP  pre_end

low_handler:  ; Handles T2CMP if mode=HIGH_TIME
  CPI  count, LOW_TIME_COUNT  ; waited long enough?
  BRNE  pre_end

  LDI  mode, HIGH_TIME  ; switch to next mode
  LDI  count, 255 ; reset count for next mode (+1 will be added 
@pre_end)
  IN  tmpwork, TCCR2
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
  ORI  tmpwork, HIGH_TIME_SCALER
  OUT  TCCR2, tmpwork
  LDI  tmpwork, 0xFF  ; Set entire port to high
  OUT  PORTA, tmpwork
  RJMP  pre_end


t2_handler:    ; Distributes T2CMP-IRQ if necessary and handles 
mode=INDV_TIME
  CLI    ; this ISR is not nested!
  PUSH  tmpwork2 ; save registers, we might be coming from rxc_handler
  PUSH  tmpwork
  PUSH  ZL
  PUSH  ZH
  CPI  mode, LOW_TIME  ; in LOW_TIME?
  BREQ  low_handler  ; distribute!
  CPI  mode, HIGH_TIME ; in HIGH_TIME?
  BREQ  high_handler  ; distribute!
  ; if this is reached, we're in INDV_TIME
  LDI  ZH,HIGH(LISTSTART)
  LDI  ZL,LOW(LISTSTART)
  LDI  tmpwork, 1  ; 1 will be shifted around for masking
  RJMP  loop_entry  ; don't rotate in the first round
loop:
  CLC      ; We don't want a 1 to be shifted into tha mask
  ROL  tmpwork
loop_entry:
  LD  tmpwork2, Z  ; Load pwm-config
  CP  tmpwork2,count  ; switching time?!
  BRNE  loop_bottom
switch:
  IN  tmpwork2, PORTA ; Get current configuration
  COM  tmpwork    ; Convert to mask
  AND  tmpwork2, tmpwork ; Set pwm pin to low
  OUT  PORTA, tmpwork2 ; Make it tha new configuration
  COM  tmpwork    ; Convert back
loop_bottom:
  ;ADIW  ZL,1
  INC  ZL
  CPI  tmpwork,1<<(NUM_PWM-1)
  BRNE  loop
count_check:
  INC  count
  CPI  count, 0  ; Are we done? (Overflow = 256th cycle)
  BRNE  end
  LDI  mode, LOW_TIME  ; switch to next mode
  IN  tmpwork, TCCR2  ; set prescaler for LOW_TIME
  ANDI  tmpwork, ~((1<<CS22)|(1<<CS21)|(1<<CS20))
  ORI  tmpwork, LOW_TIME_SCALER
  OUT  TCCR2, tmpwork
  LDI  tmpwork, 0x00  ; Set entire port to low
  OUT  PORTA,tmpwork
  RJMP  end
pre_end:
  INC  count
end:
  POP  ZH
  POP  ZL
  POP  tmpwork
  POP  tmpwork2
  RETI



rxc_handler:
  CLI
  PUSH  tmpwork
  CBI  UCSRA, RXC    ; ISR is here, don't nest for me!
  IN  tmpwork, UCSRB    ; And don't nest for USARTs
  ANDI  tmpwork, ~(1<<RXCIE)
  OUT  UCSRB, tmpwork
  SEI
  CPI  serialcount, 0 ; next is a ID?
  BREQ  read_id
  CPI  serialcount, 1  ; next is a position
  BREQ  write_pos
  ; If this is reached, we received a useless position
  IN  serialcount, UDR
  CLR  serialcount  ; start all over
rxc_end:
  POP  tmpwork
  RETI
read_id:
  INC  serialcount  ; this a ID, next is a position
  IN   tmpwork, UDR  ; get ID
  MOV  tmpwork2, tmpwork ; copy it for further manipulation, avoid stack
  ANDI  tmpwork,CID_MASK ; extrack ChipID
  CPI  tmpwork,S_CID  ; does it match ours?
  BREQ  use_read_id  ; use the servo id!
  ;CPI  tmpwork2,0xFF  ; Handshake?
  ;BREQ  handshake
  LDI  serialcount, 2  ; did not match - next position is useless to us
  ;RCALL  toggle
  RJMP  rxc_end
handshake:
  LDI  serialcount, 0 ; Reset!
  RJMP  rxc_end
use_read_id:
  ANDI  tmpwork2,SID_MASK ; extract servo id
  LDI  ZH,HIGH(LISTSTART)
  LDI  ZL,LOW(LISTSTART)
  ADD  ZL,tmpwork2  ; point to setup #servo_id
  RJMP  rxc_end
write_pos:
  IN  tmpwork, UDR  ; get position
  ST  Z, tmpwork  ; write to memory
  CLR  serialcount  ; start all over
  RJMP  rxc_end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; "Main"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rst_handler:
  CLI
  LDI  tmpwork,0xFF      ; Port A as output
  OUT  DDRA, tmpwork
  OUT  PORTA, tmpwork
  OUT  DDRB, tmpwork
  OUT  PORTB, tmpwork

  LDI  count,0
  LDI  mode,HIGH_TIME
  LDI  tmpwork, 0x00
  LDI  serialcount, 0
  OUT  UBRRH, tmpwork
  LDI  tmpwork, BAUD
  OUT  UBRRL, tmpwork
  LDI  tmpwork, (1<<RXEN)|(1<<RXCIE)
  OUT  UCSRB, tmpwork
  LDI  tmpwork, (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)
  OUT  UCSRC, tmpwork

  LDI  tmpwork,HIGH(LISTSTART-1)  ; Setting up Stack
  OUT  SPH,tmpwork
  LDI  tmpwork,LOW(LISTSTART-1)  ; Setting up Stack
  OUT  SPL,tmpwork


  LDI  ZH,HIGH(LISTSTART)
  LDI  ZL,LOW(LISTSTART)

  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Example conf, FIXME
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork,0
  STD  Z+0, tmpwork
  LDI  tmpwork,255
  STD  Z+1, tmpwork
  LDI  tmpwork,32*2
  STD  Z+2, tmpwork
  LDI  tmpwork,32*3
  STD  Z+3, tmpwork

  ;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; End Example conf
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork, (1<<WGM21)|HIGH_TIME_SCALER ; CTC mode and 64 prescaler
  OUT  TCCR2, tmpwork
  LDI  tmpwork, 125     ; every 125 steps
  OUT  OCR2, tmpwork
  LDI  tmpwork, (1<<OCIE2)
  OUT  TIMSK, tmpwork

  SEI

hang:
  IN  tmpwork, UCSRB    ; We're done, nest for Usart
  ORI  tmpwork, (1<<RXCIE)
  OUT  UCSRB, tmpwork
  SEI
  RJMP  hang

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Friedrich Wessel schrieb:

> Der Code ausschnitt ist kein Ausschnitt sondern der ganze Code (...
> wieso glaubt mir das keiner...).

Weil die Behauptung so unglaublich klingt.
Bisher gibt es keine Berichte über ein ähnliches Phänomen. Und einige 
die hier mitlesen sind schon ein paar Jährchen hier.


Hast du schon untersucht, ob dein µC nicht zufällig resettet und das was 
du als unregelmässige PWM siehst in Wirklichkeit nicht einfach nur ein 
Neustart des Programms ist?

Autor: Friedrich Wessel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja es ist sehr strange - deswegen baue ich ja auf die Erfahrung der 
Leute hier weil ich seit 3 Wochen an dem Ding sitze und keine Ahnung 
mehr habe wo der Fehler liegen kann.
Alles was ich tun kann sind meine Beobachtungen und Schlüsse hier zu 
Posten.
Wie gesagt es kann gut sein das ich komplett dem falschen Fehler 
hinterherlaufe und die Sache mit dem UART gar nicht das eigentliche 
Problem ist (was ich btw. selber nicht glaube)
Wenn jemand ne Idee hat - immer her damit. Bin mittlerweile an dem Punkt 
wo ich mit der Rassel im Kreis springe wenn jemand meint das könnte 
helfen.


Ja Reset hab ich mit Pin abfrage und Oszi getestet - tut er nicht.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm... also Reset hätte ich jezt vieleicht auch vermutet.
Schonmal ein Erase gemacht? Trennst du die Stromversorgung nach der 
neuprogrammierung?
Ich hatte mal das Problem das nach einem Reset irgenwelche Funktionen 
(UART/Watchdog...) noch aktiv waren da ich sie im (neuen) Code nicht 
explizit abgeschaltet hatte.

Ansosnten prüf mal ob der RX/TX Pin vieleicht falsch angeschlossen ist 
und ein Ausgang gegen einen Eingang treibt.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hang:
  IN  tmpwork, UCSRB    ; We're done, nest for Usart
  ORI  tmpwork, (1<<RXCIE)
  OUT  UCSRB, tmpwork
  SEI      <<<was soll das da?
  RJMP  hang

Autor: Ulf Rolf (roolf)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Friedrich Wessel schrieb:

> rxc_handler:
>   CLI
>   PUSH  tmpwork
>   CBI  UCSRA, RXC    ; ISR is here, don't nest for me!
>   IN  tmpwork, UCSRB    ; And don't nest for USARTs
>   ANDI  tmpwork, ~(1<<RXCIE)
>   OUT  UCSRB, tmpwork
>   SEI

...

> rxc_end:
>   POP  tmpwork
>   RETI


1. In allen Interrupt-Handlern hast Du vergessen, das SREG zu sichern

2. Du spielst wild mit SEI und CLI Befehlen herum, die teilweise für 
verschachtelte Interrupts sorgen.  Während der Abarbeitung eines 
Interrupts sind weitere Interrupts von Haus aus automatisch gesperrt, 
und es ist zunächst eine gute Idee, das einfach mal so zu lassen.

Abhilfe:

1. In jedem Handler SREG sichern und am Ende wieder herstellen.

2. Als ersten Ansatz um Licht in die Sache zu bringen würde ich dafür 
sorgen, dass im Programm genau an einer Stelle (nämlich unmittelbar von 
der Main-Loop) ein Befehl "SEI" steht.  Sämtliche anderen Vorkommen 
von "SEI" sowie alle "CLI" sind ersatzlos zu streichen.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>  LDI  ZH,HIGH(LISTSTART)
>  LDI  ZL,LOW(LISTSTART)
>  ADD  ZL,tmpwork2  ; point to setup #servo_id
>  RJMP  rxc_end
   ....

Dieser Konstrukt kann durchaus tödlich sein, da du einen eventuellen 
Übertrag für ZH nicht berücksichtigst.

MfG Spess

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

für mich sieht das ganze nach einem Hardwareproblem aus:

fehlende Abblockkondensatoren?
Anschluß der Quarz-Kondensatoren an die falsche Masseleitung?
vergessene Versorgungsspannung (Phantomspeisung über UART-Eingang) oder 
ähnliches?

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> wo ich mit der Rassel im Kreis springe wenn jemand meint das könnte
> helfen.

Spring mal mit ner Rassel im Kreis drumherum! Ich glaub, das müsste 
helfen!  G

Autor: Friedrich Wessel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

so hatte das WE über kein Internet, deswegen meld ich mich erst jetzt 
wieder.
Ich habe die Schaltung nochmal komplett neu aufgebaut. Die Max232 
Schaltung sieht jetzt aus wie in diesem Tutorial:
[[http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART]]
nur halt noch VCC und GND an 15 und 16 gelegt.

Die Spannungsversorgung hab ich mittlerweile mit nem fetten 4700 uF 
Kondi abgeblockt (hab aber auch schon normal 10 und 100 reingebaut 
gehabt)

Ich hab leider nicht viel Ahnung mit digitaler Schaltplan erstellung 
aber ich hab für Atmega Beschaltung mal mein bestes Versucht (Siehe 
Anhang)

Ich hoffe man kann habwegs erkennen was gemeint ist.

Die Kondis des Qaurzes liegen auf dem normalen GND der schaltung.
Versorgungsspannung liegt an und ist nochmal mit nem 1uF Kondi gepuffert

Die eigentliche Spannungsversorgung ist auf Lochraster und der Plan 
lässt sich grad nur schwer auseinander puzzeln, deswegen dazu jetzt grad 
keine Schaltung.

Beim Code habe ich eure Vorschläge eingebaut und erstmal die Interrupts 
aufgeräumt, dann SREG gesichtert, und sicherheitshalber auch die Zeile

ADD ZL, tmpwork2 ersetzt durch den richtigen 16 bit Befehl. Hatte es aus 
Geschwindigkeitsgründen rausgenommen da ich bei 4 eingestellten Servos 
mit jeweils einem Byte eigentlich kein Problem bekommen sollte.

Das Problem bleibt das alte:
der Servo stellt sich in die richtige Position und das Oszi zeigt an 
PORTB Pin1 auch das richtige Signal an. Wenn ich dann Daten per UART 
sende, sieht das nen kurzen Moment ganz gut aus, Signal am Oszi 
verändetr sich wie gesendet, und der Serv dreht. Nach ein einer Weil 
fängt der Servo an zu zucken und das Signal am Pin flackert, und ist 
größtenteils auf High mit winzigen unterbrechungen ca 10 us

Hie nochmal der Aktualisierte Code:
.include "m32def.inc"

.def tmpwork=r16
.def tmpwork2=r17
.def serialcount=r18
.def count=r23
.def mode=r24

.equ SCALE_64=(1<<CS22)
.equ SCALE_1=(1<<CS20)
.equ HIGH_TIME=0
.equ HIGH_TIME_SCALER=SCALE_64
.equ INDV_TIME=1  
.equ INDV_TIME_SCALER=SCALE_1
.equ LOW_TIME=2
.equ LOW_TIME_COUNT=35 
.equ LOW_TIME_SCALER=SCALE_64
.equ BAUD=103 ; 16MHz
;.equ BAUD=95 ; 14.7456MHz


.equ NUM_PWM=4
.equ BYTES=1
.equ RESERVED=NUM_PWM*BYTES 
.equ LISTSTART=MAXRAM-RESERVED

.equ CID=0b00000  ; ChipID
.equ S_BITS=2
.equ S_CID=(CID << S_BITS)  ; shifted chipid for comparison
.equ SID_MASK=((1<<S_BITS)-1)  ; ServoID mask
.equ CID_MASK=~(SID_MASK)  ; chipID mask
.cseg
.org 0
rjmp rst_handler
.org T2CMPaddr
rjmp t2_handler
.org URXCaddr
rjmp rxc_handler


t2_handler:              ; Distributes T2CMP-IRQ if necessary and handles mode=INDV_TIME
  PUSH  tmpwork2         ; save registers, we might be coming from rxc_handler
  PUSH  tmpwork  
  PUSH  ZL
  PUSH  ZH
  IN    tmpwork, SREG
  PUSH  tmpwork

  CPI    mode, LOW_TIME      ; in LOW_TIME?
  BREQ  low_handler        ; distribute!
  CPI    mode, HIGH_TIME     ; in HIGH_TIME?
  BREQ  high_handler      ; distribute!
  
  ; if this is reached, we're in INDV_TIME
  LDI    ZH,HIGH(LISTSTART)
  LDI    ZL,LOW(LISTSTART)
  LDI    tmpwork, 1        ; 1 will be shifted around for masking
  RJMP  loop_entry        ; don't rotate in the first round


high_handler:            ; Handles T2CMP if mode=LOW_TIME
  LDI    mode, INDV_TIME      ; switch to next mode
  LDI    count, 255        ; reset count for next mode (+1 will be added @pre_end)
  IN    tmpwork, TCCR2
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
  ORI    tmpwork, INDV_TIME_SCALER
  OUT    TCCR2, tmpwork
  RJMP  pre_end

low_handler:            ; Handles T2CMP if mode=HIGH_TIME
  CPI    count, LOW_TIME_COUNT  ; waited long enough?
  BRNE  pre_end

  LDI    mode, HIGH_TIME      ; switch to next mode
  LDI    count, 255         ; reset count for next mode (+1 will be added @pre_end)
  IN    tmpwork, TCCR2
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
  ORI    tmpwork, HIGH_TIME_SCALER
  OUT    TCCR2, tmpwork
  LDI    tmpwork, 0xFF      ; Set entire port to high
  OUT    PORTA, tmpwork
  RJMP  pre_end



loop:
  CLC                ; We don't want a 1 to be shifted into tha mask
  ROL    tmpwork  
loop_entry:    
  LD    tmpwork2, Z        ; Load pwm-config
  CP    tmpwork2,count      ; switching time?!
  BRNE  loop_bottom  
switch:
  IN    tmpwork2, PORTA     ; Get current configuration
  COM    tmpwork          ; Convert to mask
  AND    tmpwork2, tmpwork     ; Set pwm pin to low
  OUT    PORTA, tmpwork2     ; Make it tha new configuration
  COM    tmpwork          ; use again as counter for servo
loop_bottom:
  INC    ZL
  CPI    tmpwork,1<<(NUM_PWM-1)
  BRNE  loop

count_check:
  INC    count
  CPI    count, 0        ; Are we done? (Overflow = 256th cycle)
  BRNE  end
  LDI    mode, LOW_TIME      ; switch to next mode
  IN    tmpwork, TCCR2      ; set prescaler for LOW_TIME
  ANDI  tmpwork, ~((1<<CS22)|(1<<CS21)|(1<<CS20))
  ORI    tmpwork, LOW_TIME_SCALER
  OUT    TCCR2, tmpwork
  LDI    tmpwork, 0x00      ; Set entire port to low
  OUT    PORTA,tmpwork
  RJMP  end

pre_end:
  INC  count
end:
  
  POP    tmpwork
  OUT    SREG,tmpwork
  POP    ZH
  POP    ZL
  POP    tmpwork
  POP    tmpwork2
  
  RETI

  

rxc_handler:
  PUSH  tmpwork  
  IN    tmpwork, SREG
  PUSH  tmpwork

  CPI    serialcount, 0       ; next is a ID?
  BREQ  read_id
  CPI    serialcount, 1      ; next is a position
  BREQ  write_pos

  ; If this is reached, we received a useless position
  IN    serialcount, UDR
  CLR    serialcount          ; start all over

rxc_end:
  POP    tmpwork
  OUT    SREG,tmpwork
  POP    tmpwork
  RETI

read_id:
  INC    serialcount        ; this a ID, next is a position
  IN     tmpwork, UDR      ; get ID
  MOV    tmpwork2, tmpwork     ; copy it for further manipulation, avoid stack
  ANDI  tmpwork,CID_MASK     ; extrack ChipID
  CPI    tmpwork,S_CID      ; does it match ours?
  BREQ  use_read_id        ; use the servo id!
  LDI    serialcount, 2      ; did not match - next position is useless to us
  RJMP  rxc_end

handshake:
  LDI  serialcount, 0         ; Reset!
  RJMP  rxc_end

use_read_id:
  ANDI  tmpwork2,SID_MASK     ; extract servo id
  LDI    ZH,HIGH(LISTSTART)
  LDI    ZL,LOW(LISTSTART)
  ADD    ZL,tmpwork2        ; point to setup #servo_id
  RJMP  rxc_end

write_pos:
  IN    tmpwork, UDR      ; get position
  ST    Z, tmpwork        ; write to memory
  CLR    serialcount        ; start all over
  RJMP  rxc_end


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; "Main"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rst_handler:
  CLI
  
  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; PORT Conf
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork,0xFF      ; Port A as output
  OUT  DDRA, tmpwork
  OUT  PORTA, tmpwork
  OUT  DDRB, tmpwork
  OUT  PORTB, tmpwork

  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Setup UART
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  count,0
  LDI  mode,HIGH_TIME
  LDI  tmpwork, 0x00
  LDI  serialcount, 0
  OUT  UBRRH, tmpwork
  LDI  tmpwork, BAUD
  OUT  UBRRL, tmpwork
  LDI  tmpwork, (1<<RXEN)|(1<<RXCIE)
  OUT  UCSRB, tmpwork
  LDI  tmpwork, (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)
  OUT  UCSRC, tmpwork

  
  ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Setup Memory and Stack
  ;;;;;;;;;;;;;;;;;;;;;;;;


  LDI  tmpwork,HIGH(LISTSTART-1)  ; Setting up Stack  
  OUT  SPH,tmpwork
  LDI  tmpwork,LOW(LISTSTART-1)  ; Setting up Stack  
  OUT  SPL,tmpwork


  LDI  ZH,HIGH(LISTSTART)
  LDI  ZL,LOW(LISTSTART)



;
  ;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Setup Timer
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork, (1<<WGM21)|HIGH_TIME_SCALER ; CTC mode and 64 prescaler
  OUT  TCCR2, tmpwork
  LDI  tmpwork, 125     ; every 125 steps
  OUT  OCR2, tmpwork
  LDI  tmpwork, (1<<OCIE2)
  OUT  TIMSK, tmpwork

    ;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Example conf
  ;;;;;;;;;;;;;;;;;;;;;;;;

  LDI  tmpwork,255
  STD  Z+0, tmpwork
  LDI  tmpwork,255
  STD  Z+1, tmpwork
  LDI  tmpwork,32*2
  STD  Z+2, tmpwork
  LDI  tmpwork,32*3
  STD  Z+3, tmpwork


  
hang:
  SEI
  RJMP  hang



Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.