Hallo miteinander,
ich bin ein absoluter Anfänger, was die Mikrocontroller angeht.
Ich habe einen AtMega162 bei dem mit 8 Pins frei zur Verfügung stehen,
die PA0 bis PA7.
Mein Problem:
Wie kriege ich das hin, dass ich beim Zustandswechsel, zum Beispiel am
PA0 (von low auf high und dann von high auf low) eine Botschaft über
UART1 rauschicken kann?
Vielen Dank im Voraus.
Grüsse
Hemi
PORTA als Eingang konfigurieren
UART1 als Sender konfigurieren
Endlosschleife:
PINA abfragen
auf Zustandswechselabfragen
in die gewünschte Form umwandlen
und per UART1 verschicken.
Wie das Abfragen konkret einzurichten ist, hängt einmal davon ab, wie
schnell sich die Werte an PORTA ändern. Hast du da eine Vorstellung wie
schnell/langsam das passiert?
Und zum zweiten wie sicher der Zustandswechsel ist, d.h. ob Prelleffekte
vorkommen und eine Entprellung nötig ist. Bei Tastern sollte man immer
mit Prellen rechnen. Wenn saubere Digitalsignale anliegen, eher nicht.
Das Senden hängt vom Datenaufkommen ab. Wenn zeitweise viel zu senden
ist, lohnt es sich das Senden mit Interrupts und Puffern zu machen. Im
Extremfall trennt man in eine Messzeit und eine Sendezeit und benutzt
soviel Puffer wie das RAM hergibt. Dann hat man quasi einen
Logikanalysator. Tja und das haben schon andere entwickelt - schau in
die Codesammlung.
Also das ist so eine Art Schalter.
Erklärung: Das Gerät ist dazu da um etwas ein- und auszuschalten, in dem
es eine Botschaft schickt. Das Gerät hat eine eigene Stromversorgung.
Wenn man die Zündung anmacht, liegt am PA0 eine Spannung von +12V an.
Wenn es passiert ist, muss eine Botschaft rausgeschickt werden. Wenn die
Zündung wieder ausgemacht wird, liegen am PA0 0V an. Wenn es passiert,
wird eine andere Botschaft rausgeschickt.
Mehr macht das Ding nicht.
Kann man das evtl. in einem Interrupt realisieren, weil das
Hauptprogramm schon ziemlich viel macht.
Danke & Grüsse
Hemi
Ich hoffe die +12V liegen nicht direkt an PA0 an, denn dann haben die
armen Schutzdioden viel zu tun, um die zu hohe Spannung vom µC
fernzuhalten.
Es hat Vorteile, einen Hauptteil in einem Interrupt (oder Timer) zu
programmieren. Du erhälst eine Nebenläufigkeit zum Hauptcode. Vom Platz
her sprst du aber eher nichts. Und das langwierige Senden innerhalb des
Interrupts wird als schlechter Stil betrachtet. Ändern von vorhandenem
Interruptcode kann dazu führen, dass der Rest des Programmes soweit
blockiert wird, dass Funktionsfehler auftreten.
Eine Älternative insbesondere ohne Quellcode bzw. ohne Eingriff in
denselben wäre, mit einem zweiten (schwachbrüstigen und preiswerten) µC
an der 12V Leitung zu spionieren und den eigentlichen AVR komplett in
Ruhe zu lassen. Wie man die Botschaft dann auf die Sendeleitung gibt,
hängt vom Rest des Gerätes ab.
Ah, es geht um die BMW/MK4/Alextronic Geschichte. Ich hatte schon
Bedenken, als du was von externem Gerät, Fernsteuern und Zündung
geschrieben hast.
Die 12V würde ich mindestens mit einem Spannungsteiler runtersetzen
auf die Betriebsspannung des AVR. Und da das Ganze an einem KFZ
installiert wird, muss man damit rechnen, dass 12V ein nomineller Wert
ist. Die tatsächliche Spannung kann beträchtlich davon abweichen. Eine
Strombegrenzung (Sicherung) ist auch eine Überlegung wert.
Ideen zur Pegelanpassung gibt es bei Alextronic:
http://www.alextronic.de/bmw/projects_bmw_info_ibus.html#_2
Alles zusammen betrachtet, würde ich eine galvanische Trennung
bevorzugen und das über einen Optokoppler (Vorwiderstand nicht
vergessen!) lösen. Wenn das zu lahm ist, dann einen professionellen
Pegelwandler IC benutzen (Melexis TH8080 LIN-Transceiver laut
Alextronic).
Das Codestück sieht vernünftig aus. Den internen Pullup würde ich
weglassen. Was soll der hochziehen, da sehe ich im Moment nichts. Und
ich würde einer statischen oder globalen Variablen festhalten, ob die
mk4_startup_msg bzw. mk4_shutdown_msg bereits gesendet wurden. Oder
stört das den Empfänger nicht, wenn diese Nachricht öfters kommt?
Ja, genau, es handelt sich um ein MK4-Projekt.
Die Hardware ist ein AtMega162 mit zwei TH3122 LIN Transceiver. Also
bustechnisch ist alles okay und da brauche ich nichts mehr.
Auf der Platine habe ich noch 8 Ein- / Ausgänge, die ich beliebig
verwenden kann und einen daon wollte ich zum Hoch- und Runterfahren
verwenden. Was Elektronik und Mikrocontroller angeht, bin ich ein
Anfänger. Kann nur C/C++ und tralala. Aber nichts mit der Hardware.
Die Variable werde ich natürlich auch verwenden, es stört zwar nicht,
wenn die Botschaft mehrmals kommt, aber es muss nicht sein.
Hier leicht modifizierter Code:
1
intmain(void)
2
{
3
4
boolswitched_on=false;
5
6
uart0_init(9600);
7
uart1_init(9600);
8
9
// Setzen der Einstellungen am Port 0:
10
11
DDRA&=~(1<<PA0);// PIN PA0 als Eingang definieren
12
13
// Prüfen ob PA0 high ist, wenn ja, MK4 hochfahren:
14
15
16
while(1)
17
{
18
if((PINA&(1<<PINA0))&(switched_on==false))
19
{
20
uart1_sendibus_EEP(mk4_startup_msg);
21
switched_on=true;
22
}
23
24
// Prüfen ob PA0 low ist, wenn ja, MK4 runterfahren:
25
26
if((!(PINA&(1<<PINA0)))&(switched_on==true))
27
{
28
uart1_sendibus_EEP(mk4_shutdown_msg);
29
switched_on=false;
30
}
31
}
32
return0;
33
}
Das mit Spannungsteiler sind gut aus, so werde ich es machen. Kannst Du
mir sagen, auf wieviel Volt ich runter muss? Sind es diese 2,7V bis
5,5V?
Grüsse
Hemi
Im Datenblatt vom ATmega162 steht ab wo bis wohin LOW und HIGH
garantiert erkannt werden. Der Spannungsteiler muss so dimensioniert
werden, dass die HIGH/LOW Bereiche darin abgebildet werden.
AVR (typ.)
Vin HIGH [V] 0,7*Vcc ... Vcc+0,5
Vin LOW [V] -0,5 ... 0,3*Vcc
IBUS
1 U high [V] 7 V ... Ubatt
2 U low [V] 0 V ... 2 V
Angenommen der AVR läuft mit Vcc 5V, dann sind die Untergrenze Vin HIGH
3,5V und die Obergrenze Vin LOW 1,5V. Sieht nach einer einfachen
Halbierung der IBUS-Spannung mit zwei gleichen Widerständen aus.
Das Problem ist die maximale Eingangsspannung Ubatt. Da muss stärker
reduziert werden (12V => max. 5,5V => Faktor X). Dadurch verschiebt sich
aber 7V/X unter die 0,7*Vcc Bedingung von Vin HIGH. Das kann erkannt
werden, wenn der AVR etwas toleranter ist oder wenn auf dem IBUS ein
High-Pegel >7V (7,7V) liegt.
Jetzt könnte es sein, dass du daran denkst nicht mit einem IBUS Signal
auf PA0 zu gehen sondern z.B. mit einem analogen "Zündung ein" Signal
vom Zündschloss. Dann mach dir unbedingt Gedanken um die
Strombegrenzung, Bedenke den Fall Ubatt >>12V und es sind Störspitzen
auf der Leitung und überlege, ob ein Optokoppler nicht die bessere
Lösung wäre.
Die IBus Transceiver hängen direkt an den UARTs, die haben gar nichts
mit den PA0-7 zu tun.
Die Botschaften werden ja über einen der beiden TH3122 Transceiver
verschickt und empfangen.
Das, was ich will, ist einfach nur den Zustandswechsel mitzukriegen,
wenn die Zündung an ist. Also genau das, was Du im letzten Abschnitt
beschrieben hast. Der Optokoppler scheint wohl die bessere Alternative
zu sein.
Grüsse
Hemi