Hallo,
da ich im Netz keine ordentliche Libary zu dem MCP23S17 für avr gcc
gefunden habe, bin ich dabei, das ganze Anhand des Datenblattes
anzufertigen.
Derzeit habe ich jedoch lediglich die Konfiguration der Register sowie
Ausgänge getestet. Nun stellt sich aber eine Frage zum "verbiegen" einer
Funktion mittels Makro.
Was ich gerne hätte, wäre etwas wie dieses
1
MCP_PORT0|=1<<bit;
Ich habe vorerst ein Array in der C-File der Lib abgelegt (uint8_t
mcp[16]). Diese kann über ein Makro direkt angesprochen werden
1
#define MCP23S17_PORT0 mcp[0]
Nun wird das ganze in der main wie folgt aufgerufen
1
MCP23S17_PORT0=1<<ct;
Dieser Teil ist schon einmal so, ich mir das wünsche. Ich hätte aber
gerne die Möglichtkeit, dass sich diese "Ports" wie die in avr-gcc
verhalten. Soll heißen, die Wertesollen wenn möglich auch direkt
rausgeschiftet werden.
Wie kann ich das machen, ohne eine Funktion zu verwenden!?
Derzeit verwende ich noch
mcp23s17_write_hwaddr(uint8_t hwaddr, uint8_t reg, uint8_t data);
hwaddr = Jumpereinstellung A0 - A2
reg = GPIOA/GPIOB
data = Inhalb von mcp[]
Das geht leider nicht so, wie Du das möchtest.
Technisch gesehen handelt es sich darum, ob ein L-Wert (siehe ein
C-Buch) eine Speicher- bzw. memory-mapped-IO-Adresse identifiziert - in
die könnte einfach geschrieben werden -, oder ob ein komplexer Ablauf -
hier also die Bedienung des SPI-Interface des IO-Expanders -, ausgelöst
und kontrolliert werden muss.
Der einfach(st)e Fall ist eben der des memory-mapped-IO. So ist das
Front-End des GCC geschrieben.
Das nun ein SPI-Peripheriegerät am Bus hängt und das wiederum etwas
nachbildet, dass wie ein L-Wert behandelt werden kann, weiss der GCC
nicht und es ist auch keine Möglichkeit vorgesehen ihm das bekannt zu
machen.
Stefan S. schrieb:> Wie kann ich das machen, ohne eine Funktion zu verwenden!?
Wie Klaus schon sagte, geht das nicht.
Aber im Grunde wolltest du den Aufruf der Funktion ja nur verstecken, da
wäre die Funktion ja.(nur von dir nicht geschrieben)
Was erhoffst du dir denn davon?
Es gibt ja noch andere Ansätze...
Einmal kannst du es ja so machen wie die SPS-Maschinen, zu Beginn der
Main-Loop liest du die Inputs ein und am Ende der Main-Loop schreibst du
die Ausgänge.
Aber leider...
>Soll heißen, die Wertesollen wenn möglich auch direkt rausgeschiftet werden.
Dann kannst du den Aufruf ja noch im Macro selbst verbergen..
Eine andere Möglichkeit wäre es, wenn ich mittels Interrupt, oder in der
while Schleife nach einer bestimmten Zeit alle Werte der Ports
vergleiche und dann nur rausschicke, wenn sich etwas geändert hat.
Das mag dann zwar fast so aussehen wie die ich mir das gewünscht hab,
ist aber dann dort in meinen Augen nicht wirklich effizient.
Stefan S. schrieb:> Eine andere Möglichkeit wäre es, wenn ich mittels Interrupt, oder in der> while Schleife nach einer bestimmten Zeit alle Werte der Ports> vergleiche und dann nur rausschicke, wenn sich etwas geändert hat.
Nee...
Stephan schrieb:> Einmal kannst du es ja so machen wie die SPS-Maschinen, zu Beginn der> Main-Loop liest du die Inputs ein und am Ende der Main-Loop schreibst du> die Ausgänge.
Das halte ich für den besseren Weg.
Die SPS Hersteller sind ja nicht nur doof....
Ein seit Jahrzehnten bewährter Weg.
Stefan S. schrieb:> ist aber dann dort in meinen Augen nicht wirklich effizient.
Wie effizient muss es denn sein?
Hallo combie,
mir sind die SPS-Systeme Bernecker&Rainer, Siemens und teilweise auch
Möller/EATON aus dem Arbeitsalltag bekannt.
Das EVA-Prinzip ist bekannt.
Bei meiner Idee handelt es sich letzen Endes ebenfalls um das
EVA-Prinzip mit einer kleinen Änderung.
E - irgendwelche Sensorik, Taster etc wird eingelesen (derzeit noch
nicht mit dem MCP)
V - Bestimmte Werte im Array werden geändert oder auch nicht, je nach E.
A - Ausgabe auf die Register erfolgt nur bei einer Änderung.
Die Ausgabe erfolgt nur an die MCPs, bei denen eine Änderung erfolgte.
Andere werden ausgelassen.
Ich will dahin hinaus, dass der komplette Code nicht blockierend wird.
Da gehören dann auch Sachen wie Display etc dazu, dass sollte aber nicht
das Problem sein.
Ich hatte nur gehofft, dass es möglich wäre, es ähnlich wie mit der
Portmanipulation im AVR zu machen.
Könnte aber so vermutlich gelöst werden
1
while(1)
2
{
3
// Werte laden
4
5
// Werte verarbeiten
6
MCP|=1<<bit;
7
8
// Werte ausgeben
9
update();
10
}
Wobei update dann die Werte mit denen aus der vorherigen Runde
vergleicht. Kommt es zu Unstimmigkeiten, wird der Wert gesendet.
Stefan S. schrieb:> Ich will dahin hinaus, dass der komplette Code nicht blockierend wird.
das ist doch gut. :-D
Da geht das EVA Prinzip aber nicht.
hier brachst du was anderes, entweder eine X-Count Loop, oder über eine
Zeit-Basis(<- besser, glaub ich)
Wenn du mit den StateMaschines Hilfe brauchst, sag bescheid, wir
unterstützen dich. :-P
Stefan S. schrieb:> Ich will dahin hinaus, dass der komplette Code nicht blockierend wird.> Da gehören dann auch Sachen wie Display etc dazu, dass sollte aber nicht> das Problem sein.
Also ich mache das immer so daß ich am Anfang genau überlege welche der
Aufgaben zwingend ein deterministisches Timing erfordern bzw diese in
ihrer Priorität zu ordnen. Dabei kommt dann raus dass es etliche Sachen
gibt (die meisten bis auf ein oder 2) die dies ganz und gar nicht
erfordern und dazu gehören dann so Sachen wie LCD-Displays die ein
beknacktes Delay nach jedem Befehl brauchen oder Bitbanging-I²C master
und all das kann man ganz pragmatisch blockieren lassen und sequentiell
abarbeiten bevor man sich für nichts und wieder nichts einen Wolf
programmiert, in der main hat man alle Zeit der Welt (sobald man die
wirklich wichtigen Sachen daraus entfernt hat).
z.B:
Höchste: ADC anstossen (kann Timer-Hardware triggern)
Höchste: ADC auslesen und Werte wegschreiben (Interrupt, Prio 0)
Zweithöchste: Eingehende Bus-Pakete zur Kenntnis nehmen, keines
verschlucken (Interrupt, Prio 1)
Niedrige: (main) bei Gelegenheit mal neues Messergebnis ausrechnen
Niedrige: (main) bei Gelegenheit mal das fällige Antwortpaket
losschicken
Niedrige: (main) bei Gelegenheit mal das Display updaten
Niedrige: (main) Andere Sachen die kurz blockieren
Niedrige: (main) Schlafen