Hallo Zusammen,
Habe ein Software Problem bei einem Mikrocontroller Programm:
Umgebung: AtmelStudio, JTAGICE3, C, ATmega64, 3,3V
Ich habe in meinem Code mehrere Funktionen, die sich alle durch die main
Funktion aufrufen lassen. So weit funktioniert alles.
ABER: Wenn ich in "main" eine Funktion aufrufe, und aus dieser Funktion
eine andere Funktion aufrufe, bleibt der Mikrocontroller hängen. Weiß
jemand wieso? Ist das Problem bekannt?
Funktionen deklariere ich immer folgendermaßen:
Ich weiß nicht, ob dein Code hier nur beispielhaft ist. Jedoch sendest
du, wenn du "Sende_alle_Ziffern" aufrufst, hier immer nur eine "2".
Unabhängig davon, mit welchen Argumenten "Sende_alle_Ziffern" aufgerufen
wird.
Ist nur ein stark reduzierter Beispielcode. Konnte das Problem so weit
eingrenzen, dass der Controller sich definitiv beim Aufruf der 2
Funktion verabschiedet
M. S. schrieb:> In dem Fall sind vielleicht sechs Argumente für die Funktion zu viel
Werde mal alle Unterfunktionen zu einer einzigen Zusammenfassen. Ist
zwar häßlich wegen hoher Coderedundanz, scheint mir dafür aber die
einfachste Lösung. Und ist in der Ausführung sicher auch schneller, da
weniger Sprungbefehle auftauchen.
006 schrieb:> M. S. schrieb:>> In dem Fall sind vielleicht sechs Argumente für die Funktion zu viel>> Werde mal alle Unterfunktionen zu einer einzigen Zusammenfassen.
Das wird dir nicht viel bringen.
Das Problem in deinem Programm lässt sich nicht auf 'die eine Zeile'
reduzieren. Dein Programm verbraucht, wenn die Ad Hoc Diagnose
'Stack+berlauf' zutrifft, in seiner Gesamtheit einfach zuviel SRAM. Das
müsste schon sehr an der Kippe stehen, wenn dir das bischen
Returnstack-Einsparung durch einen eingesparten Funktionsaufruf die
Sache rettet. Vor allen Dingen bringt das nur ganz kurze Abhilfe. Bei
der nächsten Änderung fliegt dir dann wieder alles um die Ohren.
Also: Speicherverbrauch feststellen und nachsehen wo man ein wenig SRAM
sparen kann.
> Ist> zwar häßlich wegen hoher Coderedundanz, scheint mir dafür aber die> einfachste Lösung.
Mit Sicherheit nicht.
Karl Heinz schrieb:> Also: Speicherverbrauch feststellen und nachsehen wo man ein wenig SRAM> sparen kann.
Eventuell Strings oder andere Daten, die sich nicht ändern, in den Flash
auslagern. Versuche selbst gerade ein Menu bzw. die Strings mit __flash
dorthin zu bekommen und wieder auszugeben. Mein SRAM ist nämlich auch
voll ;-)
Gruß Max
Hier der Quellcode. Ich habe 6 Zahlenwerte und möchte die über
Schieberegister jeweils auf zwei 7-Segmentanzeigen ausgeben (2stellig
00-99).
Weiß nicht, was da jetzt für den Speicher kritisch werden sollte... Hat
jemand eine Idee?
1
/*
2
* Main_64_v01.c
3
*
4
* Created: 11.09.2014 14:28:26
5
* Author: test1
6
*/
7
8
9
//Bibliotheken
10
#include<avr/io.h>
11
#include<stdint.h>
12
13
14
// PINOUT - Anzeigemodul
15
#define SCK 3 //PE3: Speichertakt
16
#define DATA 4 //PE4: Serielle Datenleitung
17
#define CLK 5 //PE5: Schiebetakt
18
#define OE 6 //PE6: Output Enabled
19
//Board
20
#define LED 6 //PB6: Status LED auf dem Board
21
22
23
// Funktionen Deklaration
24
25
uint8_tDez_To_7Seg(uint8_tdez)// CHECKED
26
{
27
// kodiere eine Dezimalzahl für die 7-Segment-Anzeige
28
// Input : Dezimalzahl typ uint8_t
29
// Output : Code für 7-Segment Anzeige
30
31
// Pin Zuordnung
32
// Qn: Schieberegister Ausgang Nr. n
33
// n: 7-Segment-Anzeige Balken Nr. n
34
// Q0 -> nc
35
// Q1 -> 6 -> b
36
// Q2 -> 7 -> a
37
// Q3 -> 4 -> c
38
// Q4 -> 2 -> d
39
// Q5 -> 9 -> f
40
// Q6 -> 1 -> e
41
// Q7 -> 10 -> g
42
43
switch(dez){//gefdcab-
44
case0:return0b01111110;break;
45
case1:return0b00001010;break;
46
case2:return0b11010110;break;
47
case3:return0b10011110;break;
48
case4:return0b10101101;break;
49
case5:return0b10111100;break;
50
case6:return0b11111100;break;
51
case7:return0b00001110;break;
52
case8:return0b11111110;break;
53
case9:return0b10111110;break;
54
default:return0b11110100;break;// -> E: Error
55
}
56
57
}
58
59
voidSende_Ziffer(uint8_tziffer)
60
{
61
62
if(ziffer&(1<<7)){PORTE|=(1<<DATA);}//Wenn Bit 7 = High, dann High ausgeben
63
else{PORTE&=~(1<<DATA);};//Wenn Bit 7 = Low, dann Low ausgeben
Ein Atmega64 hat 4K RAM. Das dauert schon ein wenig, bis der Stack
überläuft.
M. S. schrieb:> Ich weiß nicht, ob dein Code hier nur beispielhaft ist
Jetzt zeig mal ein richtiges Programm, das auch läuft. An dem Extrakt
oben lässt sich nur die Qualität der Optimierung erkennen.
mfg.
Da ist auch nichts kritisches (ausser dass man den Code auch um 50%
kleiner schreiben kann und so die Unübersicht los wird).
Die Funktionsaufrufe sind es jedenfalls nicht.
Was hängt da für ein Schieberegister drann? 74595? Wie ist es
verdrahtet?
Karl Heinz schrieb:> Was hängt da für ein Schieberegister drann? 74595? Wie ist es74HC595. Läßt sich problemslos ansteuern so lange ich die Befehle
sequenziell in eine funktion packe... Daher wird die Verdrahtung wohl
stimmen.
006 schrieb:> Karl Heinz schrieb:>> Was hängt da für ein Schieberegister drann? 74595? Wie ist es>> 74HC595. Läßt sich problemslos ansteuern so lange ich die Befehle> sequenziell in eine funktion packe... Daher wird die Verdrahtung wohl> stimmen.
Trotzdem ist da was anderes faul.
Hast du in der IDE den korrekten µC-Typ eingstellt?
Der Code sollte so laufen, doch schau mal in der Funktion
uint8_t Dez_To_7Seg(uint8_t dez)
nach, alle return's werden durch den switch erzeugt.
Entferne mal den default und gib das als Standard zurück.
Ich glaube aber auch das es eher die Schaltung ist, z.B
Spannungseinbruch durch Schalten eines Pins zum Kurzschluss.
Gruß, Christoph
Christoph Vogel schrieb:> Ich glaube aber auch das es eher die Schaltung ist, z.B> Spannungseinbruch durch Schalten eines Pins zum Kurzschluss.
Also habe die Funktionen jetzt zu einer mit relativ hoher Coderedundanz
zusammengeführt. Läuft fehlerfrei!
Ist halt nur häßlich...
006 schrieb:> Christoph Vogel schrieb:>> Ich glaube aber auch das es eher die Schaltung ist, z.B>> Spannungseinbruch durch Schalten eines Pins zum Kurzschluss.>> Also habe die Funktionen jetzt zu einer mit relativ hoher Coderedundanz> zusammengeführt. Läuft fehlerfrei!
Bis zum nächsten Fehler.
Dein Code ist an sich in Ordnung. Da ist irgendwas faul, was wir hier
nicht sehen können. An den Funktionsaufrufen hängt es ganz sicher nicht.
>> Ist halt nur häßlich...
Und unwartbar
Karl Heinz schrieb:> Dein Code ist an sich in Ordnung. Da ist irgendwas faul, was wir hier> nicht sehen können. An den Funktionsaufrufen hängt es ganz sicher nicht.
Hat eigentlich schon jemand den Klassiker ins Spiel gebracht?
100nF an JEDEM 595er.
006 schrieb:> Ist halt nur häßlich...
Das ist der ursprüngliche Code aber auch. Funktionieren sollte er
trotzdem.
Karl Heinz schrieb:> Bis zum nächsten Fehler.
Und der wird nicht lange auf sich warten lassen.
mfg.
Thomas Eckmann schrieb:> Karl Heinz schrieb:>> Dein Code ist an sich in Ordnung. Da ist irgendwas faul, was wir hier>> nicht sehen können. An den Funktionsaufrufen hängt es ganz sicher nicht.>> Hat eigentlich schon jemand den Klassiker ins Spiel gebracht?>
nicht das ich wüsste. Sollte man aber mal klären.
006. Teste mal diesen Code. Das ist wichtig, dass wir das jetzt ein für
alle mal hinkriegen. Du kannst nicht vernünftig weiterarbeiten, wenn
nicht klargestellt ist, was da in deinem System los ist.
Karl Heinz schrieb:>> Hat eigentlich schon jemand den Klassiker ins Spiel gebracht?>>>> nicht das ich wüsste. Sollte man aber mal klären.
Das war auch eher eine rhetorische Frage.
Ich würde mich auch zu einer Wette hinreissen lassen.
mfg.
Marc Vesely schrieb:> Kürzer ?> for( i = 0; i < 2; i++ ) {> PINB |= (1<<LED);> _delay_ms( 1000 );> }
Was nützt es Dir, in einer Schleife die LED dauernd einzuschalten? So
entsteht kein BLINKEN!
Route 66 schrieb:> Was nützt es Dir, in einer Schleife die LED dauernd einzuschalten? So> entsteht kein BLINKEN!
Warum schreist du den ?
Und bist du sicher, dass es dauernd eingeschaltet wird ?
Marc Vesely schrieb:> Route 66 schrieb:>> Was nützt es Dir, in einer Schleife die LED dauernd einzuschalten? So>> entsteht kein BLINKEN!>> Warum schreist du den ?> Und bist du sicher, dass es dauernd eingeschaltet wird ?
Auf einem Mega64 gibt es die Toggle-Funktionalität mittels PINx Register
noch nicht. Wenn schon, dann hätte man es so schreiben können.
1
for(i=0;i<4;i++){
2
PORTB^=(1<<LED);
3
_delay_ms(1000);
4
}
4 Umschaltungen mach ich deshalb, weil ich nicht weiß, wie seine LED
angebunden ist. Bei 4 mal ergibt das auf jeden Fall irgendetwas
unmissverständlich sichtbares.
Aber: in meinen Augen ist das jetzt ehrlich gesagt ein Streit um des
Kaisers Bart, ob man da eine Schleife nimmt, oder per Copy&Paste
programmiert. Man muss nicht päpstlicher als der Papst sein. Der Zweck
ist auf jeden Fall so oder so erfüllt und im fertigen Programm kommts
dann sowieso wieder raus.
Karl Heinz schrieb:> 006. Teste mal diesen Code. Das ist wichtig, dass wir das jetzt ein für> alle mal hinkriegen. Du kannst nicht vernünftig weiterarbeiten, wenn> nicht klargestellt ist, was da in deinem System los ist.
Hallo Karl Heinz,
habe deinen Code probiert.
Eine Warnung:
Warning 1 #warning "F_CPU not defined for <util/delay.h>" [-Wcpp]
c:\program files (x86)\atmel\atmel toolchain\avr8
gcc\native\3.4.1056\avr8-gnu-toolchain\avr\include\util\delay.h 90 3
GccApplication2
Programm ließ sich kompilieren und übertragen. Die 7-Segment-Anzeigen
zeigen weiterhin alte Ziffern, die noch im Latch der Schieberegister
hingen.
Die Status LED leuchtet kurz auf (t>0.2s) bleibt dann ca. 1s aus
leuchtet dann ca. 1s auf und bleibt wieder eine 1s aus. Dann wiederholt
sich das Spiel.
006 schrieb:> Die Status LED leuchtet kurz auf (t>0.2s) bleibt dann ca. 1s aus> leuchtet dann ca. 1s auf und bleibt wieder eine 1s aus. Dann wiederholt> sich das Spiel.
Wie?
Die LED blinkt immer wieder?
Dann stürzt dein Prozessor laufend ab und der Verdacht, das es sich um
ein elektrisches Problem handelt verdichtet sich. Poste mal deinen
Schaltplan oder häng gleich mal prophylaktisch 100nF Kondensatoren an
die Versorgungsspannung des Prozessors und der 595 (jeder IC kriegt
seinen eigenen Kondensator, möglichst dicht ans Gehäuse des IC)
006 schrieb:> Die Status LED leuchtet kurz auf (t>0.2s) bleibt dann ca. 1s aus> leuchtet dann ca. 1s auf und bleibt wieder eine 1s aus. Dann wiederholt> sich das Spiel.
Ich meinte <0,2s. Wirklich nur kaum wahrnehmbar
Stefan Ernst schrieb:> Auch auf die Gefahr hin, wieder ignoriert zu werden:> Wie ist der Zustand der M103C-Fuse?
Guter Einwand. Wusste gar nicht, dass der Mega64 die auch hat (so wie
der 128).
Und Atmel hat (in meinen Augen) denselben Mist gemacht, wie beim 128-er.
Default ist die Fuse 'programmed', sprich man muss erst mal an die Fuse
ran, ehe man dann tatsächlich einen M64 vor sich hat.
Karl Heinz schrieb:> Dann stürzt dein Prozessor laufend ab und der Verdacht, das es sich um> ein elektrisches Problem handelt verdichtet sich. Poste mal deinen> Schaltplan oder häng gleich mal prophylaktisch 100nF Kondensatoren an> die Versorgungsspannung des Prozessors und der 595 (jeder IC kriegt> seinen eigenen Kondensator, möglichst dicht ans Gehäuse des IC)
Ich seh grade dass ich einen Vcc Eingang des Controllers nicht mit 100nF
entstört habe. Die Spannung schwangt hier un ca. 50mV. Mal sehen ob ich
noch einen einlöten kann.
006 schrieb:> Karl Heinz schrieb:>> Dann stürzt dein Prozessor laufend ab und der Verdacht, das es sich um>> ein elektrisches Problem handelt verdichtet sich. Poste mal deinen>> Schaltplan oder häng gleich mal prophylaktisch 100nF Kondensatoren an>> die Versorgungsspannung des Prozessors und der 595 (jeder IC kriegt>> seinen eigenen Kondensator, möglichst dicht ans Gehäuse des IC)>> Ich seh grade dass ich einen Vcc Eingang des Controllers nicht mit 100nF> entstört habe. Die Spannung schwangt hier un ca. 50mV. Mal sehen ob ich> noch einen einlöten kann.
Hast du dich um die Fuse gekümmert? Die Abblockkondensatoren sind
natürlich wichtig, helfen aber bei aktiviertem Kompatibilitätsmodus
nichts.
Solange der eingeschaltet ist, hast du keinen Mega64 vor dir sondern
einen Mega-103. Und der hat eine andere Speicherbelegung, was ganz
zwanglos die Abstürze erklären würde.
Um es ganz klar zu sagen: Du KANNST diese Thematik nicht ignorieren!
(Und dem Mann, der sich bei Atmel den Unsinn ausgedacht hat, dass diese
µC mit aktiviertem 103-Modus ausgeliefert werden, würde ich am liebsten
den Hals umdrehen)
Karl Heinz schrieb:> Und der hat eine andere Speicherbelegung, was ganz> zwanglos die Abstürze erklären würde.
Ich würde eher sagen:
..., was ganz zwangsweise die Abstürze erklären würde.
Hab ich schon erlebt, nur wusste ich nicht, dass der M64 die auch hat.
Ist ja n Ding.
Karl Heinz schrieb:> Hast du dich um die Fuse gekümmert? Die Abblockkondensatoren sind> natürlich wichtig, helfen aber bei aktiviertem Kompatibilitätsmodus> nichts.
Hey, das war genau der Fehler. Das Progamm von Karl Heinz läuft jetzt!!!
:) Vielen Dank euch allen für die schnelle und freundliche Hilfe.
006 schrieb:> Hey, das war genau der Fehler. Das Progamm von Karl Heinz läuft jetzt!!!> :) Vielen Dank euch allen für die schnelle und freundliche Hilfe.
Stefan gebührt die Ehre.
Da muss ich wohl in meinem persönlichen
Fehlermöglichkeiten-Gedächtnis-Ordner einen neuen Punkt für den M64
einfügen. Beim M128 hat man sich ja schon daran gewöhnt, dass das
Fehlerbild 'Absturz beim Funktionsreturn' auf eine fehlerhafte
Kompatibilitätsfuse hinweist.