mikrocontroller.net

Forum: Compiler & IDEs Timing-Problem beim ATMega32


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein kleines Problem mit meinem AtMega32...
Ich habe bereits ein lauffähiges BASCOM-Programm zusammengedängelt.
Das finde ich allesdings äusserst unschön.
Nun ist es so, dass ich selbiges gerne in ein C-Programm konvertieren 
möchte, also zumindest von der Idee her.

BASCOM-Programm:
$regfile = "m32def.dat"                                     'definieren des verwendeten Chips

$crystal = 16000000                                         'definieren des verwendeten externen Quarz (8MHz)

Config Portd = Output
Dim S As String * 24





Main:
Do



Portd.1 = 1
Waitus 833

Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833





Portd.1 = 1
Waitus 833

Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250




Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250




Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833

Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250




Portd.1 = 1
Waitus 833

Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250




Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250



Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 250


Portd.1 = 1
Waitus 833

Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 0
Waitus 833
Portd.1 = 1
Waitus 833
Portd.1 = 1
Waitus 833

Portd.1 = 1
Waitus 833

Portd.1 = 0
Waitus 833
Portd.1 = 0
Waitus 833
Waitms 10000
Loop

Return

Mein C-Programm sieht nun wie folgt aus:

#define F_CPU 16000000UL  // 16MHZ
#include <avr/io.h>
#include <util/delay.h>

void DELAYUS(int a)
{
        _delay_us(500);
        asm("nop");
        _delay_us(a-500);
}

void delay(int a)
{
        _delay_ms(a);
}

void txd(int a)
{
if (a==1)
                PORTD=0;
        else
                PORTD=2;
}

void test(void)
{
int d=800;
txd(1);
delay(1000);
//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//=================2

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//==============================3

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//======================4

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
//Parity-Bit
txd(0);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//===============5

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//================6

for (int i=0;i<=12;i++)
{
//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);
}

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
//Parity-Bit
txd(1);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);

//Startbit
txd(0);
DELAYUS(d);
//7-Bit Zeichen Übertragen
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(1);
DELAYUS(d);
txd(0);
DELAYUS(d);
txd(0);
DELAYUS(d);
//Parity-Bit
txd(0);
DELAYUS(d);
//2 Stop-Bits
txd(1);
DELAYUS(d);
txd(1);
DELAYUS(d);
delay(15);
}

int main (void) {
   DDRD  = 0xff;
   PORTD = 0x00;

   while(1) {
//      DELAYUS(800);
//      txd(1);
//      DELAYUS(800);
//      txd(0);
        test();
        delay(5000);
   }
   return 0;
}
roo


Zum testen habe ich nun in beiden Sprachen eine simple Schleife 
geschrieben die nichts weiter tut als den einen pin im 833µs-Takt ein 
und aus zu schalten.
Auf meinem Oszilloskop sehen die Intervalle in denen die beiden 
Programme schalten allerdings noch entwas unterschiedlich aus.
Mein Problem ist nicht durch die Nutzung eines UARTs zu lösen, da die 
Protokoll-Norm erheblich von der RS232-Norm abweicht.

Hat jemand eine Idee?

Grüße und Danke
Thomas

Autor: Icke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benutze einen Timer und Bitschiebereien.
So wird das nichts.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum funktioniert es denn dann mit absoluter Zuverlässigkeit mit 
BASCOM?
Und warum ist der Impuls und dessen breite so stabil, dass ich im 
Oszilloskop keine Veränderungen sehe?

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da Programm ist ja wohl ein verspäteter Aprilscherz. Selbst in Bascom 
gibt es Schleifen und Unterprogramme.

Was macht dein C-Programm, wenn du statt
> _delay_us(a-500);

 _delay_us(300);

schreibst? Der Sinn der variablen Verzögerung ist eh nicht klar.

Oliver

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Forenregeln lesen! Langer Code gehört in den Anhang! Das ist eine 
Zumutung!

Abgesehen davon: Dokumentation lesen! Variable delays gehen so nicht. 
Und ein C-Buch lesen, in dem was von Schleifen und strukturierter 
Programmierung steht!

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas,

mit allem Respekt, aber Dein Code ist brechreizerregend.

Wobei Du interessanterweise denselben Erguss bereits im Bascom-Forum 
losgeworden bist, nur hieß es dort noch:
"Code einer Loop nicht deterministisch"

Lustigerweise hast Du dort in Deinem ersten Versuch das Pin statt den 
Port getoggelt, also den Pullup, und Dich über das Ergebnis gewundert.

Du würdest Dir selber einen Gefallen tun, indem Du:
a) den Gebrauch von intelligent wirkendenden Fremdwörtern wie 
"deterministisch" in Zusammenhang mit diesem Code-gewordenen Albtraum 
unterlässt
b) erst mal programmieren lernst

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

ich kann nicht nachvollziehen, warum ihr meint die Qulität meines Codes 
beurtielen zu können wenn ihr garnicht wisst worum es bei meinem Versuch 
geht.
Mit genuss hätte ich mir das Posting sparen können wenn ich gewusst 
hätte, dass es hier sowieso nur darum geht anderen Menschen für Ihren 
Code eins aufs Maul zu hauen, wenn man selbst meint, dass man der Gott 
unter der Sonne ist.

Es handelt sich bei meinem Code nur um einen Versuch ob es möglich ist 
diese Bits in den entsprechnenden Intervallen zu übertragen. Dank der 
Hilfe im Basic-Forum habe ich das Basic-Programm auch bereits zum Laufen 
bekommen. Ich kann nun das Gerät am anderen Ende des Drahtes mit den 
gewünschten statischen Testdaten versorgen.

In der regel ist es aber doch nunmal so, dass man einen solchen Versuch 
der generellen Machbarkeit nicht mit zu vielen Strukturen durchführt um 
so viele Fehlerquellen wie möglich auszuschliessen.
Der nächste Schritt wäre dann sowieso eine Dynamik in die Übertragenen 
Daten zu bekommen.

Hat nun noch jemand einen Konstruktiven Vorschlag für mein Problem oder 
seid Ihr alle nur gut um über anderen Code Meckern???

Achso und Deterministisch hat auf mein Problem voll zugetroffen, denn es 
hat sich nicht nach jedem Schleifendurchlauf gleich verhalten!!!
Vielleich sollte da noch mal jemand über andere Arten der Beleidigung 
und Abwartschung derer Leute nachdenken!!!

Vielen Dank schonmal....

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Och, jetzt isser beleidigt.

Drehn wir den Spieß doch mal rum. Da stellt jemand einen hunderte Zeilen 
langen, völlig unleserlichen und absolut blödsinnig formulierten und 
formatierten Code in ein Forum, wovon 99,9% der Zeilen erkennbar nichts 
mit dem Problem zu tun haben, macht nicht einmal den Versuch, für das 
Problem kurzes, möglichst prägnantes Beispiel zu erstellen, geschweige 
denn, die Forenregeln oder den allgemeine Umgang im Forum zu beachten, 
und erwartet, das andere ihre freie Zeit dafür opfern, sich in den 
ganzen Müll hinzudenken. Eine bessere Steilvorlage für blöde Antworten 
und hämische Kommentare gibt es doch gar nicht.

>ich kann nicht nachvollziehen, warum ihr meint die Qulität meines Codes
>beurtielen zu können wenn ihr garnicht wisst worum es bei meinem Versuch
>geht.

Nimm das einfach mal als gegeben an. Schließlich gehst du ja auch davon 
aus, daß dir hier jemand helfen kann.

Aber zurück zum Problem:
>Zum testen habe ich nun in beiden Sprachen eine simple Schleife
>geschrieben die nichts weiter tut als den einen pin im 833µs-Takt ein
>und aus zu schalten.

Das mag sein, aber dein gezeigtes Programm macht etwas anderes. Die 
auskommentierten Zeilen im Hauptprogramm würden das tun. Zeig doch mal 
genau das Testprogramm, auf dem deine Oszi-Messungen beruhen. Abgesehen 
davon ergibt
int d=800;
wohl keine 833µs;

Oliver
Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> In der regel ist es aber doch nunmal so, dass man einen solchen
> Versuch der generellen Machbarkeit nicht mit zu vielen Strukturen
> durchführt um so viele Fehlerquellen wie möglich auszuschliessen.

Schon richtig.
Aber man läuft dann auch Gefahr, dass der Versuch mit dem Endergebnis 
absolut nichts zu tun hat und daher keineswegs in irgendeiner Form 
aussagekräftig ist, ob das gesteckte Ziel erreichbar ist oder nicht.

Wenn du schon was versuchst, ohne allzuviel Aufwand zu haben, dann mach 
dir doch um Himmels Willen wenigstens eine Funktion, ohne gleich auf 
Copy&Paste auszuweichen. Copy&Paste ist eigentlich fast immer das 
Schlimmste was du tun kannst. Es sieht nur auf den ersten Blick so aus, 
als ob damit das Programmieren schnell von der Hand geht.
void TransmitData( uint8_t Bit1, uint8_t Bit2, uint8_t Bit3, uint8_t Bit4,
                   uint8_t Bit5, uint8_t Bit6, uint8_t Bit7, uint8_t Parity )
{
  int d=800;

  //Startbit
  txd(0);
  DELAYUS(d);

  //7-Bit Zeichen Übertragen
  txd( Bit1 );
  DELAYUS(d);
  txd( Bit2 );
  DELAYUS(d);
  txd( Bit3 );
  DELAYUS(d);
  txd( Bit4 );
  DELAYUS(d);
  txd( Bit5 );
  DELAYUS(d);
  txd( Bit6 );
  DELAYUS(d);
  txd( Bit7 );
  DELAYUS(d);

  //Parity-Bit
  txd( Parity );
  DELAYUS(d);

  //2 Stop-Bits
  txd(1);
  DELAYUS(d);
  txd(1);
  DELAYUS(d);
  delay(15);
}

Alleine durch diese Funktion fällt von deinem Code schon mal geschätze 
70% weg ....
void test(void)
{
  TransmitData( 0, 1, 1, 0, 1, 1, 1,  1 );
  TransmitData( 0, 0, 1, 0, 1, 0, 1,  1 );
  TransmitData( 1, 0, 1, 0, 0, 0, 1,  1 );
  TransmitData( 1, 1, 0, 0, 1, 0, 1,  0 );
  TransmitData( 0, 0, 1, 0, 1, 0, 1,  1 );

  for (int i=0;i<=12;i++)
  {
    TransmitData( 0, 0, 0, 0, 0, 1, 0,   1);
  }

  TransmitData( 1, 0, 1, 1, 0, 0, 0,   1 );
  TransmitData( 0, 1, 0, 0, 1, 0, 0,   0 );
}

... und der Rest ist so gestaltet, dass du zumindest in der Anzahl der 
übertragenen Bits keinen Fehler mehr haben kannst.

Testcode soll durchaus ein Minimum an Funktionalität haben, aber er soll 
auch halbwegs realistisch sein.

Dein eigentliches Problem wurde ja schon angesprochen
void DELAYUS(int a)
{
        _delay_us(500);
        asm("nop");
        _delay_us(a-500);
}

... beim Aufruf der _delay_xx Funktionen immer drauf achten, dass die 
Argumente konstant sind. a-500 ist nicht konstant.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>... beim Aufruf der _delay_xx Funktionen immer drauf achten, dass die
>Argumente konstant sind. a-500 ist nicht konstant.

Das stimmt zwar, erklärt nicht aber, warum das delay nicht trotzdem 
konstant ist.

Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oliver wrote:

> Das stimmt zwar, erklärt nicht aber, warum das delay nicht trotzdem
> konstant ist.

Da hast du recht.
Auf der anderen Seite ist

> Auf meinem Oszilloskop sehen die Intervalle in denen die beiden
> Programme schalten allerdings noch entwas unterschiedlich aus.
...
> Und warum ist der Impuls und dessen breite so stabil, dass ich im
> Oszilloskop keine Veränderungen sehe?

auch keine wirklich gute Fehlerbeschreibung.
Ich kann davon eigentlich nicht wirklich ableiten, dass seine Delay 
Zeiten einen Jitter haben, nur dass die Zeiten nicht ganz das sind, was 
er sich erwartet.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich habe in meinem nun funktionieren Basic-Code ja ein Delayus von 833µs 
drin. Dieser Code funktioniert ja auch.
Also habe ich mir ein Basic-Programm gebaut welches nichts anderes macht 
als Flanken zu erzeugen:
$regfile = "m32def.dat"
$crystal = 16000000
Config Portd = Output

Main:
  Do
    Portd.1 = 1
    Waitus 833
    Portd.1 = 0
    Waitus 833
  Loop
Return

Dabei habe ich auf dem Oszi nun die tatsächliche Flanken-Länge messen 
können. Diese stimmt auch ziemlich genau mit der Ziel-Wartezeit von 
833µs überein.

Dann bin ich als nächtes her gegangen und habe ein entsprechendes 
C-Programm geschrieben was eigentlich das selbe tuen sollte. Dabei bin 
ich allerdings bei der Dokumentation darauf gestossen, dass _delay_us 
maximal 768µs Delay zulässt. Daher meine Konstruktion mit den 2 
getrennten Anweisungen.

Mein C-Programm sah nun so aus:
#define F_CPU 16000000UL  // 16MHZ
#include <avr/io.h>
#include <util/delay.h>

void DELAYUS(int a)
{
        _delay_us(500);
        _delay_us(a-500);
}

int main (void) {
   DDRD  = 0xff;
   PORTD = 0x00;

   while(1) {
      DELAYUS(800);
      txd(1);
      DELAYUS(800);
      txd(0);
   }
   return 0;
}

Dabei habe ich dann festgestellt, dass die Flankenlänge erheblich von 
der des Basic-Programms abweicht (~60-100µs)...

Nun war meine Frage warum.

Sorry, dass ich mein Fehler nicht ausführlich genug beschrieben habe. 
Vielleicht hätte der Teppich-Code von 1en und 0en nicht not getan.

Grüße
Thomas

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Dabei habe ich dann festgestellt, dass die Flankenlänge erheblich von
>der des Basic-Programms abweicht (~60-100µs)...

Was denn nun genau? Sind die Pulse der C-Version alle gleich lang, aber 
eben zu lang, oder schwankt die Pulslänge von Puls zu Puls?

Oliver

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas,

hier ein Zitat von Dir aus Deinem Beitrag im Bascom Forum:

"Nach jedem 2. Durchlauf der Schleife bleibt der Ausgang auf 0 nach 
jedem anderen Durchlauf ist der Ausgang auf 1."

Wenn Du jetzt wüsstest was das Wort "deterministisch" eigentlich 
bedeutet, dann  hättest Du verstanden, daß sich Dein Programm, im 
Gegensatz zu Deiner Aussage, in höchsten Maße deterministisch verhielt.

Jetzt ist's ja nicht schlimm, etwas nicht zu wissen, geht mir jeden Tag 
so.

Nur wer Dinge wie :

"Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang"

vollständig ignoriert, dazu Code postet der dermaßen häßlich ist und 
auch noch mit Fremdwörtern rumwirft, von denen er keine Ahnung hat, darf 
sich über ein bisserl Spott nicht beschweren.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas wrote:
> Dann bin ich als nächtes her gegangen und habe ein entsprechendes
> C-Programm geschrieben was eigentlich das selbe tuen sollte. Dabei bin
> ich allerdings bei der Dokumentation darauf gestossen, dass _delay_us
> maximal 768µs Delay zulässt.

Das stimmt nicht, lies es bitte komplett:

   Perform a delay of \c __us microseconds, using _delay_loop_1().

   The macro F_CPU is supposed to be defined to a
   constant defining the CPU clock frequency (in Hertz).

   The maximal possible delay is 768 us / F_CPU in MHz.

   If the user requests a delay greater than the maximal possible one,
   _delay_us() will automatically call _delay_ms() instead.  The user
   will not be informed about this case.
Und:

   Perform a delay of \c __ms milliseconds, using _delay_loop_2().

   The macro F_CPU is supposed to be defined to a
   constant defining the CPU clock frequency (in Hertz).

   The maximal possible delay is 262.14 ms / F_CPU in MHz.

   When the user request delay which exceed the maximum possible one,
   _delay_ms() provides a decreased resolution functionality. In this
   mode _delay_ms() will work with a resolution of 1/10 ms, providing
   delays up to 6.5535 seconds (independent from CPU frequency).  The
   user will not be informed about decreased resolution.

Oder kurz gesagt, das Maximum ist 6,5535s.


Peter

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

das mit dem Deterministisch ist eine Frage des Bezuges. Wenn man es auf 
das gesamte Programm bezieht ist deine Ausführung korrekt. Wenn ich es 
aber auf einen Schleifenzyklus beziehe ist es das nicht... schwamm 
drüber...


Wenn ich das richtig gelesen habe kann delay-us maximal ein Delay von 
768 µs und ruft dann delay_ms für alle größeren werte auf, welche aber 
nur noch auf eine zehntel millisekunde genau ist...
The maximal possible delay is 768 us / F_CPU in MHz.

Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber 
gemessen an dem basic-test-programm zu kurz...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas wrote:

> Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber
> gemessen an dem basic-test-programm zu kurz...

Deine Idee mit den beiden _delay_us ist ja nicht so schlecht.
Nur: die _delay_xx Funktionen benötigen ein konstantes Argument!

Dies liegt daran, dass die Berechnung der internen Schleifenzahl über 
Floating Point Berechnung gemacht wird. Ist das Argument eine Konstante, 
dann kann der Optimizer (darum muss der auch eingeschaltet sein) die 
komplette Berechnung aus dem Code raushalten und zur Compiletime machen. 
Im generierten Code taucht die Berechnung nicht mehr auf -> kein 
Zeitverzug durch Floating Point Berechnungen. Ist das Argument hingegen 
nicht konstant oder ist der Optimizer nicht eingeschaltet, dann wird die 
Berechnung zur Laufzeit gemacht. Und diese Berechnung hat einen 
signifikanten Einfluss auf die tatsächliche Laufzeit -> die Zeiten 
stimmen nicht mehr.

#define DELAY  833

void Delay()
{
  _delay_us( 500 );
  _delay_us( DELAY - 500 );
}

Jetzt ist das Argument konstant und von 501 bis 786+500 änderbar.

Edit: Die Grenzzeit ist ja nicht 786 sondern 768 / F_CPU

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn ich das richtig gelesen habe kann delay-us maximal ein Delay von
>768 µs

Aber nur bei 1MHz Prozessortakt. Bei 16MHz sind es dann nur noch 786/16 
= 48µs. Ist aber m.E. egal.

>Die Pulsbreite ist konstant und schwankt nicht von puls zu pusl aber
>gemessen an dem basic-test-programm zu kurz...

_delay_us(500) wird zu delay_ms(0.5), das sollte stimmen.
_delay_us(a-500) mit a=800 wird zu delay_ms(0.3), auch das sollte 
stimmen.

Allerdings verstehe ich die Frage nicht ganz, denn delay_us(800) ist 
nunmal kürzer als WAITUS 833, um "grob geschätzte" 33 us. Der Compiler 
erkennt leider trotz eingeschalteter Optimierung nicht, daß der 
Parameter von _delay_us(a-500) konstant ist, so wird der erst zur 
Laufzeit berechnet - als float, das dauert. Zusätzlich gehen gehen dann 
davon noch die Zyklen zum Aufruf des Unterprogramms ab, und jedes zweite 
mal die der while-Schleife, so daß am Ende weit weniger als 33 us 
Differenz rauskommen sollten, aber niemals 60-100us.

Very seltsam. Geht dein Scope richtig?

Oliver

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du es wirklich variabel halten musst, dann kann man auch sowas 
machen. Gegebenenfalls muss man ein klein wenig Zeit für die Rechnerei 
in der Funktion berücksichtigen.
void Delay( int a )   // Angabe in µs
{
  uint8_t i;
  uint8_t count = a / 16;
  uint8_t rest = a % 16;

  for( i = 0; i < count; ++i )
    _delay_us( 16 );

  delay_us( rest );
}

int main()
{
  Delay( 800 ); // warte 800 us
}

Aber wichtig ist: Beim Aufruf von _delay_us muss eine Konstante sein 
und der Optimizer muss eingeschaltet sein.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, also je nach Sichtweise deterministisch oder nicht :D

Aber mal ganz praktisch:
Verwende einen 16Bit Timer, z.B. Timer1, den kannst Du auf 
unterschiedliche Delays einstellen. Nimm entweder CTC oder lade den 
Timer vor mit einem Wert entsprechend des Delays. Bei 16MHz und einem 
Prescaler von 8 läuft der Timer nach maximal 32,768mS über. Für 800µS 
und bei CTC muss das OCR mit einem Wert von 1600 geladen werden, bei 
Verwendung als Overflow müsste er mit 63936 vorgeladen werden. Dann 
schreibst Du in die CTC/OVF ISR den Code rein, der die Portzustände 
(z.B. Bascom) per Read aus Data Anweisungen holt. Wenn Du 
verschwenderisch mit Speicher umgehen willst, dann ist jedes Byte ein 
Zustand. Wenn speichersparend vorzugehen ist, dann ist jedes Byte acht 
Zustände, die Du an den Portpin rausschiebst. Wenn Du eine zweite Data 
Tabelle anlegst, kannst Du darin sogar unterschiedliche Delays ablegen. 
Das Ganze ist nicht viel Code, und damit lässt sich dann viel einfacher 
arbeiten, experimentieren und auch ändern. Verändere mal auf die 
Schnelle den obigen Schlangencode, bzw. versuch die Übersicht zu 
behalten, und Du verstehst was ich meine.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab es jetzt mal in der Simulation laufen lassen.

WinAVR2009xxx, mit Optimierung -OS

High 871  us
Low 872 us

wie erwartet.  Nix mit zu kurz.

Check mal dein Scope...

Oliver

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen Dank noch einmal an alle Beteiligten und noch mal ein 
Entschuldigung von meiner Seite für die Misachtung der Forums-Regeln.

Auch ein dickes Dankeschön an Karl Heinz.

Ich habe den Code nun etwas übersichtlicher gestaltet -> siehe Post von 
Karlheinz.

Und siehe da, kaum macht man es richtig funktionierts.

Der Fehlerteufel muss im Detail gesteckt haben.
Auch die Impulslaenge stimmte auf einmal als ich meine eigenen 
warte-Methoden entsorgt hatte. Alles ist nun im Lot.

Nun geht es an das erzeugen von Initelligenz :)

Grüße
Thomas

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.