Autor |
PIC und C Amfängerfrage Suche nach: pic (2056) |
|
|
|
|
BID = 485813
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
|
Moin,
Da ich keine Ahnung von Microchips Datenblättern habe, kann ich deine Frage nicht beantworten.
Aber es ist ja i.d.R. auch nicht festgelegt, wie du bestimmte Sachen anzuschließen hast; z.b. ob ein Taster jetzt eine 1 oder eine 0 liefert, wenn er gedrückt wird.
Das muss dann im Programm dementsprechend vorgesehen werden.
_________________
|
|
BID = 485837
Herrminator Gelegenheitsposter
Beiträge: 87
|
|
Klar ja da hast du recht. Nur irgendwo muss man ja finden wie man jetzt zum Beispiel ein Eingang invertiert... Hab einiges probiert. |
|
BID = 485852
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Naja, der Eingang wird ja nicht direkt Invertiert, sndern nur ein Abbild des Einganges im Speicher.
Du musst es ja nichtmal invertieren, um zu testen, ob das Bit 0 oder 1 ist.
Dazu maskiert man das Bit, so wie ich das gemacht habe. Das ist aber völlig unabhängig vom Prozessor, die Bildung des Komplements (=Inversion) aller Bits erfolgt in der Sprache C nunmal mit der Tilde. Das ist also Sprach- und nicht maschinenabhängig.
Mit dem ! kann man z.b. das Gegenteil eines Ausdrucks ausdrücken:
Wenn das Bit nicht 1 ist, dann ist der Taster gedrückt.
if(!(Variable & Maske)){...};
Der Compiler wiederum bastelt daraus eine möglichst effiziente Konstruktion von Mnemonics. Das ist aber wieder eher unwichtig.
_________________
|
BID = 486066
Herrminator Gelegenheitsposter
Beiträge: 87
|
Klar ja hast mal wieder recht. Hab es gestern mal noch probiert allerdings mault mein Compiler jetzt dran rum.
bit Taster @ PORTA.3 ;
i=~Taster;
^------
Error[1] D:\cc5x\Test C mplab\testC.c 24 : Unable to generate code
(The C syntax is correct. However, CC5X is unable to generate code.
The workaround is often to split the code into simpler statements,
using an extra variable to store temporary results. Sometimes it is
enough to change the sequence of operations)
if(i & 1<<Taster)
^------
Error[2] D:\cc5x\Test C mplab\testC.c 28 : Unable to generate code
|
BID = 486157
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Moin,
Ich habe leider keine Ahnung von PICs, aber kann man dort nicht auch einen ganzen Port (=eine IO-Adresse) in eine Variable laden?
Angenommen, das klappt (und davon gehe ich aus), sehe dein Programm so aus:
#define TASTER_BIT_POSITION 3 //Taster hängt an Bit 3
int main(void)
{
...
...
...
//testen, ob Taster 1 oder 0 liefert:
unsigned char i=PORT_LESEN; //hier irgendwie den kompl. Port einlesen
if(!(i & 1<<TASTER_BIT_POSITION)){
...
};
...
return(0);
};
Um zu verdeutlichen, was der Teil "1<<TASTER_BIT_POSITION"bedeutet, erkläre ich erstmal den Schiebeoperator >> und <<:
Diese Operatoren schieben ein Bit an eine bestimmte Position; z.B. wäre der Ausdruck i = 1<<7; das gleiche wie i = 128; oder i = 0x80; oder binär i = 10000000b (klar? Der Rechte Operand gibt also an, an welche Position das Bit geschoben wird, während der linke Opreand angibt, ob das Bit gesetzt (=1) oder gelöscht (=0) ist.
Mit dem #define TASTER_BIT_POSITION kann man also festlegen, welches Bit vom Taster repräsentiert wird und mit dem 1<<TASTER_BIT_POSITION wird eine Zahl generiert, an der _nur_ das 3. Bit 1 ist. Verunde ich nun die Zahl
i:
xxxx1xxx (x: Bitzustand spielt keine Rolle)
mit
00001000
Dann ist das Ergebnis entweder 0, da 0 und x immer 0, oder das Ergebnis ist ungleich 0 (nämlich 00001000), da 1 und 1 1 ergibt.
Mit dem ! davor wird genau das Gegenteil davon getestet und da if boolsch' auswertet, und alles ungleich 0 wahr und 0 falsch ist, kann eindeutig getestet werden, ob der Taster gedrückt oder nicht gedrückt ist
Der Compiler wiederum sollte für diese Ausdrücke dann möglichst effiziente Mnemonics nutzen, die der PIC-Instruktionssatz zur Verfügung stellt.
So könnte ich mir vorstellen, dass es bereits Maschinenbefehle gibt, die direkt einen IO-Pin abfragen können, so wie das manche Prozessoren der Firma Atmel auch können.
Da wird aus
if(PINC & 1<<4){
var|=1;
};
sbic PINC, 4
ori rx, 1
...
_________________
|
BID = 486171
Racingsascha Schreibmaschine
Beiträge: 2247 Wohnort: Gundelsheim
|
Zitat :
| So könnte ich mir vorstellen, dass es bereits Maschinenbefehle gibt, die direkt einen IO-Pin abfragen können |
btfsc PORTA,3 testet ob RA3 gelöscht (0) ist. Wenn ja, dann überspringt der Adresszähler den nachfolgenden Befehl.
btfss PORTA,3 macht dasselbe, nur überspringt er den Befehl wenn RA3 gesetzt (1) ist.
_________________
Fnord ist die Quelle aller Nullbits in deinem Computer.
Fnord ist die Angst, die Erleichterung, und ist die Angst.
Fnord schläft nie.
|
BID = 486207
Herrminator Gelegenheitsposter
Beiträge: 87
|
Hab nen Fehler gefunden jetzt geht der Compiler.
Aber s will immer noch nicht gehen.
So siehts Programm jetzt aus:
#pragma config |= 0b.1111.1111.0010 // Konfigurationswort
void main (void) // Start des Hauptprogramms
{
TRISC = 0b.1111.1110; // Led DS1 als Ausgang
TRISA = 0b.0000.1000; // SW 1 als Eingang
bit LED @ PORTC.0 ;
bit T @ PORTA.3 ;
unsigned char i;
Start:
i=PORTA.3;
if (!(i & 1<<'T'))
{
LED=1;
goto Start;
}
else
{
goto Start;
}}
LED leuchtet jetzt immer, nur wenn man den Taster drückt nicht mehr.
Der Compiler meint in der If Zeile wäre ein Teil immer Wahr
Gruß Tobias
|
BID = 486214
Racingsascha Schreibmaschine
Beiträge: 2247 Wohnort: Gundelsheim
|
Gibt es die Möglichkeit den compilierten ASM-Code anzeigen zulassen?
Zitat :
| unsigned char i;
Start:
i=PORTA.3;
|
Ich bin zwar ziemlich unbeleckt in C, aber ich ich glaube i sollte ein Boolescher Wert sein. Dann kann man auch einfacher mit true und false die LED an und ausmachen.
_________________
Fnord ist die Quelle aller Nullbits in deinem Computer.
Fnord ist die Angst, die Erleichterung, und ist die Angst.
Fnord schläft nie.
|
BID = 486230
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Nein, ein char ist kein boolscher Wert, sondern eine 8-Bit-Zahl (Byte)
Sry, ich kann dir da nicht weiterhelfen, habe einfach von PICs keine Ahnung.
Wie ist das denn mit dem Eingang? Liegt der auf der gleichen IO-Adresse wie der Ausgang? Bei AVRs ist das anders.
Wie dem auch sei, ich würde keine Bitfelder benutzen, sondern so wie ich das vorgeschalgen hatte:
Als Beispiel sei das mal für einen AVR gemacht:
LED ist an PORTC, Pin 0 (Ausgang)
Taster an PORTA, Pin 3 (Eingang)
int main(void)
{
DDRC |= 1<<0; //Bit0 setzen -> Pin wird Ausgang
DDRA &=~(1<<3); //Bit3 löschen -> Pin wird Eingang
while(1){
if(!(PINA & 1<<3))
PORTC |= 1<<0; //Led anschalten
else
PORTC &=~(1<<0); //Led ausschalten
};
return(0);
};
DDRC und -A sind die Register, die festlegen, ob ein Pin als Ein- oder Ausgang dient.
Du siehst, ich nutze keine Bitfelder, die sind zwar oft übersichtlicher, aber auch resourcenfressender und somit im Mikrokontrollerbereich zu vermeiden
_________________
[ Diese Nachricht wurde geändert von: DonComi am 30 Dez 2007 20:01 ]
|
BID = 486237
Jornbyte Moderator
Beiträge: 7178
|
.
.
.
else
{
LED=0;
goto Start;
}}
_________________
mfg Jornbyte
Es handelt sich bei dem Tipp nicht um eine Rechtsverbindliche Auskunft und
wer Tippfehler findet, kann sie behalten.
|
BID = 486239
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Ha!
Stimmt, die LED wird ja nie wieder ausgeschaltet.
Jorn hats,
ich haperte noch am 1<<'T' ...
_________________
|
BID = 486260
Nukeman Schriftsteller
Beiträge: 754 Wohnort: bei Kleve
|
Hi,
ich hab den Code mal ein bisschen umgestellt. Mit Gotos
aus if-bedingungen auszubrechen ist nicht gerade die sauberste
Art zu programmieren Und die Bitschiebereien bei
der Abfrage sind nicht nötig bzw. vielleicht sogar falsch,
es ist ja schon eine Bit-Variable.
Ausserdem meine ich, dass er bei 'T' den ASCII-Wert vom Buchstaben
nimmt und somit die 1 um 84 Stellen nach links gerückt.
Code : |
#pragma config |= 0b.1111.1111.0010 // Konfigurationswort
void main (void) // Start des Hauptprogramms
{
TRISC = 0b.1111.1110; // Led DS1 als Ausgang
TRISA = 0b.0000.1000; // SW 1 als Eingang
bit LED @ PORTC.0 ;
bit T @ PORTA.3 ;
while(1) // endlos-schleife
{
if(T) // Taste=1?
{
LED=0;
}
else
{
LED=1;
}
}
}
|
|
Evtl. geht auch statt dem if-else teil einfach LED = !T;
Manchmal hat der CC5x-Compiler aber seine Not, wenn zuviele
Anweisungen in einer Zeile stehen. Hast Du ja auch schon erlebt.
Dann hilft es meistens die Anweisungen auf mehrere Zeilen zu
verteilen oder eine Hilfsvariable zu benutzen.
Gruß
Stefan
edit: 2x umformatiert
[ Diese Nachricht wurde geändert von: Nukeman am 30 Dez 2007 20:55 ]
|
BID = 486263
Jornbyte Moderator
Beiträge: 7178
|
Zitat :
| Manchmal hat der CC5x-Compiler aber seine Not, wenn zuviele
Anweisungen in einer Zeile stehen. Hast Du ja auch schon erlebt. |
Ohh ja...
_________________
mfg Jornbyte
Es handelt sich bei dem Tipp nicht um eine Rechtsverbindliche Auskunft und
wer Tippfehler findet, kann sie behalten.
|
BID = 486265
Herrminator Gelegenheitsposter
Beiträge: 87
|
ja
; CC5X Version 3.3A, Copyright (c) B Knudsen Data
; C compiler for the PICmicro family
; ************ 30. Dec 2007 18:54 *************
processor 16F690
radix DEC
__config 0xFF2
PORTA EQU 0x05
TRISA EQU 0x85
RP0 EQU 5
RP1 EQU 6
TRISC EQU 0x87
LED EQU 0
i EQU 0x20
GOTO main
; FILE testC.c
;// Taktfrequenz 4MHz
;
;
;#pragma config |= 0b.1111.1111.0010 // Konfigurationswort
;
;void main (void) // Start des Hauptprogramms
;{
main
;TRISC = 0b.1111.1110; // Led DS1 als Ausgang
MOVLW .254
BSF 0x03,RP0
BCF 0x03,RP1
MOVWF TRISC
;TRISA = 0b.0000.1000; // SW 1 als Eingang
MOVLW .8
MOVWF TRISA
;
;
;bit LED @ PORTC.0 ;
;bit T @ PORTA.3 ;
;
;unsigned char i;
;
;Start:
;i=PORTA.3;
m001 BCF 0x03,RP0
BCF 0x03,RP1
CLRF i
BTFSC PORTA,3
INCF i,1
;if (!(i & 0<<'T'))
;
;{
;LED=1;
BSF 0x07,LED
;goto Start;
GOTO m001
;}
;
;else
;{
;goto Start;
END
; *** KEY INFO ***
; 0x0001 P0 13 word(s) 0 % : main
; RAM usage: 1 bytes (1 local), 255 bytes free
; Maximum call level: 0
; Codepage 0 has 14 word(s) : 0 %
; Codepage 1 has 0 word(s) : 0 %
; Total of 14 code words (0 %)
|
BID = 486268
DonComi Inventar
Beiträge: 8605 Wohnort: Amerika
|
Genau das meinte ich mit 'T'... .
_________________
|