Hi zusammen,
Hardware:
µC = ATMega32 16MHz
4 x SRAM von ST (M68AW031A) 256Kbit (32K x8)
Verdrahtung vom SRAM zum µC:
PORTB(PB0 - PB7) = Adresse0 - Adresse7 (SRAM)
PORTA(PA1 - PA7) = Adresse8 - Adresse14 (SRAM)
PORTC(PC0 - PC7) = Daten DQ0 - DQ7 (SRAM)
ich habe ein Problem mit meinem C code und dem auslesen von SRAM
Bausteine.
Ich befülle diese (4st. à 32Kx8Bit -> 1MB) davor via RS232 mit Daten.
Diese Daten sind 16Bit Werte. Also lege ich jeweils in die erste 8Bit
Zeile das HighNibble und in die zweite Zeile das LowNibble des 16Bit
Wertes.
Später lese ich mit einem Interrupt vom Timer2 (TIMER2_COMP_vect) diese
Daten wieder aus und baue wieder eine 16Bit Adresse zusammen und
übergebe diese dann dem OCR1A Register vom Timer1. Dieser macht dann
eine PulsPausenModulation, welche über Tiefpässe geht um eine variable
Ausgangsspannung zu bekommen.
Mein Problem ist die Stelle am Timer2 (wo die 2x8Bit Werte aus dem SRAM
gelsen werden und dem OCR1A übergeben wird). Der Timer2 taktet mit
einstellbarer frequenz um daraus eine Samplerate für den OCR1A hin zu
bekommen. Wenn ich den Timer2 mit z.B. 250Samples/s laufen lasse (also
250 mal lößt der interrupt aus um den SRAM aus zu lesen) passt noch
alles.
Wenn ich jedoch die Samplerate erhöhe (auf 5000Hz -> 5000Samples/s),
werden einige Interrups "verschluckt". Wenn ich zum Testen einen PortPin
toggeln lasse um zu sehen wie lange der µC braucht, sehe ich, dass es
~206 - 210µs sind. Es dürften jedoch max. 200µs sein, da die Periode von
5000Hz = 200µs sind.
Mein kongrete Frage hierzu ist:
Kann ich den code zum auslesen des SRAM noch etwas optimieren, damit ich
Sampleraten von 5000 hin bekomme? In der ISR steht viel zu viel drin,
damit diese schnell abgearbeitet werden kann, normalerweise sind bei den
anderen ISrs immer ~5 - 15 Zeilen drin, in dieser jedoch einige mehr.
Ich denke da ist der Hund begraben...
Hier mal ein snippet vom Auslesen des SRAM (
1
ReadSRAM(longAddress)
) welche von der Funktion (
1
PlayStartCurveFromRAM(void)
) aufgerufen wird. Diese Funktion wird wiederum von der ISR (
1
ISR(TIMER2_COMP_vect)
) aufgerufen.
Nachtrag:
Die Divider in der TIMER2_COMP_vect ISR sind dafür da, um einen software
vorteiler zu realisieren. der Timer2 taktet mit mit einem Prescaler von
128 = 125000 Hz. Je nach Divider1 & Divider2 sind sampleraten (in der
theorie von 125000 - 4 Hz machbar). Jedoch in der ISR aber code drin
steht wird diese langsamer ODEr es werden welche "verschluckt" (Mit dem
Oszi nachgemessen).
Schon mal vielen Dank im voraus!
Gruß
Thomas D.
1
ISR(TIMER2_COMP_vect)
2
{
3
/*This Timer2 compare vector service routine generate the samplerate for
4
the start curve. See the Table below (timer2_init()) for more informations.
5
Divider1 and Divider2 values set the samplerate.
6
Example: Samplerate = 5000 samples/sec.
7
-> Divider1 = 24 (25 steps [0 - 24]).
8
-> Divider2 = 0
9
Divider1 & Divider2 are each 8Bit counter. The count clock is
10
F_CPU/Prescale -> 16MHz/128 = 125KHz.
11
Divider2 is a counter in a counter (Divider2 will increment when Divider1 is overflow).
12
*/
13
14
if(Divider1<Divider1_limit)//Current count value (Divider1) < count limit (Divider1_limit).
15
{
16
Divider1++;//Increment Divider1 register.
17
}
18
else//If Divider1 >= Divider1_limit.
19
{
20
Divider1=0;//Set Divider1 to default count value (re-start).
21
if(Divider2<Divider2_limit)//Current count value (Divider2) < count limit (Divider2_limit).
22
{
23
Divider2++;//Increment Divider2 register.
24
}
25
else//If Divider2 >= Divider2_limit.
26
{
27
PlayStartCurveFromRAM();
28
Divider2=0;//Set Divider2 to default count value (re-start).
29
}
30
}
31
}
1
voidPlayStartCurveFromRAM(void)
2
{
3
if(fSRAM_Address_Pointer<fSRAM_Address)
4
{
5
TempH=ReadSRAM(fSRAM_Address_Pointer);
6
fSRAM_Address_Pointer++;
7
TempL=ReadSRAM(fSRAM_Address_Pointer);
8
fSRAM_Address_Pointer++;
9
OCR1A=(((uint16_t)TempH<<8)|TempL);
10
}
11
else
12
{
13
TCCR2=0b00001000;
14
OCR1A=(((uint16_t)TempH<<8)|TempL);
15
fSRAM_Address_Pointer=0;
16
}
17
}
1
uint8_tReadSRAM(longAddress)
2
{
3
/*
4
Truth table of Multiplexer.
5
IC 4051 (MUX):
6
µC Pin: (PD6) (PD2) | (Out) (Out) (Out) (Out)
7
MUX Pin: 11 10 | 13 14 15 12
8
_____________|____________________________
9
A B | X0 X1 X2 X3
10
L L | L H H H
11
H L | H L H H
12
L H | H H L H
13
H H | H H H L
14
15
PD6 = L & PD2 = L -> 1.(SRAM IC14) -> Address: 0x00000 - 0x07FFF.
16
PD6 = H & PD2 = L -> 2.(SRAM IC12) -> Address: 0x08000 - 0x0FFFF.
17
PD6 = L & PD2 = H -> 2.(SRAM IC11) -> Address: 0x10000 - 0x17FFF.
18
PD6 = H & PD2 = H -> 4.(SRAM IC13) -> Address: 0x18000 - 0x1FFFF.
Hallo,
deine sogenannte Adressverwaltung ist viel zu kompliziert gedacht. RAM
addressiert man linear, bei 4 St. 32k-Chips sind das 15 Bit direkt an
die Chips und 2 Bit an einen 2 zu 4 Dekoder - da gibt es schlichtweg
nichts zu rechnen!
Einfach mit 17 Bit zählen und den Zählerstand ausgeben, fertig ist die
Adressierung. Wenn dann die Zeit nicht reicht, dann gehts eben wirklich
nicht.
Gruss Reinhard
@ Martin Wende (Firma: fritzler-avr.de) (fritzler)
>Nimmste nen AVR mit Hardware Speicherinterface und der saugt dir das in>paar Takten ausm SRAM.
Richtig. Und wenn es mehr als 64kB sein sollen, macht man halt old
school ne Bankumschaltung.
Hi!
@Georg G.
Verstehe ich nicht ganz was Du damit sagen willst. der SRAM benötigt
min. 70ns Zeit um sich einzustellen (Laut datenblatt). Da das setzen von
PD3 schon etwas dauert, reichen hier 50ns. funtioniert auch wunderbar...
@Joerg Wolfram
Danke für den Tipp, werd das mal so probieren, jedoch benötigt diese
adressierung am wenigsten Zeit von der Funktion. :(
Werde diese aber einbauen.
@Reinhard Kern
ein µC mit Speicherinterface hätte ich auch gerne genommen, diese HW war
aber schon fertig gelayoutet. Ich muss hier nur den ATMega statt ein
C-control µC ersetzen da der C-Control viel zu langsam war.
Zwecks der Adressierung und der 17Bit. Das mache ich eigentlich, nur in
zwei steps.
Die 4 SRAMs sind parallel geschaltet, über ein MUX (2 zu 4) wähle ich
dann den richtigen IC...
Thomas D. schrieb:> Die 4 SRAMs sind parallel geschaltet, über ein MUX (2 zu 4) wähle ich> dann den richtigen IC...
Und wozu um alles in der Welt brauchst du dazu Subtraktionen??
Gruss Reinhard
Thomas D. schrieb:> reichen hier 50ns
Sieh dir bitte mal an, wie lange ein _delay_us(0.05) in der Realität
dauert und welche Menge Code dafür eingebunden wird. Die delay Funktion
rechnet intern mit double Gleitkomma! Mit einem oder zwei inline nop
bist du besser bedient.
Thomas D. schrieb:> Address -= 0x08000;
Überflüssig, da im weiteren Verlauf ohnehin nur die unteren 15 Bits
genutzt werden.
> PORTA(PA1 - PA7) = Adresse8 - Adresse14 (SRAM)> PORTA = (Address >> 7);
Ungünstig. PA0..6 wär einfacher, da >>8 billiger ist als >>7.
> DDRC = 0xFF; //Set PORTC back to Output.> PORTB = 0; //Clear Low Nibble Address.> PORTA = 0; //Clear High Nibble Address.> PORTD &= ~(1 << PD6); //Set PD6 (MUX A) back to default (low).> PORTD &= ~(1 << PD2); //Set PD2 (MUX B) back to default (low).
Was bringt dir dieser ganze Zauber? Der Kram wird das nächste Mal
ohnehin komplett neu gesetzt und bis dahin interessiert es niemanden.
> über ein MUX (2 zu 4) wähle ich dann den richtigen IC...
Das ist ein Decoder, kein Mux.
@ am falschen Rechner (Gast)
>> reichen hier 50ns>Sieh dir bitte mal an, wie lange ein _delay_us(0.05) in der Realität>dauert und welche Menge Code dafür eingebunden wird.
Genau DAS solltes DU mal tun.
> Die delay Funktion>rechnet intern mit double Gleitkomma!
Jain. Nur wird das vom Compiler zur Compilezeit gemacht, nicht zur
Laufzeit. Wenn die Optimierung eigeschaltet ist ;-)
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29>Mit einem oder zwei inline nop>bist du besser bedient.
Kommt auf das Gleiche raus.
A. K. schrieb:>> über ein MUX (2 zu 4) wähle ich dann den richtigen IC...>> Das ist ein Decoder, kein Mux.
PS: Das IC mag ein Muxer sein, dessen Verschaltung ist hier ein Decoder.
Kannst du mal die komplette Verschaltung vom RAM posten? Also nicht nur
CE und WE, sondern auch OE. Und auch skizzieren, was mit OE im Code so
alles passiert. Der Ablauf davon sieht nämlich etwas seltsam aus. Kommt
nicht oft vor, dass man beim Lesen die Schreibleitung steuert (und evtl.
beim Schreiben die Leseleitung?). Üblich wärs andersrum.
Ja gibt es, diese steht in der WriteSRAM Funktion. Diese ist hier aber
nicht gelistet. Da über diese Funktion daten auf das SRAM geladen
werden, ist dies nicht zeitkritisch.
Zwecks MUX bin ich davon ausgegangen das jeder weis was ich mein...
@Joerg Wolfram
Hab Dein Vorschlag eingebaut, funktioniert damit ja auch. Nur ohne Erolg
auf die performance.
Es muss doch möglich sein in 200µs zwei mal einen 8Bit wert am PORTC zu
lesen (davor die Adresse einstellen) und diese dann über casting ins
OCR1A Register zu schieben, hätte nicht gedacht das genau hier von den
insg. 1500 Zeilen code Probleme auftreten. :(
Gruß
Thomas D.
Thomas D. schrieb:> Ja gibt es, diese steht in der WriteSRAM Funktion. Diese ist hier aber> nicht gelistet. Da über diese Funktion daten auf das SRAM geladen> werden, ist dies nicht zeitkritisch.
Ist in diesem Aspekt nicht der Punkt. Ich habe den konkreten Verdacht,
das dein Datenbus die meiste Zeit auf Krawall gebürstet ist, also
Ausgang gegen Ausgang steht. Wenn OE permanent aktiv ist, dann sind die
Datenleitungen vom RAM aktiv sobald CE=0,WE=1. Also die von Bank 0
meistens. Dein Port C ist es aber auch...
Üblich wärs eigentlich, in der Leseroutine für die Dauer vom Zugriff OE
zu aktivieren und in der Schreibroutine analog WE.
Thomas D. schrieb:> Es muss doch möglich sein in 200µs zwei mal einen 8Bit wert am PORTC zu> lesen (davor die Adresse einstellen) und diese dann über casting ins> OCR1A Register zu schieben, hätte nicht gedacht das genau hier von den> insg. 1500 Zeilen code Probleme auftreten. :(
Dann sieh dir doch einfach mal den Assemblercode an....
BTW: hast du verstanden, was da im
Beitrag "Re: SRAM auslesen zu langsam." gemeint ist?
Ein Tipp: Zeichen mal deine Adressleitungen A15 und A16 auf. Und dann
daneben die Eingänge vom Multiplexer.
Warum verwendet man einen Analogmultiplexer zur Ansteuerung eines
digitalen Bausteins?
>>>> SRAM auslesen zu langsam
1
PORTD|=(1<<PD3);//Set PD3 to high, to disable the Write Enable Pin in SRAM (LOW active).
2
:
3
:
4
:
5
PORTD|=(1<<PD3);//Set PD3 to high, to disable the Write Enable Pin in SRAM (LOW active).
Warum bastelst du in der Leseroutine laufend am WE# rum?
1
PORTD&=~(1<<PD6);//Set PD6 (MUX A) back to default (low).
2
PORTD&=~(1<<PD2);//Set PD2 (MUX B) back to default (low).
Ist nicht jeder andere Wert genauso gut wie dieser "Defaultwert"?
Du jammerst, dass das Lesen zu lange dauert und dir die Zeit nicht
reicht, verplemperst aber jede Menge Zeit mit unnötigen Aktionen...
Lothar Miller schrieb:> Warum verwendet man einen Analogmultiplexer zur Ansteuerung eines> digitalen Bausteins?
Ist zwar eine kuriose Methode, aber nicht wirklich ein Problem.
Und wenn du schon mit kompletten Adressen rummachst
> uint8_t ReadSRAM(long Address)
Adressen können nicht negativ sein.
Also wäre das sinnvollerweise ein unsigned long.
Dann kommen jede Menge
if (Address >= 0x00000 && Address <= 0x07FFF) //Enable SRAM IC 14.
und Subtraktionen und weiß der Kuckuck was noch.
Zerleg dir die 32 Bit Adresse gleich mal in die 2 Bits, die du zur
Selektion brauchst und die restlichen 15 Bit. Die 15 Bits interessieren
dich nicht weiter, die gibst du an den Port aus.
Und die 2 Bits legst du an DB6 bzw. DB2.
Es gibt da keinen Grund für Vergleichsorigien bzw. Subtraktionen. Und
schon gar nicht gibt es da einen Grund dafür, deinen µC dafür in 32 Bit
Arithmetik hineinzutreiben.
Es heißt zwar immer 'vorzeitige Optimierung sei die Wurzel allen übels'.
Aber auf der anderen Seite muss man seinen µC auch nicht sinnloserweise
in Beschäftigungstherapie treiben, in dem man ihm naheliegende
Vereinfachungen vorenthält. Und wenn du ihn mutwillig in 32 Bit
Arithmetik hineintreibst, dann darfst du dich über fehlenden Speed nicht
wundern.
if(Address>=0x00000&&Address<=0x07FFF)//Enable SRAM IC 14.
2
{
3
...
4
}
5
if(Address>=0x08000&&Address<=0x0FFFF)//Enable SRAM IC 12.
6
{
7
...
Eine Adresse kann nicht negativ sein. Wenn sie es jemals ist, dann
deswegen, weil du für Address einen long genommen hast, der eigentlich
ein unsigned long sein sollte. Und ein unsigned long kann per Definition
nicht kleiner als 0 sein.
d.h die erste Abfrage nach >= 0 ist schon mal sinnlos. Den für einen
unsigned long ist das trivialerweise IMMER erfüllt.
weiters: wenn dein erstes if korrekterweise erkannt hat, dass sich die
Adresse im Bereich 0 bis 0x07FFF bewegt, dann KANN trivialerweise der
nächste if (und alle weiteren) nicht mehr TRUE ergeben! d.h diese
weiteren Tests sind sinnlose weitere Tests, die nur Zeit verbrauchen und
sonst nichts. Und genau aus dem Grund wurde ein 'else' erfunden, um
auszudrücken: Nur dann, wenn dieser Test nicht TRUE ergeben hat:
1
if(Address<=0x07FFF)//Enable SRAM IC 14.
2
{
3
...
4
}
5
elseif(Address>=0x08000&&Address<=0x0FFFF)//Enable SRAM IC 12.
6
{
7
...
(Sobald das erste if den Adressbereich erkannt hat, werden die anderen
Adresstests gar nicht mehr gemacht.
Wenn aber das erste if den Adressbereich nicht erkannt hat, dann ist
auch klar, dass sich die Adresse NICHT im Bereich 0 bis 0x07FFF bewegt.
Daraus folgt aber auch, dass du nicht extra testen musst, ob die Adresse
auch wirklich >= 0x08000 ist. Denn die MUSS größer/gleich sein. Wenn sie
es nicht wäre, dann hätte der erste if das bereits erkannt und
behandelt. D.h. du hast da einen Vergleich, der trivialerweise erfüllt
sein MUSS! Andernfalls wäre das Programm überhaupt nie an diese Abfrage
gekommen!
1
if(Address<=0x07FFF)//Enable SRAM IC 14.
2
{
3
...
4
}
5
elseif(Address<=0x0FFFF)//Enable SRAM IC 12.
6
{
7
...
Bei einer Reihe von Bereichsprüfungen, bei denen die Bereiche nahtlos
aneinander anschliessen, ist die Prüfung auf die Untergrenze eine
sinnlose Operation. Denn durch die Anordnung der if bzw. else if ist
automatisch sicher gestellt, dass die Untergrenze bereits von den
vorhergehenden if bzw. else if korrekt erkannt wurde. Das muss man nicht
extra testen und kostet nur Zeit, wenn der Compiler das nicht erkennt
und wegoptimiert.
A. K. schrieb:> Lothar Miller schrieb:>> Warum verwendet man einen Analogmultiplexer zur Ansteuerung eines>> digitalen Bausteins?>> Ist zwar eine kuriose Methode, aber nicht wirklich ein Problem.
Doch schon.
Man braucht zusätzliche Pullups, damit die nicht selektierten Pins nicht
in der Gegend rumfloaten.
Peter
@Peter Dannegger (peda)
>Man braucht zusätzliche Pullups, damit die nicht selektierten Pins nicht>in der Gegend rumfloaten.
Vor allem, wozu wurden ICs wie der 74HC138 erfunden? Damit wird die
ganze sinnlose Adressprüferei zu einer trivialen und schnellen
Bitkopiererei.
Ist zwar immer noch deutlich langsamer als eine direkte Hardwarelösung,
aber auch deutlich schneller als der akademische Murks.
Die Pins für WE und OE kenn ich jetzt nicht, hab einfach mal geraten.
Falk Brunner schrieb:> Genau DAS solltes DU mal tun.
Und? Was ist dein Ergebnis? Stimmen die 50ns auch nur annähernd?
Papier lesen ist etwas anderes als eine Sache auch mal auszuprobieren.
Drei Takte, wie zu erwarten. Klar, mit nop() kann man es taktgenau
machen, war aber gar nicht die Kernaussage.
Beitrag "Re: SRAM auslesen zu langsam."
Einfach nur Blödsinn.
Wahrscheinlich wird es schon funktionieren, wenn du nur die vorherigen
Tipps beachtest.
Zusätzlich kannst du noch bedenken, dass ein Funktionsaufruf auch Zeit
kostet. Je nach Optimierungsstufe ersetzt der Compiler das durch inline
Funktionen. Auf der sicheren Seite bist du allerdings, wenn du die
Geschichte direkt implementierst bzw. Makros verwendest.
Gruß
> Wenn ich jedoch die Samplerate erhöhe (auf 5000Hz -> 5000Samples/s),> werden einige Interrups "verschluckt". Wenn ich zum Testen einen> PortPin toggeln lasse um zu sehen wie lange der µC braucht, sehe ich,> dass es ~206 - 210µs sind. Es dürften jedoch max. 200µs sein, da> die Periode von 5000Hz = 200µs sind.
Wobei allerdings:
Wenn man bei 16Mhz Taktfrequenz keine höhere ISR Frequent als 5000
Aufrufe pro Sekunde hinkriegt, dann ist da mit Sicherheit noch was
anderes faul. Das wären 3200 Takte von einem ISR Aufruf zum nächsten. So
viel kann er gar nicht in der ISR verbraten haben. Noch nicht mal mit
der ganzen 32-Bit Geschichte.
Es sei denn natürlich, der Optimizer war nicht angeschaltet und das
_delay_us hat die komplette Floating Point Arithmetik nach sich gezogen.
Aber dann gehören ihm sowieso die Ohren langgezogen.
Karl Heinz Buchegger schrieb:> Es gibt da keinen Grund für Vergleichsorigien bzw. Subtraktionen.
Das habe ich auch schon versucht zu erklären, er versteht da aber nur
komplett Bahnhof. Das ist eben das Problem beim Copy&Paste, er weiss
auch nicht annähernd was die Software eigentlich tut und warum. In dem
Fall weiss ich es allerdings auch nicht, eigentlich gibt es nichts
einfachers als einen Zählerstand auszugeben und die Daten einzulesen.
Was sich der Programmierer bei ReadSRAM gedacht hat, ist mir ein
komplettes Rätsel. Aber vielleicht verstehe ich den modernen
Programmierstil nicht mehr.
Gruss Reinhard
Werf das Layout weg und such dir einen geeigneten µC.
Vielleicht einen mit direkt genug internem Ram, oder zumindest ein HW
interface für externe Ram Anbindung.
Wenn du die Zeit und Ärger rechnest die du in eine solche SW
investierst, ist ein neues Layout allemal billiger.
An alle die nichts besseres zu tun haben wie nur die letzten zwei
Einträge zu lesen und dann irgendwas schreiben wollen weil sie sonst
nichts im leben zu sagen haben können mir gestohlen bleiben.
Das Problem ist mittlerweile gelöst, läuft alles wunderbar.
Interessieren wird es hier wohl eh keinen, daher lass ich es mit der
Erklärung.
Ist mir auch klar das einer der das ganze schon 10 jahre macht schneller
ans ziel kommt, darum geht es hier aber nicht, eigeninitiative und Übung
ist bei jedem gefragt der damit anfängt, positive kritik und
Verbesserungen sind wichtig, dafur gibt es doch foren, oder?
Viele denken sie müssen aber gegen einen spielen um etwas zu beweisen..
ha da lach ich.
@kern
Werde erwachen... bitte!
Und warum immer so viel off topic herrscht verstehe ich nicht von wegen
neue hw bauen etc. Wenn die leute mal alles gelesen hätten, wüssten die,
das die hw fertig ist und nicht von mir ist... ich setze nur den mc auf
die pcb. Daher bin ich an das pinning und an die randbeschaltung
gezwungen.
An alle die etwas produktives geschriebenen haben, vielen dank! Hat mir
geholfen.
Gruß
An den rest geht mein herzliches Beileid!
Thomas D. schrieb:> das die hw fertig ist und nicht von mir ist... ich setze nur den mc auf> die pcb. Daher bin ich an das pinning und an die randbeschaltung> gezwungen.
Und genau das ist immer wieder das gleiche Problem.
Irgendein Hardware Spezi macht eine Platine und wirft die den Software
Leuten vor die Füße mit dem Kommentar, "hier ist fertig jetzt mach mal,
Änderungen gibt es keine".
Eigentlich müsste mal als Softareentwickler das Teil zurückwerfen mit
dem Kommentar "Das ist Müll, nochmal von vorne, aber dann richtig"
Ist das denn SOOO schwer das die Hardwareentwickler ( oder Einkäufer,
die sind noch schlimmer) mit den Softwareentwicklern reden BEVOR die
Hardware gebaut ( gekauft) wird.
@Der
Das Problem war wie vermutet, dass in der ISR zu viele unterfunktionen
aufgerufen wurden.
z.b. zwei mal ReadSRAM, PowerOff(), etc..
Ich bin mir nicht sicher, aber ich vermute, dass wenn die ISR eine
andere Methode aufruft die auch von anderen Methoden in der Main
aufgerufen werden können, hat es geknallt.
Ja, ich habe alle wichtigen variablen mit volatile deklariert.
Nach dem ich die eigentliche funktion vom auslesen des SRAM in die ISR
direkt geschrieben habe, komme ich locker untrer die kritischen 200µs
(sind jetzt ca. 170µs). D.h. alleine 3 funtionen aufzurufen, hatte ca.
30µs gedauert, zumindest roh im c code gesehen. Was der comiler dann
daraus gemacht hat, kann ja was ganz anderes sein. Optimierungsstufe war
O1. Momentan benutze ich O3.
@Ralph
Da gebe ich Dir voll und ganz recht! Ich hätte auch lieber einen µC mit
Speicheranbindung genommen, dazu die Spannung nicht mit einer
PulsPausenModulation und Tiefpässe 6er Ordnung geglättet, sondern eine
art 10 oder 12 Bit 2R2 Netzwerk genommen.
Oder gleich einen µC mit Speicheranbindung UND D/A wandler, dann wäre
das alles viel einfacher.
Gruß
Thomas D.
Thomas D. schrieb:> eine andere Methode aufruft
Eine Methode also. Früher was das in C noch eine simple Funktion...
> komme ich locker untrer die kritischen 200µs (sind jetzt ca. 170µs).
Du hast 85% Prozessorauslastung und sagst "locker"?
Warum brauchst du so lange?
Was läuft da schief?
Interessiert dich das nicht?
Lothar Miller schrieb:> Warum brauchst du so lange?> Was läuft da schief?> Interessiert dich das nicht?
Scheint nicht so zu sein.
Bei 16Mhz hat er eine Taktzeit von 0.0625 µs
Dauert die ISR 170µs, dann verbrutzelt er in der ISR 2720 Takte. Ein
gesunder Mix aus Assembleranweisungen vorausgesetzt sind das über den
Daumen irgendwas bei 2200 Instruktionen. Der SRAM Zugriff braucht,
wieder über den Daumen und extrem wohlwollend geschätzt, davon ca. 20
bis 40. Wo kommen die restlichen 2100 Instruktionen her? Das ein
Funktionsaufruf ein paar Takte kostet, Register sichern und
wiederherstellen .... alles geschenkt. Klar kostet das was, aber das
sind keine 2000 Instruktionen.
Irgendwas stimmt da nicht.
Und nicht zuletzt hab ich schön langsam den Verdacht, dass die 16Mhz in
Wirklichkeit nur 1Mhz sind und/oder es irgendwo Floating Point en mass
gibt, die er nicht zeigt.
Das hier
> D.h. alleine 3 funtionen aufzurufen, hatte ca. 30µs gedauert,
ist keine Erklärung. bzw. nur dann, wenn man beide Augen zukneift. Denn
3 Funktionsaufrufe sind bei 16Mhz nie und nimmer für 30µs
verantwortlich. Das sind 480 Takte. 160 pro Aufruf.
Und bei den Zahlen wage ich die Prognose: wir werden noch mal von ihm
hören.