Forum: Mikrocontroller und Digitale Elektronik UART läuft auf ATMEGA 32 aber nicht auf 328


von Daniel H. (danyag)


Angehängte Dateien:

Lesenswert?

Hey,
ich habe ein Problem mit dem UART. Ich nutze die library von Peter 
Fleury. Egal was ich am Programmcode ändere, sobald uart_puts oder 
uart_putc aufgerufen wird, passiert gar nichts mehr und der AVR scheint 
festzuhängen. Der Code ist sicher alles andere als perfekt, aber einen 
Fehler finde ich nicht. Solange keine UART-Ausgabe erfolgen soll, 
funktioniert alles wie gewünscht. Auf einem ATMEGA 32 bekomme ich das 
Programm (bezüglich der Register leicht angepasst) zum Laufen.

Mit dem ATMEGA 328 passt irgendwas nichts. Sobald die UART-Ausgabe 
erfolgen soll, passiert gar nichts mehr. An keinem Pin findet noch eine 
Änderung statt.

Auch bei der Auskommentierung großer Teile des Codes und/oder einer 
direkten string Ausgabe wie "uart_puts("Hallo Welt")" passiert nichts.

Ich habe zwei ATMEGA 328 und einen 168 getestet. Es funktioniert nur mit 
dem ATMEGA 32. Es wäre toll wenn jemand eine Idee bzw. einen Tipp für 
mich hätte.


Viele Grüße
Daniel

von public (Gast)


Lesenswert?

Dir ist bewusst das ATMega32 und ATMega328 nicht codecompatibel sind?

Beispiel:
ATMega32  --> USART Control and Status Register A – UCSRA
ATMega328 --> UCSRnA – USART Control and Status Register n A

Die Funktionsweise könnte gleich sein, die Namen sind aber definitiv 
anders.

beste grüße

von Peter D. (peda)


Lesenswert?

Daniel H. schrieb:
> Egal was ich am Programmcode ändere, sobald uart_puts oder
> uart_putc aufgerufen wird, passiert gar nichts mehr

Dann nimm doch erstmal alles andere raus.

Und wir suchen auch nicht raus, wo man eine Fleury-Lib findet und 
wieviel Versionen es davon gibt.

von Daniel H. (danyag)


Lesenswert?

Moin,

public schrieb:
> Dir ist bewusst das ATMega32 und ATMega328 nicht codecompatibel sind?

beide AVRs sind eigentlich entsprechend in der library definiert. Auf 
einem weiteren ATMega328 befindet sich ein sehr ähnliches Programm, bei 
dem die Ausgabe über UART problemlos funktioniert. Ich kann mir das 
wirklich nicht erklären.

Peter D. schrieb:
> Und wir suchen auch nicht raus, wo man eine Fleury-Lib findet und
> wieviel Versionen es davon gibt.

sry, irgendwie habe ich so oft von der lib gelesen, dass ich wohl dachte 
die sei quasi allgemein bekannt. Könnte ich nach etwas bestimmten 
suchen, das vielleicht fehlt oder falsch definiert wurde?

Peter D. schrieb:
> Dann nimm doch erstmal alles andere raus.

Daniel H. schrieb:
> Auch bei der Auskommentierung großer Teile des Codes und/oder einer
> direkten string Ausgabe wie "uart_puts("Hallo Welt")" passiert nichts.

Ich habe das Programm sowohl stückweise auskommentiert, als auch den 
Code auf das nötigste beschränkt. Der Tx-Pin bleibt dauerhaft auf "high" 
und der AVR macht gar nichts mehr, sobald eine Ausgabe erfolgen sollte.


Viele Grüße
Daniel

von Peter D. (peda)


Lesenswert?

Daniel H. schrieb:
> sry, irgendwie habe ich so oft von der lib gelesen, dass ich wohl dachte
> die sei quasi allgemein bekannt.

Nö.

Daniel H. schrieb:
>> direkten string Ausgabe wie "uart_puts("Hallo Welt")" passiert nichts.

Und warum postest Du es dann nicht so?

von Eric B. (beric)


Lesenswert?

Da steckt viel zu viel Zeug und Kram in deiner ISR. Nimm all diese 
Textbearbeitung raus, und tue das in der main().
Und Delays haben in einer ISR NIX verloren!!

von J.-u. G. (juwe)


Lesenswert?

Eric B. schrieb:
> Da steckt viel zu viel Zeug und Kram in deiner ISR. Nimm all diese
> Textbearbeitung raus, und tue das in der main().
> Und Delays haben in einer ISR NIX verloren!!

Abgesehen davon, sehe ich in dem gezeigten Code weder eine Freigabe des 
INT0 noch eine globale Interruptfreigabe.

Edit: Ach doch, das sei() ist in der Hauptschleife.

: Bearbeitet durch User
von Jochen S. (jochen_s)


Lesenswert?

Hallo,

aber das Compilersettinh "Controller" wurde auf 328 umgestellt? Oder 
versuchst du das selbe HEX auf einem anderen Controller laufen zu 
lassen??

Gruß
Jochen

von M. K. (sylaina)


Lesenswert?

Daniel H. schrieb:
> beide AVRs sind eigentlich entsprechend in der library definiert. Auf
> einem weiteren ATMega328 befindet sich ein sehr ähnliches Programm, bei
> dem die Ausgabe über UART problemlos funktioniert. Ich kann mir das
> wirklich nicht erklären.

Und du bist dir sicher, dass es kein Hardwarefehler ist? Was sagt denn 
der Compiler zum Code? Immer dran denken: Es gibt keinen Grund Warnings 
zu ignorieren. Ich gehe also davon mal aus, dass der Compiler weder 
moppert noch meckert.

von Daniel H. (danyag)


Lesenswert?

Peter D. schrieb:
> Daniel H. schrieb:
>>> direkten string Ausgabe wie "uart_puts("Hallo Welt")" passiert nichts.
>
> Und warum postest Du es dann nicht so?

das habe ich doch so gepostet :/

Eric B. schrieb:
> Da steckt viel zu viel Zeug und Kram in deiner ISR. Nimm all diese
> Textbearbeitung raus, und tue das in der main().
> Und Delays haben in einer ISR NIX verloren!!

ist das nur sehr unschön oder eine definitive Fehlerquelle?

J.-u. G. schrieb:
> Abgesehen davon, sehe ich in dem gezeigten Code weder eine Freigabe des
> INT0 noch eine globale Interruptfreigabe.

Die Freigabe von INT0 erfolgt in der "wl_module.c", so wie es in der 
main.c auskommentiert angegeben ist. Der Interrupt funktioniert auch 
einwandfrei. Daten Werden empfangen, Daten der Sensoren werden 
ausgelesen  und anschließend werden diese korrekt auf dem LCD 
ausgegeben. Lediglich uart_puts wird nicht korrekt ausgeführt.

Jochen S. schrieb:
> aber das Compilersettinh "Controller" wurde auf 328 umgestellt? Oder
> versuchst du das selbe HEX auf einem anderen Controller laufen zu
> lassen??

Der Controller wurde umgestellt. Ich habe auch verschiedene 
Taktfrequenzen und Baudraten getestet.

Michael K. schrieb:
> Und du bist dir sicher, dass es kein Hardwarefehler ist?

Ich habe 2 ATMega328 und 1 ATMega168 überprüft und mit allen besteht das 
gleiche Problem. Das andere Programm, das sehr ähnlich ist, erzeugt eine 
funktionierende UART-Ausgabe an jedem der genannten Controller.

Michael K. schrieb:
> Ich gehe also davon mal aus, dass der Compiler weder
> moppert noch meckert.

Da sind leider schon ein paar Warnungen, die ich bisher nicht "lösen" 
konnte, aber keine hat einen direkten Bezug zu UART.

von Peter D. (peda)


Lesenswert?

Daniel H. schrieb:
> Peter D. schrieb:
>> Daniel H. schrieb:
>>>> direkten string Ausgabe wie "uart_puts("Hallo Welt")" passiert nichts.
>>
>> Und warum postest Du es dann nicht so?
>
> das habe ich doch so gepostet :/

Nö.
Da ist von INT0, ADC, LCD usw. allerhand Krams drinne, nur kein 
"uart_puts("Hallo Welt")".

Die Chance ist also sehr groß, daß es garnicht am immer noch unbekannten 
Fleury-UART liegt.
Ein bischen mußt Du Dir schon Mühe geben und auch selber etwas tun.


Ich würd mal vermuten, in dem ganzen String-Bastel-Kauderwelsch ist der 
Wurm drin. Warum nimmst Du nicht einfach sprintf, der 328 hat doch genug 
Flash.
Es ist auch keine gute Idee, den String asynchron zur Ausgabe zu 
basteln. Da kann gut ein Mischmasch aus alter+neuer String entstehen.

: Bearbeitet durch User
von Matthias P. (matthias_p65)


Lesenswert?

Ist das Absicht, daß du in der while-Schleife immer wieder mit sei() die 
Interrupts einschaltest?

Stings in einer ISR zusammenzubasteln ist tatsächlich keine gute Idee.

Ich benutze hier übrigens auch die Fleury-Lib auf einem 328p, 
funktioniert tadellos.

von Eric B. (beric)


Lesenswert?

Daniel H. schrieb:
> Eric B. schrieb:
>> Da steckt viel zu viel Zeug und Kram in deiner ISR. Nimm all diese
>> Textbearbeitung raus, und tue das in der main().
>> Und Delays haben in einer ISR NIX verloren!!
>
> ist das nur sehr unschön oder eine definitive Fehlerquelle?

Ob es eine definitive ist kann ich nicht sagen. Es ist aber eine 
potenzielle, da unter Umständen deine Daten in der ISR geändert werden 
während sie gleichzeitig von puts auf der serielle Schnittstelle 
ausgegeben werden.

von Sajuuk (Gast)


Lesenswert?


von Daniel H. (danyag)


Lesenswert?

Peter D. schrieb:
> Die Chance ist also sehr groß, daß es garnicht am immer noch unbekannten
> Fleury-UART liegt.
> Ein bischen mußt Du Dir schon Mühe geben und auch selber etwas tun.

Ich bemühe mich so sehr ich kann. Es tut mir leid wenn ich den Eindruck 
geweckt haben sollte, dass ich selbst keine Lust hätte dem Problem auf 
die Spur zu kommen.

Peter D. schrieb:
> Ich würd mal vermuten, in dem ganzen String-Bastel-Kauderwelsch ist der
> Wurm drin. Warum nimmst Du nicht einfach sprintf, der 328 hat doch genug
> Flash.
> Es ist auch keine gute Idee, den String asynchron zur Ausgabe zu
> basteln.

Ok, werde mal schauen dass ich das überarbeite. Die Ausgabe auf dem LCD 
scheint aber einwandfrei.

Matthias P. schrieb:
> Ist das Absicht, daß du in der while-Schleife immer wieder mit sei() die
> Interrupts einschaltest?

Ne, das war ein Versehen -danke.

Eric B. schrieb:
> Es ist aber eine
> potenzielle, da unter Umständen deine Daten in der ISR geändert werden
> während sie gleichzeitig von puts auf der serielle Schnittstelle
> ausgegeben werden.

Könnte ich das nicht einfach durch eine Art "Buffer-String" in der 
while-Schleife lösen?

Sajuuk schrieb:
> Kannst du Ausschließen das während deinem uart_puts aufruf ein interrupt
> auftritt? Das kann durchaus problematisch sein.

Den Pegel des Interrupt-Pin beobachte ich auf dem Oszilloskop. Der 
Interrupt folgt periodisch mehrmals pro Minute und dauert etwa 376µs an. 
So lange liegt also ein Low-Pegel an. Ich habe keine Vorkehrungen 
getroffen den Zustand auszuschließen, aber wenn sollte das äußerst 
selten passieren?!


Ich werde mal die ISR bis auf den Empfang säubern und die 
"String-Bearbeitung" ganz rausnehmen. Mich beschleicht aber irgendwie 
das Gefühl es könne mit der Portkonfiguration zusammenhängen.
Hier mal die momentane Beschaltung des AVR:

Pin 1  (PC6): Reset an ISP
Pin 2  (PD0): -
Pin 3  (PD1): UART Tx
Pin 4  (PD2): Int0 an IRQ (NRF24L01)
Pin 5  (PD3): -
Pin 6  (PD4): an LCD Data0
Pin 7  (Vcc): Versorgungsspannung
Pin 8  (GND): Masse
Pin 9  (PB6): an DHT22 Signal
Pin 10 (PB7): Eingang der UART-Ausgabe aktivieren soll
Pin 11 (PD5): an LCD Data1
Pin 12 (PD6): an LCD Data2
Pin 13 (PD7): an LCD Data3
Pin 14 (PB0): an CE (NRF24L01)
Pin 15 (PB1): an CSN (NRF24L01)
Pin 16 (PB2): SS an Vcc
Pin 17 (PB3): MOSI an ISP und NRF24L01
Pin 18 (PB4): MISO an ISP und NRF24L01
Pin 19 (PB5): SCK an ISP und NRF24L01
Pin 20 (AVCC): -
Pin 21 (AREF): -
Pin 22 (GND): -
Pin 23 (PC0): ADC0 an LDR
Pin 24 (PC1): an LCD RS
Pin 25 (PC2): an LCD RW
Pin 26 (PC3): an LCD E
Pin 27 (PC4): SDA an bmp085 Sensor
Pin 28 (PC5): SCL an bmp085 Sensor

von Eric B. (beric)


Lesenswert?

Anregung: lass deine Mainschleife in festen ms ticks laufen 
(mit_delay_ms()) und zähle für die verschiedene Unterfunktion die ticks 
mit. So kannst du relativ einfach von einander unabhängige Aufgaben 
parallellisieren ohne alles zu blockieren:
1
ISR(INT0_vect)
2
{
3
  ...
4
  int0_occured = 1;
5
}
6
7
8
void main()
9
{
10
  // init everything
11
   
12
  // main loop
13
  for(;;)
14
  {
15
    // Interrupt handling
16
    if(int0_occured)
17
    {
18
        handle_int0();
19
        int0_occured = 0;
20
    }
21
22
    // TASK 1 -- e.g. UART output
23
    task1_counter --;
24
    if(!task1_counter)
25
    {
26
       do_task1();
27
       task1_counter = 100; // every 500ms
28
    }
29
30
    // TASK 2 -- e.g. LCD output
31
    task2_counter --;
32
    if(!task2_counter)
33
    {
34
       do_task2();
35
       task1_counter = 50;  // every 250ms
36
    }
37
38
    // etc etc etc
39
40
    // now block for a minimum amount of time
41
    _delay_ms(5); // 5ms tick
42
  }
43
}
Ganz striktes Timing kriegt man so natürlich nicht hin, aber es macht 
alles schon "fliessender" als mit den blockierenden delays.

: Bearbeitet durch User
von Daniel H. (danyag)


Angehängte Dateien:

Lesenswert?

Eric B. schrieb:
> So kannst du relativ einfach von einander unabhängige Aufgaben
> parallellisieren ohne alles zu blockieren:

Ah, vielen Dank - sowas ist immer ungemein hilfreich! Ich bin mit 
solchen Konzepten leider nicht so vertraut und habe mich auch noch nicht 
groß um derlei Optimierungsmöglichkeiten gekümmert. Es wird aber 
offenbar Zeit ;)


Bezüglich des UART Problems bin ich nicht unbedingt weitergekommen, aber 
habe ein paar Sachen versucht, die mehr oder weniger aufschlussreich 
waren.
Ich habe schrittweise Teile des Codes entfernt, bis nur noch die 
UART-Ausgabe selbst vorhanden war. Um wenigstens in etwa abschätzen zu 
können was passiert, wird noch ein Pin (PB7) ein- und ausgeschaltet.

Der Tx-Pin bleibt noch immer dauerhaft auf "High", aber die Zahl der 
Programmwiederholungen hängt von der Stringlänge ab, die uart_puts() 
übergeben wird.
Länge:  0 -> inf. Pulse
Länge:  1 -> 32 Pulse am Pin
Länge:  2 -> 16 Pulse
Länge:  4 ->  8 Pulse
Länge: 32 ->  1 Puls

..danach passiert gar nichts mehr, bis ich einen Reset auslöse oder die 
Spannungsversorgung aus- und wieder einschalte.

Wo der Fehler genau liegt weiß ich leider noch immer nicht.

von M. K. (sylaina)


Lesenswert?

Daniel H. schrieb:
> Da sind leider schon ein paar Warnungen, die ich bisher nicht "lösen"
> konnte, aber keine hat einen direkten Bezug zu UART.

Die solltest du auf jeden Fall IMO behandeln. Es gibt wenige Ausnahmen, 
bei denen man ein Warning ignorieren kann (Klassiker: discards 
'volatile' qualifier …) aber in der Regel sollte man sie immer beachten 
und beseitigen.

von Stefan E. (sternst)


Lesenswert?

Daniel H. schrieb:
> Wo der Fehler genau liegt weiß ich leider noch immer nicht.

Bei dem Testcode liegt der Fehler beim fehlenden sei().
Der Fleury-UART-Code arbeitet mit einem Puffer und Interrupt gesteuertem 
Senden.

von Daniel H. (danyag)


Lesenswert?

Stefan E. schrieb:
> Bei dem Testcode liegt der Fehler beim fehlenden sei().

Ich bin auch ein Esel.
Nach dem Hinzufügen von sei() ergibt sich immerhin direkt ein neues 
Fehlerbild. Direkt nach dem Programmieren läuft das Programm durch, aber 
es gibt noch immer keine UART-Ausgabe.
Nach einem Neustart passiert dann gar nichts mehr. :/

von Daniel H. (danyag)


Lesenswert?

so, ich habe was gefunden..
Da war eine Compiler-Warnung die eigentlich recht eindeutig scheint.

uart.c:243: warning: 'SIG_USART_RECV' appears to be a misspelled signal 
handler
uart.c:286: warning: 'SIG_USART_DATA' appears to be a misspelled signal 
handler

Die entsprechenden Stellen beziehen sich wohl auf:
#define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
#define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA

Laut Datenblatt des ATMega328 gibt es diese Interrupt Vektoren nicht. 
Dort habe ich folgendes gefunden:
USART Rx Complete:         USART, RX
USART Data Register Empty: USART, UDRE
USART Tx Complete:         USART, TX

Daher habe ich die oben genannten Zeilen wie folgt geändert:
#define UART0_RECEIVE_INTERRUPT   USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT  USART_UDRE_vect

Der Compiler hat nichts zu meckern und es scheint zu funktionieren. Sind 
das die richtigen Vektoren? Was hat das "SIG" zu bedeuten?

..und warum funktioniert das andere Programm inklusive UART auf dem 
gleichen AVR mit der library fehlerfrei?

von Joachim B. (jar)


Lesenswert?

Daniel H. schrieb:
> ..und warum funktioniert das andere Programm inklusive UART auf dem
> gleichen AVR mit der library fehlerfrei?

da musst du dich mal durchwühlen,

ich nutze auch gerne Fleury LIBs aber da ist noch einges veraltet

z.B.
an manchen Stellen xtalCpu, an anderen wieder F_CPU

ich habe die von hier mal angesehen:
http://homepage.hispeed.ch/peterfleury/uartlibrary.zip

die ganzen Prozzi #defines stehen auch in uart.c, sowas gehört sich ja 
in uart.h oder man macht sein eigenes, so mache ich es.

Man kann leider so schlecht Codes mixen wenn es von verschiedenen 
Autoren aus unterschiedliche Jahrzehnten stammt.

Besser man definiert neu mit ungebrächlichen oder verfemdeten #defines 
und trägt die benötigen passend ein:

z.B. so
1
#if defined(__AVR_ATmega328P__)
2
  #define   TIMSKx              TIMSK1
3
  #define   OCIExA              OCIE1A
4
  #define   TIMERx_COMPA_vect   TIMER1_COMPA_vect  // ATmega
5
  #define   TCCRxA              TCCR1A
6
  #define   COMxA0              COM1A0
7
  #define   OCRxA               OCR1A
8
  #define   TCCRxB              TCCR1B
9
  #define   WGMx2               WGM12
10
  #define   CSx0                CS10
11
12
  #define ARDUINO_LED      5
13
  #define DDR_ARDUINO_LED  DDRB
14
  #define PORT_ARDUINO_LED PORTB
15
  #define ARDUINO_LED_ON   PORT_ARDUINO_LED|=(1<<ARDUINO_LED)
16
  #define ARDUINO_LED_OFF  PORT_ARDUINO_LED&=~(1<<ARDUINO_LED)
17
18
#elif defined(__AVR_ATmega1284P__)
19
  #define   TIMSKx              TIMSK3
20
  #define   OCIExA              OCIE3A
21
  #define   TIMERx_COMPA_vect   TIMER3_COMPA_vect  // ATmega
22
  #define   TCCRxA              TCCR3A
23
  #define   COMxA0              COM3A0
24
  #define   OCRxA               OCR3A
25
  #define   TCCRxB              TCCR3B
26
  #define   WGMx2               WGM32
27
  #define   CSx0                CS30
28
29
//#elif defined(__AVR_ATmega1284P__)
30
  #define LED_ARDUINO       7
31
  #define LED_ARDUINO_PORT  PORTB
32
  #define LED_ARDUINO_DDR   DDRB
33
  #define LED_ARDUINO_ON       LED_ARDUINO_PORT  |= (1<<LED_ARDUINO)
34
  #define LED_ARDUINO_OFF      LED_ARDUINO_PORT &= ~(1<<LED_ARDUINO)
35
36
#endif

von J.-u. G. (juwe)


Lesenswert?

Daniel H. schrieb:
> Die entsprechenden Stellen beziehen sich wohl auf:
> #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
> #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA

Und genau deshalb wäre es sinnvoll ein (möglichst minimales) 
vollständiges Codebeispiel, inklusive aller verwendeten Dateien, zu 
posten, damit potentielle Helfer wissen, wovon die Rede ist. Eine 
"uartlibrary" von Fleury findet man beispielsweise hier:
http://homepage.hispeed.ch/peterfleury/avr-software.html

In dieser kommt weder ein "SIG_USART_RECV" noch ein "SIG_USART_DATA" 
vor.

> ..und warum funktioniert das andere Programm inklusive UART auf dem
> gleichen AVR mit der library fehlerfrei?

Ohne den relevanten Code zu kennen, kann das keiner sagen.

von M. K. (sylaina)


Lesenswert?

Daniel H. schrieb:
> Sind
> das die richtigen Vektoren? Was hat das "SIG" zu bedeuten?

Ja, das sind die richtigen Vektoren. Das SIG deutet aber auf relativ 
alten Code hin. Was damals SIG hieß heißt heute vect. Die Bezeichnungen 
haben sich geändert.

Du solltest auf jeden Fall mal eine aktueller Version der Lib dir 
beschaffen oder aber du schreibst dir selbst eine Lib zum UART. Das ist 
nicht schwer und braucht vielleicht eine Stunde Arbeit aber dann weißt 
du auch wie der UART funktioniert.

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.