PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Neu in der C-Programmierung



rogerberglen
15.11.2015, 10:19
Hallo Zusammen,
ich habe vor mich mit C-Programmierung zu beschäftigen, nachdem ich jetzt schon eine ganze Weile mit BASCOM und Assembler programmiert habe.
Und gleich habe ich ein Problem:
Im Atmel Studio habe ich eine Funktion "void Wait10ms(void)" definiert, vor dem Programmteil int main(void).
Jetzt wird dieser Programmteil in Atmel Studio im Einzelschrittmodus nicht aufgerufen!
Im Hauptprogramm rufe ich diesen über "Wait10ms()" auf, aber der Einzelschritt springt nicht in die Funktion "Wait10ms".
Wie geht das richtig?

shedepe
15.11.2015, 10:36
Hey, als erstes. Wenn du fragen zu Code hast poste den Code !
Dann zu deiner Frage, verwendest du den Debugger oder den Simulator?

Beim Debugger gibt es einmal die Variante des Einzelschritt der innerhalb der derzeitigen Methode bleibt und einmal die Variante die in eine aufgerufene Methode reinspringt. Die Tastenkombinationen dafür sollten oben im Debugmenü stehen.

rogerberglen
15.11.2015, 10:47
Hier der Code:

#include <avr/io.h> // Deklarationen einfügen
#define Takt 1000000UL // Systemtakt 1MHz intern

void Warte1ms() ;


/************************************************** **********
* Anfang der Hauptfunktion *
************************************************** **********/

int main(void)
{

DDRB = 0xFF ; // Port B ist Ausgang
PORTB = 0 ; // Anfangswert Null

/*********************************************
* 5 Takte Low / 5 Takte High gibt Takt / 10 *
*********************************************/

while (1) // unendliche Schleife

{

Warte1ms() ; // Wartefunktion ca 1ms
PORTB ++ ; // Portzähler + 1

}

}

void Warte1ms(void)
{

for (unsigned int i = Takt/4000ul; i > 0; i--) ;


}

Im Einzelschrittmodus wird immer die Stelle "void Warte1ms(void) übersprungen. Der gelbe Balken kommt nie in "for (unsigned int i = Takt/4000ul; i > 0; i--) an.

shedepe
15.11.2015, 10:58
Wie gesagt, es gibt dabei 2 verschiedene Arten von Einzelschrittmodi. Schau dir das Debugmenü in Atmelstudio an.

Sisor
15.11.2015, 11:04
Möglicherweise optimiert der Kompiler die Zeile

for (unsigned int i = Takt/4000ul; i > 0; i--) ;

einfach weg, weil seiner Meinung nach nichts passiert. Versuch mal:

for (unsigned volatile nt i = Takt/4000ul; i > 0; i--) ;

rogerberglen
15.11.2015, 11:13
Jetzt wird in die Funktion gesprungen, aber ich sehe nicht, dass die Variable i in irgendeiner Weise heruntergezählt wird. Der gelbe Balken verlässt die Funktion wieder nach nur einem Schritt. Beim nächsten Mal steht dann in i wieder der Startwert.<br>Ich würde schon gerne sehen, dass die Variable i heruntergezählt wird bevor die For-Scleife wieder verlassen wird.

neuer Gast
15.11.2015, 15:56
Gibt es überhaupt einen Inhalt zu void warte 1ms?

Hubert.G
15.11.2015, 17:47
Schreib mal so:
for (unsigned int i = Takt/4000ul; i > 0; i--)
{
asm("nop");
}

Dann wird es funktionieren. Ausserdem solltest du das Takt/4000ul vorher machen, sonst wird es bei jedem Durchlauf neu berechnet. Das sind dann etliche Takte mehr.

Sisor
15.11.2015, 18:25
Schreib mal so:
Ausserdem solltest du das Takt/4000ul vorher machen, sonst wird es bei jedem Durchlauf neu berechnet. Das sind dann etliche Takte mehr.
Ein Kompiler versucht alle konstanten Ausdrücke im Vorlauf zu berechnen. D.h. da wird im kompilierten Code nichts berechenet, sondern i wird mit 250 vorgeladen.

HaWe
15.11.2015, 20:01
mach deinen Zähler volatile!


void Warte1ms(void)
{
volatile unsigned int i;
for (i = Takt/4000ul; i > 0; i--) ;
}


edit:
das ist übrigens genau das, was ich meine, wenn ich sage:
nacktes C ist für Anfänger absolut nicht geeignet!

Daher gibt es für Anfänger C per Arduino IDE.
da gibt es Timer mit Millisekunden
millis()
oder Microsekunden
micros()
und
delay(msec)
und
delayMicroseconds(usec)

Ansonsten musst du dir die Timer callbacks selber programmieren.
( * schauder * )



int outPin = 8; // digital pin 8

void setup()
{
pinMode(outPin, OUTPUT); // sets the digital pin as output
}

void loop()
{
digitalWrite(outPin, HIGH); // sets the pin on
delayMicroseconds(50); // pauses for 50 microseconds
digitalWrite(outPin, LOW); // sets the pin off
delayMicroseconds(50); // pauses for 50 microseconds
}

Unregistriert
16.11.2015, 06:39
Auch in C gibt es delay(ms). Ist auf jeden Fall einfacher als void. Wenn ich void warte ... nichts reinschreibe wird es einfach gelesen ohne Funktion.

HaWe
16.11.2015, 10:15
delay() ist kein ANSI C oder C++ Befehl nach C99 oder C11 ANSI Standard.
Aber es kann natürlich theoretisch und praktisch möglich sein, dass es Plattform-spezifische Zusatzlibs gibt, die diesen Befehl implementiert haben.

oberallgeier
16.11.2015, 13:17
Ich gehe mal davon aus, dass Du AVRStudio zusammem mit WINAVR benutzt. Dann steht Dir die Bibliotheksfunktion

void _delay_ms (http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html#gad22e7a36b80e2f917324dc43 a425e9d3) (double __ms)zur Verfügung. Erläuterungen z.B. hier (klick) (http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html#gad22e7a36b80e2f917324dc43 a425e9d3). Die Bibliothek befindent sich (abhängig von Betriebssystem und Installation) z.B. in: C:\WinAVR-20100110\avr\include\util\delay.h AUF DEINEM Computer.

Sieht schon etwas komplexer aus als Deine Funktion ;-) :
void
_delay_ms(double __ms)
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
{
// __ticks = requested delay in 1/10 ms
__ticks = (uint16_t) (__ms * 10.0);
while(__ticks)
{
// wait 1/10 ms
_delay_loop_2(((F_CPU) / 4e3) / 10);
__ticks --;
}
return;
}
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}Sie funktioniert eine begrenzte Anzahl Millisekunden. Einschränkungen sind in der Funktionsbeschreibung im oben genannten Link zu nongnu.org und im Quelltext der _delay_ms ausführlich genannt. Lies das mal durch und - vielleicht Probierst Du mal das ? !