mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT89C52 - serielle übertragung


Autor: Nikolaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nickl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nickl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Nickl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...

Autor: Nickl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HELP!!! ;-)

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Nickl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, danke... mit dem hast mir sehr geholfen !! thx :-)

nickl

Autor: Schoasch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

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.