Hallo,
ich bin Azubi im ersten Lehrjahr und soll den PIC16F688 programmieren.
Ein Blinklicht habe ich schon hinbekommen. Ich benutze MPLAB und den
HI-TECH C-Compiler. Hier mein Code bis jetzt:
#include <htc.h> //include header file
#include <pic16f688.h> //include PIC header
#define FOSC_INTOSCIO 0xFFFC //set internal oscillator I/O
function on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN
#define WDTE_OFF 0xFFF7 //disable Watchdog Timer
#define MCLRE_OFF 0xFFDF //MCLR pin function is digital
input, MCLR internally tied to VDD
int main(){
ANSEL = 0b00000000; //All I/O pins are configured as
digital
CMCON0 = 0b00000111; //Coperators turned OFF
PORTC = 0x00; //write 0 to port C
TRISC = 0x00; //set RC0 as output pin / set TRIS
register BIT 0 to 0
while(1){
PORTC = 1; //LED_ON
_delay(1000000); //delay for 1000000 cycles
PORTC = 0; //LED_OFF
_delay(1000000); //delay for 1000000 cycles
}
}
Die LED blinkt.
So meine Frage: Jetzt leuchtet die LED nur am RC0. Wie kann ich denn
andere Ausgänge des Ports ansteuern? Sodass ich mehrere LED blinken
lassen kann? oder gar ein lauflicht?
PORTC = 0x01
TRISC = 0x01 etc.pp. hab ich schon versucht...es zeigt keine wirkung.
sprut kenne ich auch schon und hilft mir leider nicht weiter, da er viel
assembler macht. ICh hoffe ihr könnt mir helfen.
Ich habe auch schon etwas über bitmanipulation gelesen, aber ich
verstehe es nicht ganz, bzw. die syntax.
Liebe Grüße
Stefan
Du hast ja schon mal den ganzen Port C auf Ausgang gestellt. Das ist
schon mal gut.
PortC ist aber nicht nur ein Bit sondern ein ganzes Byte.
Du sagst jetzt ja mit PORTC =1 das gleiche wie PORTC = b00000001.
Hallo,
vielen lieben Dank für eure schnellen Antworten. Erstens entschuldige
ich mich für die etwas gewöhnungsbedürftige Schreibweiße meines ersten
Posts, doch ich war leider unter Zeitdruck, da ich bald Feierabend
hatte.
Ich habe eigentlich zu jeder eurer Antworten Fragen, die stelle ich hier
einfach mal, in der Hoffnung, dass Ihr sie noch lest und der Thread
nicht schon "Schnee von gestern" ist.
@Timmo H. : Wie meinst du das mit 8 LEDs an PortC? Mein PIC16F688 hat
nur 6 I/O beim Port C, die anderen 2 bits sind laut Datenblatt nicht
implementiert. Zu meiner eigentlichen Frage:
1
PORTC=0xAA;
2
while(1){
3
_delay(1000000);//delay for 1000000 cycles
4
PORTC^=0xFF;//und umdrehen
5
6
}
was genau meinst du denn mit PORTC ^= 0xFF , was genau macht denn diese
Zeile und was bedeutet "^"?
@Jürgen D. : So wie ich deine Antwort verstehe, liegt mein Problem
darin, dass ich durch PORTC = 1 sage, dass das erste Bit gesetzt werden
soll, sprich RC0? Wenn ich dann die anderen Ausgänge ansprechen will,
muss ich gerade das Bit weiterschieben: PORTC = 0b00000010 ? Wäre das
dann der Ausgang RC1? Und ist es egal ob ich 0b00000010 schreibe oder
0x01?
@Ralf G. : Die ersten beiden Zeiler meiner main() besagen:
1
ANSEL=0b00000000;//All I/O pins are configured as digital
2
CMCON0=0b00000111;//Coperators turned OFF
ich weiß leider gerade nicht, was du von mir willst, so wie ich die
beiden Zeilen verstehe, sage ich durch den ersten Befehl, dass alle I/O
Pins digital sind, und durch CMCON0 sage ich, dass der interne
Comperator deaktiviert sein soll. Oder verstehe ich das falsch?
Übrigens sehr nett, dass Ihr mir helft, ich hatte ein Semester Java
Programmieren gelernt in der Uni, jetzt da ich die Ausbildung mache,
wünschte ich mir, ich hätte mehr aufgepasst, dann hätte ich vermutlich
nicht so viele PRobleme mit C. Ich wrne hier schon vor, dass es bestimmt
noch zu einigen weiteren Fragen kommen wird. Vielen Dank und einen
schönen Abend wünsche ich euch noch.
Stefan
Stefan H. schrieb:> @Timmo H. : Wie meinst du das mit 8 LEDs an PortC? Mein PIC16F688 hat> nur 6 I/O beim Port C, die anderen 2 bits sind laut Datenblatt nicht> implementiert.
Auch recht.
> muss ich gerade das Bit weiterschieben: PORTC = 0b00000010 ? Wäre das> dann der Ausgang RC1? Und ist es egal ob ich 0b00000010 schreibe oder> 0x01?
Es ist wie im dir gewohnten Dezimalsystem.
1 ist nicht dasselbe wie 10 (Zehn) und das ist nicht dasselbe wie 100
(hundert) etc. etc.
Nur das du hier erst mal kein Dezimalsystem zur Basis 10, sondern ein
Binärsyste, zur Basis 2 hast. Das vorangestellte 0b kennzeichnet die
Zahl als Binärzahl.
Wie wird da gezählt?
Na genauso, wie auch im Dezimalsystem gezählt wird. Nur dass es dann
eben nur die beiden Ziffern 0 und 1 gibt. Ist ja schliesslich das Binäre
Zahlensystem (und im Dezimalsystem haben wir 10 verschiedene Ziffern. Im
Oktalsystem [Oktal == 8] sind es 8 und im Hexadezimal-System sind es 16)
Also wie zählen wir? (Dezimalsystem)
Du fängst bei 0 an, und bei jedem mal weiterzählen nimmst du die nächste
Ziffer aus deinem Vorrat.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Wie gehts weiter? Dein Ziffernvorrat ist aufgebraucht. Mehr als diese 10
Ziffern hast du nicht. Ist aber kein Problem. Wir benutzen ja ein
Stellenwertsystem. D.h. ein bestimmtes Symbol hat unterschiedliche
Wertigkeiten, je nachdem an welcher Stelle es in einer Zahl auftaucht
(AChtung: Zahl - nicht Ziffer. Eine Ziffer ist eine einzelne Stelle.
eine Zahl ist das ganze, also die Summe aller Ziffern)
Deine Ziffern sind aufgebraucht. Aber du weist auch, dass du dir vor der
Einerstelle einen ganzen Haufen führende 0-en vorstellen kannst. Diese
ändern ja an der Zahl erst mal nichts. Ob du 5 oder 005 oder 0000000005
schreibst - es ist immer die gleiche Zahl.
Zurück zum 'Experiment'. Wir hatten
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
und wie gehts weiter? Na ganz einfach. Du erhöhst einfach die
unmittelbar links davon liegende Stelle um 1 (da wo jetzt noch eine
gedachte führende 0 steht) und beginnst in der Einerstelle wieder bei 0
10, 11, 12, 13, 14, 15, 16, 17, 18, 19
und wieder hast du in der Einerstelle alle deine möglichen 10 Ziffern
verballert. Aber du kennst das Rezept ja schon: zu der Stelle davor 1
dazuzählen (also die nächste Ziffer aus dem Vorrat nehmen) und weiter
gehts.
20, 21, 22, 23, 24, 25, 26, 27, 28, 29
das geht jetzt natürlich solange weiter ...
90, 91, 92, 93, 94, 95, 96, 97, 98, 99
... bis du in der Situation bist, dass du wieder in der Einerstelle
keine Ziffer mehr hast, und daher in der Zehnerstelle um 1 erhöhen
musst. Nur: Auch dort hast du bereits alle deine 10 dir zur Verfügung
stehenden Ziffern aufgebraucht. Was machst du? Du machst dasselbe, was
du auch gemacht hast, als die Ziffern das erste mal in der Einerstellt
aufgebraucht waren: du borgst dir wieder in der ersten Stelle links eine
führende 0 und schreibst das nächste Zeichen deines Vorrats rein. Die
nächste Zahl nach 99 ist daher 100
und schon läuft der Laden wieder
100 101 102 103 104 105 106 107 108 109
110 111 112 113 114 115 116 117 118 119
Klar soweit?
Zählen ist also nichts anderes als nacheinander alle Zeichen des Vorrats
'durchzuspielen' und wenn alle Zeichen an einer Stelle aufgebraucht
sind, dann geht es an der Stelle links davon weiter dort das nächste
Zeichen zu benutzen. Falls das geht - wenn nicht, dann gehts halt noch
eine Stelle weiter. etc. etc.
Und im Binärsystem ist das auch nicht anders. Nur dass du nicht 10
Ziffern hast, sondern nur 2. Die 0 und die 1
Wie wird also gezählt
0, 1
mehr geht erst mal nicht. Aber völlig identisch zu oben, nehmen wir
einfach mal die stille führende 0 mit dazu und erhöhen die auf die
nächste Ziffer
10 11
wieder ist aufgebraucht. Die 'Zehner'-Stelle ist ebenfalls aufgebraucht
(so wie das im Dezimalsystem bei der 99 war), also nehmen wir die
nächste Stelle links dazu
100 101
110 111
und wieder sind wir am Ende. Noch eine Stelle muss her
1000 1001
1010 1011
1100 1101
1110 1111
und die nächste
10000 10001
10010 10011
10100 10101
10110 10111
11000 11001
11010 11011
...
und so geht das immer weiter .... fast
Denn im Computer hat man nicht beliebig viel Platz. Irgendwo muss man
eine Grenze setzen. Und da hat man als kleinste Zusammenfassung das Byte
gewählt. Ein Byte besteht aus 8 binären Stellen (den sog. Bits)
D.h. du hast nicht beliebig viele stille führende 0-en sondern nach der
8-ten ist SChluss. Und da man die 8 Bits oft in einem Aufwasch braucht,
schreibt man diese 8 Stellen auch tunlichst hin. Etwas das wir im
Dezimalsystem selten tun (zb bei Uhrzeiten. Wir schreiben nicht 8:5 für
8 Uhr 5, sondern wir schreiben 08:05)
Hier sind diese 8 Bits, die ein Byte bilden
0b0000000
und wenn da gezählt wird, dann funktioniert das nach genau dem Schema,
das du schon kennst
0b00000000 ( = dezimal 0 )
0b00000001 ( 1 )
0b00000010 ( 2 )
0b00000011 ( 3 )
0b00000100 ( 4 )
0b00000101 ( 5 )
0b00000110 ( 6 )
0b00000111 ( 7 )
0b00001000 ( 8 )
....
0b11111110 ( 254 )
0b11111111 ( 255 )
fertig, mehr geht mit 8 Bits nicht.
Dein Port ist nun so verkabelt, dass er auch diese 8 Bits hat. Aber:
Anstatt dass da die Bits einfach nur gespeichert sind, sind sie aus dem
µC herausgeführt. Diese Bits kontrollieren also tatsächlich den Pegel
deiner Ausgangsleitungen. Gut, bei deinem Port sind nur 6 herausgeführt.
Das hat aber mehr technische Gründe als sonst irgendwas anderes
0b00000000
||||||||
|||||||+----> zum Pin RC0
|||||||
||||||+-----> zum Pin RC1
||||||
|||||+------> zum Pin RC2
|||||
||||+-------> zum Pin RC3
..... etc.
D.h. wenn du deinem Port das Bitmuster
0b00001011
zuweist
PORTC = 0b00000110;
dann gehen RC1 und RC2 auf 5V und die anderen Pins bleiben auf 0.
Da du aber oben in der Tabelle gesehen hast, dass das Bitmuster
0b00000110 der dezimalen Zahl 6 entspricht (weil es ja beim Abzählen an
dieser Position drann kam), kannst du daher auch schreiben
PORTC = 6;
und es passiert genau dasselbe. Denn 6 ist nur eine andere Schreibweise,
in einem anderen Zahlensytstem (nämlich im Dezimalsystem) für das
Biutmuster 00000110.
Der Unterschied ist das 0b in 0b00000110.
Es kennzeichet eine Binärzahl
PORTC = 0b0000110;
und PORTC = 00000110;
sind also verschiedene Dinge. Das erste ist die Binärzahl 0000110 und
das andere ist die Dezimalzahl 110 (ein hundert zehn)
Uff. Ist etwas lang geworden :-)
Wow, vielen lieben Dank für die wirklich sehr ausführliche Antwort,
jetzt bin ich dem System doch einen Schritt näher gekommen. Schön zu
wissen, dass es Menschen gibt, die sich die Zeit nehmen einem mal zu
helfen in der sonst so schnelllebigen hecktischen Welt.
So, das mit den Ports und den Pins hab ich jetzt verstanden, werde das
nach dem Feiertag gleich mal ausprobieren (hoffentlich klappt es :-) ).
Was ich jetzt noch nicht ganz verstanden habe ist folgendes: Wenn ich
durch wenn ich durch das Bitmuster dem Port Hi und Low Pegel zuweisen
kann, wozu brauche ich dann das TRIS - Register des Ports? In meinem
Code aus dem ersten Post habe ich das Byte im TRIS-Register auf
0b00000000 gesetzt. Ohne diese Zeile funktioniert der Code nicht.
Stefan H. schrieb:> So, das mit den Ports und den Pins hab ich jetzt verstanden, werde das> nach dem Feiertag gleich mal ausprobieren (hoffentlich klappt es :-) ).> Was ich jetzt noch nicht ganz verstanden habe ist folgendes: Wenn ich> durch wenn ich durch das Bitmuster dem Port Hi und Low Pegel zuweisen> kann, wozu brauche ich dann das TRIS - Register des Ports?
Weil du an deinen µC Pins nicht nur LEDs anschliessen willst, sondern
auch mal einen Taster.
D.h. du brauchst eine Möglichkeit, wie du festlegen kannst, welcher Pin
als Ausgang und welcher als Eingang fungieren soll.
Ausgang: dein Programm kontrolliert den Pegel. Eine externe
Hardware (zb eine LED) reagiert darauf
Eingang: die externe Hardware (zb ein Schalter oder Taster)
kontrolliert die Spannung an diesem Pin.
Dein Programm kann das abfragen und das Programm
reagiert auf den Pegel.
Karl Heinz Buchegger schrieb:> int main()> {> unsigned char i;>> ANSEL = 0b00000000; //All I/O pins are configured as digital> CMCON0 = 0b00000111; //Coperators turned OFF> PORTC = 0x00; //write 0 to port C> TRISC = 0x00; //set RC0 as output pin / set TRIS register BIT
0 to 0
>> i = 0;>> while(1){>> PORTC = i;> i = i + 1;>> _delay(1000000); //delay for 1000000 cycles> }> }
Ich habe jetzt zwar nicht die Möglichkeit das zu testen, werde ich aber
gleich am Freitag machen. So wie ich deinen Code verstehe, müssten die
Ausgänge beginnend bei RC0 bis RC5 nacheinander schalten? Allerdings
läuft das ganze nur bis 255 theoretisch. Oder liege ich hier falsch?
Weil i kann ja maximal 255 werden bzw. 0b11111111?
Karl Heinz Buchegger schrieb:> D.h. du brauchst eine Möglichkeit, wie du festlegen kannst, welcher Pin> als Ausgang und welcher als Eingang fungieren soll.
Ah, das heißt also, wenn ich schreibe
1
2
TRISC=0b00010101;
das RCO -> Input
RC1 -> Output
RC2 -> Input
RC3 -> Output
etc.
ist?
MaWin schrieb:> _delay auf einem PIC16 nimmt wirklich ein Long als Parameter ?> Ich bin erstaunt.
ich weiß zwar nicht genau was du meinst, da ich nur diesen PIC kenne,
aber das _delay funktioniert :)
gibt es noch eine andere Möglichkeit eine Zeitverzögerung zu
implementieren?
>> das RCO -> Input> RC1 -> Output> RC2 -> Input> RC3 -> Output> etc.> ist?
Ja.
ABer ich hab jetzt eigentlich nicht vor, hier alles wiederzukäuen, was
auf unzähligen PIC-Tutorial Seiten und nicht zuletzt im Datenblatt des
µC des langen und breiten vorgekaut wird.
http://www.mikroe.com/chapters/view/4/
Stefan H. schrieb:> gibt es noch eine andere Möglichkeit eine Zeitverzögerung zu> implementieren?
Jede Menge. Und ein delay ist die schlechteste Version davon.
Aber das soll dich im Moment nicht daran hindern. Irgendwo muss man mal
anfangen und man kann nicht alles auf einmal lernen.
MaWin war nur erstaunt darüber, dass man die Anzahl der zu verballernden
Zyklen angibt und nicht gleich direkt eine Zeitangabe und der µC rechnet
sich selber aus, wieviele Taktzyklen er verballern muss um auf diese
Zeit zu kommen. Dazu müsste allerdings das Programm wissen, wie schnell
der µC getaktet wird. Überlässt man diese Rechnerei dem Programmierer,
ist es zunächst erst mal einfacher. Auch wenn es für den Programmierer
erst mal mehr Arbeit bedeutet.
> MaWin war nur erstaunt darüber, dass man die Anzahl der zu verballernden> Zyklen angibt und nicht gleich direkt eine Zeitangabe und der µC rechnet> sich selber aus,
Nein, ich war erstaunt, daß micht bei 65535 Schluss ist mit der _delay
Zahl, oder gar bei 255.
Denn das heisst, daß der Compiler für den kleinen PIC einen int als 32
bit Wert umsetzt.
MaWin schrieb:>> MaWin war nur erstaunt darüber, dass man die Anzahl der zu verballernden>> Zyklen angibt und nicht gleich direkt eine Zeitangabe und der µC rechnet>> sich selber aus,>> Nein, ich war erstaunt, daß micht bei 65535 Schluss ist mit der _delay> Zahl, oder gar bei 255.
Das erstaunt jetzt mich wieder.
Was willst du mit maximal 65535 verballerten Zyklen gerade als Anfänger
anfangen?
> Denn das heisst, daß der Compiler für den kleinen PIC einen int als 32> bit Wert umsetzt.
sind doch nur 4 ineinander geschachtelte Byte-Schleifen. Und ob das so
genau zugeht ... ich hab da so meine Zweifel. Aber egal. Er braucht erst
mal eine einfach Version um irgendwas im Sekundenbereich hinzukriegen.
Und dafür dürfte es ja reichen.
> int als 32> bit Wert umsetzt.
wie kommst du da drauf?
auf einem int mit 16 Bit ist ein 1000000 automatisch ein long.