Forum: Mikrocontroller und Digitale Elektronik AT89C52 - serielle übertragung


von Nikolaus (Gast)


Lesenswert?

Hi!
Ich hätt eine Frage,

Wie mach ich das am besten, wenn am µP ein Programm laufen soll, dass
ich nur, wenn nötig, über die Serielle-Schnittestlle waren will...
Genauer handelt es sich um eine Heizungssteuerung die selbständig
laufen soll, nur dass ich über die Serielle den aktuellekn Status
abrufen und die Temperaturgrenzwerte verändern kann...

Irgendwie bekomm ich das mitn seriellen Interrupt nicht ganz hin...

kann mir jemand helfen ?


lg Niklas

von Jochen (Gast)


Lesenswert?

Wo ist Dein Problem?

Im Interrupt den seriellen Puffer füllen und im Hauptprogramm
abarbeiten.
Oder aber zwei Interruptlevel und das Ganze vernünftig aufteilen.

Schreib mal, wo genau Dein Problem liegt.

von Nickl (Gast)


Lesenswert?

Tjo... das ist so... sobald ich die interrupt routine schreibe, meldet
mir erstens der linker eine warngung, die da sagt:
MULTIBLE CALLER TO SEGMENT....
SEGMENT: PRINTF....

kA warum.... er übersetz den code zwar, aber er geht mir nicht in die
routine hinein, wenn ich ein zeichen sende... ich glab, ich bin zu
blöd...

lg niki, vl. hatt jemand ein beispiel programm für mich ?! thx.

von Peter Dannegger (Gast)


Lesenswert?

printf() ruft man tunlichst nicht ausm Interrupt auf.
Ehe das so aus die Puschen kommt, sind schon tonnenweise andere
Interrupts verloren gegangen.
Und erst recht, wenn man es ungepuffert auf die UART schreiben läßt.


Der C51-Compiler ist dahingehend optimiert, daß Funktionen nicht
reentrant sind. Das müßten sie aber sein, wenn man sie von 2
verschiedenen Ausführungsleveln aufruft.

Ich weiß jetzt nicht, ob von printf() auch eine reentrante Version
gelinkt werden kann.
Aber wie gesagt, sowas macht ja normalerweise auch keiner.


Peter

von Peter D. (peda)


Lesenswert?

P.S.:
Ich sach mal, von printf() gibt es keine reentrante Version.

Es mag mancher zwar lustig finden, wenn mittendrinn in einem Text vom
Main plötzlich ein Text vom Interrupt erscheint (vielleicht noch die
Zeichen gemischt), aber sowas hätte keinerlei praktischen Wert.

printf() darf daher immer nur einmal zur Zeit ausgeführt werden.


Peter

von Jochen (Gast)


Lesenswert?

@Nik:

Schreib doch Deine eigene printf-Routine. Die vielen Optionen brauchst
Du eh nicht, das ist Platz- und Performanceverschwendung (und somit
unnötiger Stromverbrauch).

Schreib Dir interrupt-gesteuerte Routinen für den Empfang und das
Senden von der seriellen Schnittstelle und mach Dir einen einen Puffer,
der zur Not ein paar Zeichen aufnehmen kann.
Wenn dann ein Zeichen gekommen ist, dann setz ein Flag und werte das im
Hauptprogramm aus. Sobald dann ein Befehl erkannt wurde (z.B. Temperatur
ändern oder Status abfragen), führe die entsprechende Aktion durch.

Poste doch mal die Ausschnitte aus Deinem Programm hier.

von Nickl (Gast)


Lesenswert?

@ Jochn.... ja, im Prinzip sollte nocht viel dahinterstecken,
Was ich einfach möchjte Währe, dass wenn ein bestimmtest Zeichen
erhaöten wird, ich in ein Menüinterface komme, wo ich  mit die aktuelle
Temperatur anschauen kann, die Hysterese verändern (num) und die Heizung
manuell ein- od. ausschalten kann.
Das ist natürlich nur der Prototyp des Programmen, es kommen dann noch
Stellventil, Aussentemperatur und 2 Pumpen dazu....


hier mal ein Teil des Sources

#include <AT89X52.H>
#include <stdio.h>


#ifndef READ
    #define READ   1
#endif

#ifndef WRITE
    #define WRITE  0
#endif

#ifndef I2CCLK
    #define I2CCLK 0xA0
#endif

#ifndef SCL
  #define SCL P1_6
#endif

#ifndef SDA
  #define SDA P1_7
#endif

unsigned char _i2c_error;      // bit array of error types

void          _I2CBitDly(void);
void          _I2CSCLHigh(void);
void           I2CSendAddr(unsigned char addr, unsigned char rd);
void           I2CSendByte(unsigned char bt);
int        _I2CGetByte(unsigned char lastone);
void           I2CSendStop(void);


#define I2CGetByte()     _I2CGetByte(0)
#define I2CGetLastByte() _I2CGetByte(1)




#define XTAL 11.0592  // Quarzfrequenz in MHz
#define BAUD 9600    // Baudrate

int b,c,kom,v,num=20,nume=0,q=1;
char ch;

main()
{
  const unsigned int RCAP2 = 0x10000-XTAL*1e6/(32.0*BAUD);  //
Rückladewert timer-2



  TMOD = 0x20;
  TH1 = 0xfd;
  TR1 = 1;
  SCON = 0x5a;


  REN = 1;    // Empfänger freischalten
  TI = 1;    // Senden des 1. Zeichens ermöglichen



  while(getchar() != 'x');
  P1=255;      //Port1 zum Empfangen bereit
  P1_4=0;
  P1_5=0;    //Relais ausschalten
  while(1){


    I2CSendAddr(0x90,WRITE);
    I2CSendByte(0);
    I2CSendStop();
    I2CSendAddr(0x90,READ);
    b = I2CGetByte();
    c = I2CGetLastByte();
    I2CSendStop();

/*
b... 00000000  temperatur im 2er-Komplement
   ^....Vorzeichen (0-positiv, 1-negativ)

c... 00000000
   ^....Wenn 1 dann b += 0.5°C

0x90... 10010000
    ^^^^     .... Adresse des Bausteinhersteller
      ^^^  .... Adresse die am Baustein gesetzt werden kann
         ^ .... Lesen/Schreiben ( wird durch WRITE od. READ gesetz)
*/



  printf("\nmesse...\n");    //koninuierliche Statusmeldung


  if (c>=128)    //auf .5 Werte überprüfen
    kom=1;
  else
    kom=0;
  v=0;


  //---- Hysterese ----    Einschalten bei 2°C unter Sollwert,
ausschalten bei 2°C über Sollwert


  if (b<(num-2))    //Wenn Ist-Wert 2°C  kleiner als Soll-Wert -> 
Heizung
ein
    P1_4=1;

  if (b>(num+2))
    P1_4=0;        //Wenn Ist-Wert 2°C größer als Soll-Wert -> Heizung 
aus

von Nickl (Gast)


Lesenswert?

...

von Nickl (Gast)


Lesenswert?

HELP!!! ;-)

von Schoasch (Gast)


Lesenswert?

Hi!
Wir ham erst mal vor kurzem mit dem AT89C52 mal gearbeitet und auch
UART benutzt. vl bringt dir das was (ist nur die interruptroutine).

void serial_IT(void) interrupt 4
{
  if (RI == 1)
  {   /* if reception occur  */
    RI = 0;
    uart_data = SBUF;   /* Read receive data  */
    SBUF = uart_data;
    uart_flag = 1; /* Send back same data on uart*/
   }
   else TI = 0; /* if emission occur */
/* clear emission flag for next emission*/
}

Hier empfängt der µC daten und schickt diese gleich wieder retour.

von Nickl (Gast)


Lesenswert?

Super, danke... mit dem hast mir sehr geholfen !! thx :-)

nickl

von Schoasch (Gast)


Lesenswert?

achja... :-)

ein hinweis: auf der Homepage der Firma Atmel findest du beispiele
dafür wie du UART und alles mögliche andere Benuzt, mit beispielen!
von da habe ich auch diesen Code ;-) denn es gibt ja eben nicht nur
einen UART mode ;-)

Hat es so funktioniert?

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.