Autor |
Programm für Fahrtsteller anpassen |
|
|
|
|
BID = 841490
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
|
Hatte gerade mal wieder etwas Zeit zum Programmieren und natürlich lässt das Erste Problem nicht lange auf sich warten.
Und zwar will ich nichts weiter, als eine einfache Variablenzuweisung für die Ausgangspins des µC. Für die Eingangspins funktioniert es schon mal
Seltsamerweise gibt es bei Google eine Vielzahl von Treffern, wenn man danach sucht, aber funktioniert hat nichts so recht.
Jetzt hoffe ich, dass ihr mir weiter helfen könnt. Hier der Quellcode.
Code : |
#include <avr/io.h>
#include <avr/delay.h>
int main (void)
{
DDRB = 0xF0; //Bit7...4 Ausgänge, Bit3...0 Eingänge
PORTB = 0x00; //Alle PullUp-Widerstände aus
//Ein Taster steuert eine LED mit Variablenzuweisung an
do{
#define S1 (PINB&(1<<PINB3))
#define S2 (PINB&(1<<PINB2))
#define S3 (PINB&(1<<PINB1))
#define S4 (PINB&(1<<PINB0))
/* So (Zuweisung als Pseudocode) soll es mal aussehen
LED1 --> PB7
LED2 --> PB6
LED3 --> PB5
LED4 --> PB4
if(S1) LED1=1;
else LED1=0;
if(S2) LED2=1;
else LED2=0;
if(S3) LED3=1;
else LED3=0;
if(S4) LED4=1;
else LED4=0;
}
*/
//So sieht es bis jetzt aus, und funktioniert dafür wenigstens
if(S1) PORTB|=(1<<PB7);
else PORTB&=~(1<<PB7);
if(S2) PORTB|=(1<<PB6);
else PORTB&=~(1<<PB6);
if(S3) PORTB|=(1<<PB5);
else PORTB&=~(1<<PB5);
if(S4) PORTB|=(1<<PB4);
else PORTB&=~(1<<PB4);
}while(1);
return 1;
} |
|
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber. |
|
BID = 841493
perl Ehrenmitglied
Beiträge: 11110,1 Wohnort: Rheinbach
|
|
Zitat :
| Alle PullUp-Widerstände aus | Warum?
Die sind doch recht praktisch und erlauben es die Schalter ohne weitere Bauteile nach Masse zu legen.
Zitat :
| aber funktioniert hat nichts so recht. | Dann schau dir doch mal mit dem Simulator bzw. Disassembler den erzeugten Maschinencode an.
Du kannst ihn sogar im Einzelschritt untersuchen.
Auf diese Weise verstehst du die Arbeitsweise des Compilers und deine Fehler noch am besten.
|
|
BID = 841496
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
Zitat :
| erlauben es die Schalter ohne weitere Bauteile nach Masse zu legen.
|
Klar, ich wollte aber gegen VCC schalten. Daher wurden die internen Pullup-Widerstände deaktiviert und ein R-Netzwerk als Pulldown eingesetzt.
Zitat :
| Auf diese Weise verstehst du die Arbeitsweise des Compilers und deine Fehler noch am besten.
| Hilft mir leider nicht weiter.
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|
BID = 841498
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Zitat :
|
[...]
als eine einfache Variablenzuweisung für die Ausgangspins des µC.
|
Das kann ja nicht gehen, schließlich werden im Regelfall acht Bits an einer Adresse gemappt und können nur über die Adresse angesprochen werden (die Adresse ist bis auf wenige Ausnahmen im RAM gemappt und daher funktioniert sowas wie PORTD = 0xf5 auch erst. PORTB ist vom Typ (volatile uint8_t*).
Statt LED1 = 1 geht es aber so:
#define LED1 PORTB, PORTB5
#define LED2 PORTA, PORTA3
#define setbit(IO) __setbit(IO)
#define __setbit(PORT, BIT) PORT |= (1<<BIT)
#define clearbit(IO) __clearbit(IO)
#define __clearbit(PORT, BIT) PORT |= &= ~(1<<BIT)
Du kannst dann irgendwo im Programm schreiben:
if(Bedingung) setbit(LED1);
else clearbit(LED1);
Habe da noch andere Dinge geschrieben, die IO-Geschichten auf AVRs deutlich vereinfachen. Z.B. kann man auch sagen isoutput(LED1), dann wird im Prinzip das passende Bit im passenden DD-Register gesetzt.
Das ganze sind nur Makros, der Code wird zu sbi <PORT>, <BIT> assembliert, also optimal.
_________________
[ Diese Nachricht wurde geändert von: DonComi am 4 Aug 2012 0:16 ]
[ Diese Nachricht wurde geändert von: DonComi am 5 Aug 2012 0:11 ]
|
BID = 841583
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
Danke Don, so etwas habe ich gesucht.
Leider funktioniert es aber nicht.
Die LEDs gehen sofort nach dem Programmieren an.
Ein Betätigen der Schalter bringt keine Veränderung.
Fehlt da evtl. ein "#include < hastenichgesehen>", um diese Funktionen zu verwenden?
So sieht der Quellcode bis jetzt aus:
Code : |
#include <avr/io.h>
#include <avr/delay.h>
int main (void)
{
DDRB = 0xF0; //Bit7...4 Ausgänge, Bit3...0 Eingänge
PORTB = 0x00; //Alle PullUp-Widerstände aus
//Ein Taster steuert eine LED mit Variablenzuweisung an
do{
#define S1 (PINB&(1<<PINB3))
#define S2 (PINB&(1<<PINB2))
#define S3 (PINB&(1<<PINB1))
#define S4 (PINB&(1<<PINB0))
#define LED1 PORTB, PORTB7
#define LED2 PORTB, PORTB6
#define LED3 PORTB, PORTB5
#define LED4 PORTB, PORTB4
#define setbit(IO) __setbit(IO)
#define __setbit(PORT, BIT) PORT |= (1<<BIT)
#define clearbit(IO) __clearbit(IO)
#define __clearbit(PORT, BIT) PORT |= (1<<BIT)
if(S1) setbit(LED1);
else clearbit(LED1);
if(S2) setbit(LED2);
else clearbit(LED2);
if(S3) setbit(LED3);
else clearbit(LED3);
if(S4) setbit(LED4);
else clearbit(LED4);
}while(1);
return 1;
}
|
|
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|
BID = 841603
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Nein,
ich habe einen Fehler in clearbit().
Statt
#define __clearbit(PORT, BIT) PORT |= (1<<BIT)
muss es natürlich
#define __clearbit(PORT, BIT) PORT &= ~(1<<BIT)
sein.
Defines innerhalb von C-Code sind nicht schön,
packe am besten diese IO-Makros in einen separaten Header oder aber zumindest an den Anfang deines Programmes, macht einiges übersichtlicher.
Edit:
Zusätzliche Header sind für diese Makros nicht nötig.
Sie funktionieren prinzipiell auch mit Variablen, man könnte mit
register uint8_t val = 0x00;
setbit(val, 5);
Auch das fünfte Bit in einem Register (wie hier) oder in einer Variablen (uint8_t val) setzen.
Für IO-Ports funktioniert das deshalb zusätzlich, da diese im unteren Speicherbereich gemappt sind und der Zugriff transparent geschieht.
Der Compiler merkt, dass der Adressbereich zu IO-Registern gehört und nutzt dafür dann die entsprechenden Instruktionen sbi und cbi. Damit umgeht man ein read-modify-write, also sowohl Platz als auch Geschwindigkeit.
sbi/cbi funktionieren nur bis zu einer gewissen Adressgrenze, darüber muss man dann tatsächlich mit Read-Modify-Write arbeiten, wie ja auch die Anweisung PORT |= 1<<4 <==> PORT = PORT | 0x10; schon vermuten lässt.
_________________
[ Diese Nachricht wurde geändert von: DonComi am 5 Aug 2012 0:09 ]
|
BID = 841612
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
Noch mal einen RIESEN Dank an dich, jetzt funktioniert es, wie es soll
Zitat :
| muss es natürlich
#define __clearbit(PORT, BIT) PORT &= ~(1<<BIT)
sein. |
Jetzt wo du´s sagst, fällt es mir auch auf...
Und so sieht es aus - Für alle, die ein ähnliches/das gleiche Problem haben.
Code : |
#include <avr/io.h>
#include <avr/delay.h> //Wird für einen anderen Programmteil verwendet, dieses hier ist die gekürzte Variante
#define S1 (PINB&(1<<PINB3))
#define S2 (PINB&(1<<PINB2))
#define S3 (PINB&(1<<PINB1))
#define S4 (PINB&(1<<PINB0))
#define LED1 PORTB, PORTB7
#define LED2 PORTB, PORTB6
#define LED3 PORTB, PORTB5
#define LED4 PORTB, PORTB4
#define setbit(IO) __setbit(IO)
#define __setbit(PORT, BIT) PORT |= (1<<BIT)
#define clearbit(IO) __clearbit(IO)
#define __clearbit(PORT, BIT) PORT &=~ (1<<BIT)
int main (void)
{
DDRB = 0xF0; //Bit7...4 Ausgänge, Bit3...0 Eingänge
PORTB = 0x00; //Alle PullUp-Widerstände aus
//Ein Taster steuert eine LED mit Variablenzuweisung an
do {
//Direkte Zuweisung
if(S1) setbit(LED1);
else clearbit(LED1);
if(S2) setbit(LED2);
else clearbit(LED2);
if(S3) setbit(LED3);
else clearbit(LED3);
if(S4) setbit(LED4);
else clearbit(LED4);
/*
//Zuweisung über logische Verknüpfungen
if(S1&&S2) setbit(LED1); // AND
else clearbit(LED1);
if(!(S2&&S3)) setbit(LED2); // NAND
else clearbit(LED2);
if(S3||S4) setbit(LED3); // OR
else clearbit(LED3);
if(!(S4||S1)) setbit(LED4); // NOR
else clearbit(LED4);
*/
}while(1);
return 1;
} |
|
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|
BID = 846665
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
...ich mal einfach mal hier mit einem weiteren kleinen Problemchen weiter.
Diesmal geht es ums Entprellen ....jaja ich weiß, dieses Thema wurde schon in tausend Foren durchgekaut, würde aber dennoch gerne wissen, wo der Fehler liegt.
Verwendet habe ich diesen Code (von hier)
Allerdings bringt mein Compiler (AVR Studio 4.19) die Fehlermeldung
expected identifier or '(' before '{' token
in
Zitat :
|
#define debounce( port, pin )
Dieser Zeile ({
static uint8_t flag = 0;
|
Daher die Frage an die Experten: Was ist da los?
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|
BID = 846716
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Kannst du den Quellcode mal als C-Datei posten?
So kann ich damit nichts anfangen.
Wenn Defines über mehr Zeilen gehen sollen, dann __muss__ jede Zeile mit einem Backslash abgeschlossen werden.
Ansonsten noch mal gucken, ob das Makro auch richtig aufgerufen wird.
_________________
|
BID = 846729
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
Zitat :
| Kannst du den Quellcode mal als C-Datei posten? |
Den hatte ich doch verlinkt.
Zitat :
| Ansonsten noch mal gucken, ob das Makro auch richtig aufgerufen wird. |
Wenn du mir noch verrätst wie, gerne.
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|
BID = 846736
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Also ich kann den Source direkt und fehlerfrei übersetzen.
Im Allgemeinen ist von solchen Konstruktionen (mit Makros) abzuraten. Das ist nicht schön.
Mein Compileraufruf:
avr-gcc -mmcu=attiny2313 -Os -o debounce debounce.c
_________________
|
BID = 846788
Offroad GTI Urgestein
Beiträge: 12742 Wohnort: Cottbus
|
Zitat :
| Also ich kann den Source direkt und fehlerfrei übersetzen. |
Nachdem ich ein neues Projekt angelegt hatte, klappt es bei mir jetzt auch.
Nur die 98µs Verzögerungszeit waren viel zu lang (für ein Senoiren-Telefon wahrscheinlich gerade richtig )
Habe sie jetzt soweit runter gesetzt, dass auch relativ schnell (~4Hz) getastet werden kann.
_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.
|