Forum: Mikrocontroller und Digitale Elektronik Delay beim HC12 einbauen? In C. Für LED-Blinken!


von J. R. (cia_man)


Lesenswert?

Hallo

Ich möchte wie oben beschrieben ein delay von 0.5 s einbauen in mein 
Programm!

Programm:

#include <stdio.h>

#include <mc912d128.h>



void main(void) {


  DDRH ^= 0x80;






  DDRH |=0x80;

  while(1){
  }
}


Ihr seht ich möchte einfach die LED im 0,5 s Zyklus ab und anschalten!

Gibt es dafür einen direkten Befehl beim MC912DG128A??? So etwas wie 
delay... ??? Ich programmiere in ICC12 mit C!


THX!

von Lehrmann M. (ubimbo)


Lesenswert?

Jochen R. schrieb:
> Ihr seht ich möchte einfach die LED im 0,5 s Zyklus ab und anschalten!

Dann sollte der Code + Delay aber in die Endlosschleife. Ansonsten 
blinkt's nur einmal.

Schau mal im Handbuch nach. Heißt meistens delay.h oder delays.h

von J. R. (cia_man)


Lesenswert?

Lehrmann Michael schrieb:
> Jochen R. schrieb:
>> Ihr seht ich möchte einfach die LED im 0,5 s Zyklus ab und anschalten!
>
> Dann sollte der Code + Delay aber in die Endlosschleife. Ansonsten
> blinkt's nur einmal.
>
> Schau mal im Handbuch nach. Heißt meistens delay.h oder delays.h

Ja des delay fehlt ja oben eben noch! :)

Darum frage ich ja ;)

von J. R. (cia_man)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich muss jetzt doch mal blöd fragen... das ist doch das Handbuch was ihr 
immer meint oder? Weil da steht nix von delay.h bzw delays.h drinnen :)

THX!!!

von Justus S. (jussa)


Lesenswert?

Jochen R. schrieb:

> Ich muss jetzt doch mal blöd fragen... das ist doch das Handbuch was ihr
> immer meint oder?

nein, dass zu deinem Compiler...

von Timmo H. (masterfx)


Lesenswert?

Ich glaube der ICC hat kein Delay oder so eingebaut. Du könntest dich 
mal mit dem Timer beschäftigen, sodass er z.B. jede Millisekunde einen 
Interrupt generiert und darin eine Variable hochzählt welche du dann 
überprüfst ob diese schon größer-gleich 500 ist.

Du kannst dir natürlich auch erstmal eine wait-Funktion über eine 
While-Schleife machen.
Ich glaube das funktionierte ganz gut bei mir:
1
void delay1ms(void) {
2
  asm("ldy #2400");
3
  asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
4
}
5
6
7
void wait(int duration)
8
{
9
  while(duration--)
10
  delay1ms();
11
}

Wenigstens kann ich dir bei jeder deiner Frage helfen. Besonders viele 
arbeiten hier nämlich nicht mit HC12 (ich auch nicht mehr, hatte aber 
mal ein größeres Projekt)

von J. R. (cia_man)


Lesenswert?

Timmo H. schrieb:
> Ich glaube der ICC hat kein Delay oder so eingebaut. Du könntest dich
> mal mit dem Timer beschäftigen, sodass er z.B. jede Millisekunde einen
> Interrupt generiert und darin eine Variable hochzählt welche du dann
> überprüfst ob diese schon größer-gleich 500 ist.
>
> Du kannst dir natürlich auch erstmal eine wait-Funktion über eine
> While-Schleife machen.
> Ich glaube das funktionierte ganz gut bei mir:
>
1
> void delay1ms(void) {
2
>   asm("ldy #2400");
3
>   asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
4
> }
5
> 
6
> 
7
> void wait(int duration)
8
> {
9
>   while(duration--)
10
>   delay1ms();
11
> }
12
>
>
> Wenigstens kann ich dir bei jeder deiner Frage helfen. Besonders viele
> arbeiten hier nämlich nicht mit HC12 (ich auch nicht mehr, hatte aber
> mal ein größeres Projekt)

Jo leider :( Aber naja mal schauen... wenigstens kannst du mir ja ab und 
an ein paar Tipps geben!  Ich werde mir jetzt mal das Buch Embedded 
Microcomputer Systems (Real Time Interfacing)
- by Jonathan W. Valvano

    * (This book uses the ImageCraft ICC12 compiler extensively in its 
examples! :-) )

besorgen! Weiß nicht ob du das kennst? Hoffe mal damit kann ich dann 
etwas mehr meine Wissenslücken stopfen! ;)


Und danke natürlich nochmal für deine Tipps!!! ;)

von J. R. (cia_man)


Lesenswert?

Kannst du mir bitte die einzelnen Zeilen des Programms noch etwas 
erklären?

void delay1ms(void) {
  asm("ldy #2400");
  asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
}


void wait(int duration)
{
  while(duration--)
  delay1ms();
}


Wäre gut!! ;)

THX!!!

von Timmo H. (masterfx)


Lesenswert?

Alles innerhalb von asm(...) sind assembler Befehle, also Maschinencode. 
Im Datenblatt steht wie lange der µC für das Ausführen der Befehle 
braucht (siehe Kommentar) und diese beiden Befehle mit dem 
entsprechenden Zahlenwert (2400) brauchen eben 0,994ms (bei 8 MHz). 
Eigentlich wird halt nur der Zahlenwert "2400" in ein Register (ldy 
#2400) geschrieben und solange dekrementiert bis dieser 0 ist (dbne = 
Decrement Branch Not Equal to Zero )
Diese Schleife kannst du dann über wait(100) aufrufen um also 100 mal 
diese Schleife zu durchlaufen = 994 ms

von J. R. (cia_man)


Lesenswert?

Timmo H. schrieb:
> Alles innerhalb von asm(...) sind assembler Befehle, also Maschinencode.
> Im Datenblatt steht wie lange der µC für das Ausführen der Befehle
> braucht (siehe Kommentar) und diese beiden Befehle mit dem
> entsprechenden Zahlenwert (2400) brauchen eben 0,994ms (bei 8 MHz).
> Eigentlich wird halt nur der Zahlenwert "2400" in ein Register (ldy
> #2400) geschrieben und solange dekrementiert bis dieser 0 ist (dbne =
> Decrement Branch Not Equal )
> Diese Schleife kannst du dann über wait(100) aufrufen um also 100 mal
> diese Schleife zu durchlaufen = 994 ms

Ist dieser Zahlenwert dann eine Hex-Zahl? Und bedeutet "dbne y,." also 
der . um 1 erniedrigen???

Und wait(100) schreibe ich dann ganz ans Ende oder?

THX!!! ;) das hilft mir wirklich ungemein!!!

von Timmo H. (masterfx)


Lesenswert?

Jochen R. schrieb:
> Ist dieser Zahlenwert dann eine Hex-Zahl? Und bedeutet "dbne y,." also
> der . um 1 erniedrigen???
Nein, schau auch mal ins Reference manual: CPU12RM.pdf

#2400 ist eine dezimalzahl die mit ldy in das Y-Register geladen wird.
Mit dbne y,. wird das Y-Register dekrementiert und solange es ungleich 0 
ist wird auf "." (also die gleiche Adresse wie der Befehl selbst 
gesprungen (ähnlich wie while(i--);)

Das wait verwendest du dann in der Main, also z.B.
1
void delay1ms(void) {
2
  asm("ldy #2400");
3
  asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
4
}
5
6
7
void wait(int duration)
8
{
9
  while(duration--)
10
  delay1ms();
11
}
12
13
int main(){
14
15
16
  DDRH |=0x80; // als Ausgang setzen
17
18
  while(1){
19
    PTH ^= 0x80; // 1=>0 bzw. 0=>1
20
    wait(100);   //100ms warten
21
  }
22
}

von J. R. (cia_man)


Lesenswert?

Timmo H. schrieb:
> Jochen R. schrieb:
>> Ist dieser Zahlenwert dann eine Hex-Zahl? Und bedeutet "dbne y,." also
>> der . um 1 erniedrigen???
> Nein, schau auch mal ins Reference manual: CPU12RM.pdf
>
> #2400 ist eine dezimalzahl die mit ldy in das Y-Register geladen wird.
> Mit dbne y,. wird das Y-Register dekrementiert und solange es ungleich 0
> ist wird auf "." (also die gleiche Adresse wie der Befehl selbst
> gesprungen (ähnlich wie while(i--);)
>
> Das wait verwendest du dann in der Main, also z.B.
>
> [c]
> void delay1ms(void) {
>   asm("ldy #2400");
>   asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
> }
>
>
> void wait(int duration)
> {
>   while(duration--)
>   delay1ms();
> }
>
> int main(){
>
>
>   DDRH |=0x80; // als Ausgang setzen
>
>   while(1){
>     PTH ^= 0x80; // 1=>0 bzw. 0=>1
>     wait(100);   //100ms warten
>   }
> }

Okay!

Und warum blinkt es bei mir mit folgendem Code nur 1mal?

#include <stdio.h>

#include <mc912d128.h>


void delay1ms(void) {
  asm("ldy #2400");
  asm("dbne y,.");  // 3cyc x 135ns x 2400 = 0,994ms
}


void wait(int duration)
{
  while(duration--)
  delay1ms();
}



void main(void) {


  DDRH ^= 0x80;


 wait(1000);



  DDRH |=0x80;

  while(1){
  }
}


THX!!!!!!

von APW (Gast)


Lesenswert?

Da ist ein kleiner Rechenfehler drin.
HC12 bei 8MHz Busclock = 125 ns Cycle.
1ms Verzögerung sind dann 8000 Buscycles, die man verbrennen muss.
dbne... braucht 3 Cycles -> 8000/3=2666
also:

  asm("ldy #2600"); //2600 in Y-Register laden
  asm("dbne y,.");  // Decrement, bis Y=0 ist /
                    //3cyc x 125ns x 2666 = 0,99975ms

(dabei ist zu hoffen, dass der icc das y Register sichert.)

von Heike L. (Gast)


Lesenswert?

Eventuell deswegen?

while(1){
  }

von Timmo H. (masterfx)


Lesenswert?

Jochen R. schrieb:

> Okay!
>
> Und warum blinkt es bei mir mit folgendem Code nur 1mal?

>   while(1){
>   }
Weil du da auf der Stelle stehen bleibst. Mit while(1) bleibst du dort 
stehen, aber du willst ja quasi unendlich lange blinken lassen also 
müssen deine Befehle IN die While-Schleife.
Übrigens wie schon bei deinem letzen Post geschrieben solltest du den 
Port mit PTH ^= 0x80 setzen und nicht das DDR-Register dazu verwenden. 
Damit schaltest du dann ständig zwischen Tristate und Ausgang mit 0 hin 
und her.

von APW (Gast)


Lesenswert?

So:

void main(void) {

  DDRH |=0x80;  // Auf Ausgang schalten

  while(1)
  { PORTH ^= 0x80;  //Am Portpin wackeln
    wait(1000);
  }
}

von APW (Gast)


Lesenswert?

Kann sein dass icc das PTH statt PORTH nennt.

von APW (Gast)


Lesenswert?

Muss mich mal registrieren, dass ich meinen Sch.. korrigieren kann.
Das oben soll natürlich

  asm("ldy #2666"); //2666 in Y-Register laden
  asm("dbne y,.");  // Decrement, bis Y=0 ist /
                    //3cyc x 125ns x 2666 = 0,99975ms

heißen.

von J. R. (cia_man)


Lesenswert?

APW schrieb:
> Muss mich mal registrieren, dass ich meinen Sch.. korrigieren kann.
> Das oben soll natürlich
>
>   asm("ldy #2666"); //2666 in Y-Register laden
>   asm("dbne y,.");  // Decrement, bis Y=0 ist /
>                     //3cyc x 125ns x 2666 = 0,99975ms
>
> heißen.

So jetzt nochmal den vollen Code! Mit Verbesserungen! ;)

#include <stdio.h>

#include <mc912d128.h>


void delay1ms(void) {
  asm("ldy #2666"); //2666 in Y-Register laden
  asm("dbne y,.");  // Decrement, bis Y=0 ist /
          //3cyc x 125ns x 2666 = 0,99975ms
}


void wait(int duration)
{
  while(duration--)
  delay1ms();
}



void main(void) {


  DDRH |= 0x80;




  while(1){

  PORTH ^=0x80;
  wait(1000);

  }
}

Geht einwandfrei!!! Und ich habs endlich mal verstanden!!! Die 
while-Schleife läuft also so lange bis 0 eintritt! :)

Was bei der 2ten mit 1 nie passiert... darum blinkt es durch....

freu

THX!!!!

von Timmo H. (masterfx)


Lesenswert?

APW schrieb:
> Da ist ein kleiner Rechenfehler drin.
> HC12 bei 8MHz Busclock = 125 ns Cycle.
> 1ms Verzögerung sind dann 8000 Buscycles, die man verbrennen muss.
> dbne... braucht 3 Cycles -> 8000/3=2666
> also:
Ja stimmt, ich hatte damals nen Baudratenquarz drin 7,3728 MHz, darum 
weichen die etwas ab.

von APW (Gast)


Lesenswert?

Der Lerneffekt ist groß, wenn du mal solche einfachen Sachen Schritt für 
Schritt im Debugger auf Assemblerebene ausführst.
Gelegentliche Blicke ins Listingfile sind auch hilfreich, da sieht man, 
was der Compiler aus dem C-Quellcode macht.

von J. R. (cia_man)


Lesenswert?

APW schrieb:
> Der Lerneffekt ist groß, wenn du mal solche einfachen Sachen Schritt für
> Schritt im Debugger auf Assemblerebene ausführst.
> Gelegentliche Blicke ins Listingfile sind auch hilfreich, da sieht man,
> was der Compiler aus dem C-Quellcode macht.

Was nehme ich dann für das Debuggen auf Assemblerebene für ein 
Programm?? Am besten ein kostenloses! ;)

THX!!!

von Timmo H. (masterfx)


Lesenswert?

Für ICC12 gibt den NoICE 12-Debugger (weiß gar nicht mehr ob der dabei 
ist)

von APW (Gast)


Lesenswert?

Hast du überhaupt einen BDM-Debugger?

von APW (Gast)


Lesenswert?

Ich hab bis jetzt auf 2 Wegen HC(S) 12 programmiert:
1) ICC12 Comiler + StarProg zum Brennen über ComPod12 + NoIce Debugger
2) Freescale CodeWarrior + USBMultilinkBDM

wobei 2) fast nur Vorteile hat (auch finanziell) und du auch ohne 
Mehrkosten HCS08 programmieren kannst.

von J. R. (cia_man)


Lesenswert?

APW schrieb:
> Hast du überhaupt einen BDM-Debugger?

Ja! Hab ich!

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.