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


von Friedrich Wessel (Gast)


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

von holger (Gast)


Lesenswert?

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

Kann nicht sein. Dein Code benutzt keinen UART.

von spess53 (Gast)


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

von Friedrich Wessel (Gast)


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.

von spess53 (Gast)


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von Öpf (Gast)


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.

von Friedrich Wessel (Gast)


Lesenswert?

Hallo,

ich wollte hier niemanden verärgern oder vor den Kopf stoßen. 
Schuldigung wenn ich es doch getan habe.
1
 Es sei denn Du willst uns sagen, das unabhängig davon, ob
2
der UART-Code enthalten ist oder nicht, die PWM sich verändert sobald
3
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

von spess53 (Gast)


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

von Hannes L. (hannes)


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.

...

von Friedrich Wessel (Gast)


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ß.

von STK500-Besitzer (Gast)


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...

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

von Ulf R. (roolf)


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.

von Friedrich Wessel (Gast)


Lesenswert?

Hauptprogramm ist hang

von Friedrich Wessel (Gast)


Lesenswert?

1
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

von Karl H. (kbuchegg)


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?

von Friedrich Wessel (Gast)


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.

von Läubi .. (laeubi) Benutzerseite


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.

von ... .. (docean) Benutzerseite


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

von Ulf R. (roolf)


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.

von spess53 (Gast)


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

von Anja (Gast)


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?

von Klaus (Gast)


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

von Friedrich Wessel (Gast)


Angehängte Dateien:

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:
1
.include "m32def.inc"
2
3
.def tmpwork=r16
4
.def tmpwork2=r17
5
.def serialcount=r18
6
.def count=r23
7
.def mode=r24
8
9
.equ SCALE_64=(1<<CS22)
10
.equ SCALE_1=(1<<CS20)
11
.equ HIGH_TIME=0
12
.equ HIGH_TIME_SCALER=SCALE_64
13
.equ INDV_TIME=1  
14
.equ INDV_TIME_SCALER=SCALE_1
15
.equ LOW_TIME=2
16
.equ LOW_TIME_COUNT=35 
17
.equ LOW_TIME_SCALER=SCALE_64
18
.equ BAUD=103 ; 16MHz
19
;.equ BAUD=95 ; 14.7456MHz
20
21
22
.equ NUM_PWM=4
23
.equ BYTES=1
24
.equ RESERVED=NUM_PWM*BYTES 
25
.equ LISTSTART=MAXRAM-RESERVED
26
27
.equ CID=0b00000  ; ChipID
28
.equ S_BITS=2
29
.equ S_CID=(CID << S_BITS)  ; shifted chipid for comparison
30
.equ SID_MASK=((1<<S_BITS)-1)  ; ServoID mask
31
.equ CID_MASK=~(SID_MASK)  ; chipID mask
32
.cseg
33
.org 0
34
rjmp rst_handler
35
.org T2CMPaddr
36
rjmp t2_handler
37
.org URXCaddr
38
rjmp rxc_handler
39
40
41
t2_handler:              ; Distributes T2CMP-IRQ if necessary and handles mode=INDV_TIME
42
  PUSH  tmpwork2         ; save registers, we might be coming from rxc_handler
43
  PUSH  tmpwork  
44
  PUSH  ZL
45
  PUSH  ZH
46
  IN    tmpwork, SREG
47
  PUSH  tmpwork
48
49
  CPI    mode, LOW_TIME      ; in LOW_TIME?
50
  BREQ  low_handler        ; distribute!
51
  CPI    mode, HIGH_TIME     ; in HIGH_TIME?
52
  BREQ  high_handler      ; distribute!
53
  
54
  ; if this is reached, we're in INDV_TIME
55
  LDI    ZH,HIGH(LISTSTART)
56
  LDI    ZL,LOW(LISTSTART)
57
  LDI    tmpwork, 1        ; 1 will be shifted around for masking
58
  RJMP  loop_entry        ; don't rotate in the first round
59
60
61
high_handler:            ; Handles T2CMP if mode=LOW_TIME
62
  LDI    mode, INDV_TIME      ; switch to next mode
63
  LDI    count, 255        ; reset count for next mode (+1 will be added @pre_end)
64
  IN    tmpwork, TCCR2
65
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
66
  ORI    tmpwork, INDV_TIME_SCALER
67
  OUT    TCCR2, tmpwork
68
  RJMP  pre_end
69
70
low_handler:            ; Handles T2CMP if mode=HIGH_TIME
71
  CPI    count, LOW_TIME_COUNT  ; waited long enough?
72
  BRNE  pre_end
73
74
  LDI    mode, HIGH_TIME      ; switch to next mode
75
  LDI    count, 255         ; reset count for next mode (+1 will be added @pre_end)
76
  IN    tmpwork, TCCR2
77
  ANDI  tmpwork,~((1<<CS20)|(1<<CS21)|(1<<CS22))
78
  ORI    tmpwork, HIGH_TIME_SCALER
79
  OUT    TCCR2, tmpwork
80
  LDI    tmpwork, 0xFF      ; Set entire port to high
81
  OUT    PORTA, tmpwork
82
  RJMP  pre_end
83
84
85
86
loop:
87
  CLC                ; We don't want a 1 to be shifted into tha mask
88
  ROL    tmpwork  
89
loop_entry:    
90
  LD    tmpwork2, Z        ; Load pwm-config
91
  CP    tmpwork2,count      ; switching time?!
92
  BRNE  loop_bottom  
93
switch:
94
  IN    tmpwork2, PORTA     ; Get current configuration
95
  COM    tmpwork          ; Convert to mask
96
  AND    tmpwork2, tmpwork     ; Set pwm pin to low
97
  OUT    PORTA, tmpwork2     ; Make it tha new configuration
98
  COM    tmpwork          ; use again as counter for servo
99
loop_bottom:
100
  INC    ZL
101
  CPI    tmpwork,1<<(NUM_PWM-1)
102
  BRNE  loop
103
104
count_check:
105
  INC    count
106
  CPI    count, 0        ; Are we done? (Overflow = 256th cycle)
107
  BRNE  end
108
  LDI    mode, LOW_TIME      ; switch to next mode
109
  IN    tmpwork, TCCR2      ; set prescaler for LOW_TIME
110
  ANDI  tmpwork, ~((1<<CS22)|(1<<CS21)|(1<<CS20))
111
  ORI    tmpwork, LOW_TIME_SCALER
112
  OUT    TCCR2, tmpwork
113
  LDI    tmpwork, 0x00      ; Set entire port to low
114
  OUT    PORTA,tmpwork
115
  RJMP  end
116
117
pre_end:
118
  INC  count
119
end:
120
  
121
  POP    tmpwork
122
  OUT    SREG,tmpwork
123
  POP    ZH
124
  POP    ZL
125
  POP    tmpwork
126
  POP    tmpwork2
127
  
128
  RETI
129
130
  
131
132
rxc_handler:
133
  PUSH  tmpwork  
134
  IN    tmpwork, SREG
135
  PUSH  tmpwork
136
137
  CPI    serialcount, 0       ; next is a ID?
138
  BREQ  read_id
139
  CPI    serialcount, 1      ; next is a position
140
  BREQ  write_pos
141
142
  ; If this is reached, we received a useless position
143
  IN    serialcount, UDR
144
  CLR    serialcount          ; start all over
145
146
rxc_end:
147
  POP    tmpwork
148
  OUT    SREG,tmpwork
149
  POP    tmpwork
150
  RETI
151
152
read_id:
153
  INC    serialcount        ; this a ID, next is a position
154
  IN     tmpwork, UDR      ; get ID
155
  MOV    tmpwork2, tmpwork     ; copy it for further manipulation, avoid stack
156
  ANDI  tmpwork,CID_MASK     ; extrack ChipID
157
  CPI    tmpwork,S_CID      ; does it match ours?
158
  BREQ  use_read_id        ; use the servo id!
159
  LDI    serialcount, 2      ; did not match - next position is useless to us
160
  RJMP  rxc_end
161
162
handshake:
163
  LDI  serialcount, 0         ; Reset!
164
  RJMP  rxc_end
165
166
use_read_id:
167
  ANDI  tmpwork2,SID_MASK     ; extract servo id
168
  LDI    ZH,HIGH(LISTSTART)
169
  LDI    ZL,LOW(LISTSTART)
170
  ADD    ZL,tmpwork2        ; point to setup #servo_id
171
  RJMP  rxc_end
172
173
write_pos:
174
  IN    tmpwork, UDR      ; get position
175
  ST    Z, tmpwork        ; write to memory
176
  CLR    serialcount        ; start all over
177
  RJMP  rxc_end
178
179
180
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181
;; "Main"
182
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
183
184
rst_handler:
185
  CLI
186
  
187
  ;;;;;;;;;;;;;;;;;;;;;;;;
188
  ;; PORT Conf
189
  ;;;;;;;;;;;;;;;;;;;;;;;;
190
191
  LDI  tmpwork,0xFF      ; Port A as output
192
  OUT  DDRA, tmpwork
193
  OUT  PORTA, tmpwork
194
  OUT  DDRB, tmpwork
195
  OUT  PORTB, tmpwork
196
197
  ;;;;;;;;;;;;;;;;;;;;;;;;
198
  ;; Setup UART
199
  ;;;;;;;;;;;;;;;;;;;;;;;;
200
201
  LDI  count,0
202
  LDI  mode,HIGH_TIME
203
  LDI  tmpwork, 0x00
204
  LDI  serialcount, 0
205
  OUT  UBRRH, tmpwork
206
  LDI  tmpwork, BAUD
207
  OUT  UBRRL, tmpwork
208
  LDI  tmpwork, (1<<RXEN)|(1<<RXCIE)
209
  OUT  UCSRB, tmpwork
210
  LDI  tmpwork, (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL)
211
  OUT  UCSRC, tmpwork
212
213
  
214
  ;;;;;;;;;;;;;;;;;;;;;;;;
215
  ;; Setup Memory and Stack
216
  ;;;;;;;;;;;;;;;;;;;;;;;;
217
218
219
  LDI  tmpwork,HIGH(LISTSTART-1)  ; Setting up Stack  
220
  OUT  SPH,tmpwork
221
  LDI  tmpwork,LOW(LISTSTART-1)  ; Setting up Stack  
222
  OUT  SPL,tmpwork
223
224
225
  LDI  ZH,HIGH(LISTSTART)
226
  LDI  ZL,LOW(LISTSTART)
227
228
229
230
;
231
  ;;;;;;;;;;;;;;;;;;;;;;;;;
232
  ;; Setup Timer
233
  ;;;;;;;;;;;;;;;;;;;;;;;;
234
235
  LDI  tmpwork, (1<<WGM21)|HIGH_TIME_SCALER ; CTC mode and 64 prescaler
236
  OUT  TCCR2, tmpwork
237
  LDI  tmpwork, 125     ; every 125 steps
238
  OUT  OCR2, tmpwork
239
  LDI  tmpwork, (1<<OCIE2)
240
  OUT  TIMSK, tmpwork
241
242
    ;;;;;;;;;;;;;;;;;;;;;;;;
243
  ;; Example conf
244
  ;;;;;;;;;;;;;;;;;;;;;;;;
245
246
  LDI  tmpwork,255
247
  STD  Z+0, tmpwork
248
  LDI  tmpwork,255
249
  STD  Z+1, tmpwork
250
  LDI  tmpwork,32*2
251
  STD  Z+2, tmpwork
252
  LDI  tmpwork,32*3
253
  STD  Z+3, tmpwork
254
255
256
  
257
hang:
258
  SEI
259
  RJMP  hang

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.