if(PORTBbits.RB0==0&&PORTBbits.RB1==1){// Eingangspegel (Switch) RB0 und RB1
32
33
zaehlen();}
34
35
return0;
36
}
37
38
/**
39
End of File
40
*/
Dieser Code hier Funtioniert hier leider nicht richtig, am Oszi sieht
man zwar ein rythmisches PWM-Signal, welches sich aber nicht stabil
ändert.Also es wird nicht incrementiert wie erwartet.Eigenartig ist das
trotzdem ein PWM-Signal nach draußen geht, denn die Bedingung RB0=0
(betätigt, Pullup aktiviert) und RB1=1(Pullup ebenfalls eingestellt),
ist noch nicht erfüllt, weil RB0 noch nicht auf Masse gelegt wurde!?
Warum versucht da trotzdem irgendwas die PWM-zuverändern, denn ändern
tut sie sich, nur eben völlig planlos?
Was mich stört, ist das ich die Varable "Counter" nicht "
PWM1_LoadDutyValue" einfügen kann, weil der Compiler dann meckert das
die Variable nicht deklariert ist!?Ich wollte den Counter eigentlich an
der Stelle platzierem,weil es die Variable ist die ja durch das
Timer1-interrupt hochgezählt werden soll.
Also immer wenn das Interrupt vom Timer kommt, sollen die Eingänge RB0
und RB1 geprüft und dann entsprechend die Variable "Counter" hochgzählt
werden, damit sich das Dutyvalue so steuern lässt.
Also was ist denn hier falsch??...bin Neuling in Sachen
C-programmierung!!
>Warum versucht da trotzdem irgendwas die PWM-zuverändern,
Weil mit jedem Aufruf von zählen() der Wert erhöht wird. Und nicht nur,
wenn Deine RB Tasten betätigt werden.
Matthias L. schrieb:> int HpwmKrem(void) // interrupt Handler> {> if(PORTBbits.RB0 ==0 && PORTBbits.RB1 ==1)> { // Eingangspegel (Switch) RB0 und RB1> if (++counter >= 512) counter = 0;> PWM1_LoadDutyValue(counter); // Load PWM1_LoadDutyValue> }> }
Hmmm, was ich hier nicht verstehe...zählt dein Counter hier automatisch
hoch und immer wenn Taster RB0 betätigt ist und ein Zählwert von 0 bis
512 im Register ist, wird der aktuelle Wert ins PWM1_LoadDutyValue
geladen??
Da würden dann doch Zufallswerte rauskommen?
Timer1 löst in meinem Fall das Interrupt alle 100ms aus und deine
Variable "uint16_counter" läuft automaisch durch oder??
In der Routine soll jedenfalls jedes mal nur um 1 erhöht werden können,
wenn RB0 betätigt auf Null geht.
Nop schrieb:> und außerdem geben Interrupts nichts zurück - wohin denn auch?
return zur variable Counter (siehe Funktion "zaehlen"), die im Bereich
von 0 bis einschließlich 512 liegen darf.
Mein Problem:ich komme an "counter" nicht ran, weil die Variable
innerhalb einer Funktion steckt.Ich brauche aber den "Counter"-Wert!? :(
Rudi R. schrieb:> return zur variable Counter (siehe Funktion "zaehlen"), die im Bereich> von 0 bis einschließlich 512 liegen darf.
Das funktioniert in C so nicht. Was es wirklich tut: Den Zähler mit 0
initialisieren, das Ergebnis (also null) mit 512 vergleichen, und den
wahr/falsch-Vergleichswert wegwerfen.
> Mein Problem:ich komme an "counter" nicht ran, weil die Variable> innerhalb einer Funktion steckt.
Wieso, den gibst Du doch mit der return-Anweisung zurück?!
Nop schrieb:> Das funktioniert in C so nicht. Was es wirklich tut: Den Zähler mit 0> initialisieren, das Ergebnis (also null) mit 512 vergleichen, und den> wahr/falsch-Vergleichswert wegwerfen.
Counter ist doch eine Variable,der ich einen Wertebereich geben muss,
sonst wird in einen Bereich inkrementiert,den das PWM-register nicht
mehr nach außen geben wird.Weiteres incrementieren ist ab 512 also nicht
erwünscht.
Bringt auch nichts, weil ich dann auch, wenn das funktioniert,irgendwie
wieder in die andere Richtung also decrementieren will.
Also ein anpassbares PWM-Signal.
Wieso, den gibst Du doch mit der return-Anweisung zurück?!
Der incrementierte Wert geht in die Funktion zurück.
Die variable Counter wird bei mir beim debuggen als nicht deklariert
angegeben, leider!Das dachte ich mir auch, dass ich Counter hier
extrahiert weiter verwenden kann, doch das scheint ja nicht zu
funktionieren!?
Ich brauche eine Variable die sich in der Routine decrementieren und
dann in der PWM1_LoadDutyValue mit den aktuellen Wert einfügen lässt.
Eine Frage die mich schon länger beschäftigt: Der Code von Anfängern ist
oft, naja, katastrophal formatiert. Das sieht man, wie hier, in Foren,
aber ich sehe es auch in der 4ma.
Warum ist das so?
Rudi R. schrieb:> Counter ist doch eine Variable,der ich einen Wertebereich geben muss
Das kannst Du in C aber nicht auf diese Weise. Dazu mußt Du vor dem
Inkrementieren prüfen, ob der Counter kleiner als Dein Maximalwert ist,
und nur dann inkrementieren.
So, wie Dein Code jetzt ist, compiliert er zwar, weil es legaler C-Code
ist, aber er tut nicht das, was Du beabsichtigst.
> Die variable Counter wird bei mir beim debuggen als nicht deklariert> angegeben, leider!
Setz mal einen Breakpoint direkt an die Stelle, wo er inkrementiert
wird.
Experte schrieb:> Warum ist das so?
Weil sie irgendwas programmieren, dann feststellen, daß es doch in einem
Block kommen muß, und nur die minimale Zahl an Tastendrücken ausführen,
um das zu erreichen. Lesbarkeit hat keine Priorität, weil sie noch nie
fremden Code lesen mußten und daher Lesbarkeit keinen Wert für sie
darstellt.
Ein weiteres Merkmal ist es übrigens, auf deutsch zu programmieren. Das
brennt einem zusammen mit den englischen Eigenbegriffen der Sprache
jedesmal die Augen weg.
Nop schrieb:> Das kannst Du in C aber nicht auf diese Weise. Dazu mußt Du vor dem> Inkrementieren prüfen, ob der Counter kleiner als Dein Maximalwert ist,> und nur dann inkrementieren.
Das verstehe ich jetzt nicht.Wenn die Variable in dem Bereich vom
Zahlenwert vorgegeben wird,passiert bei einem Wert von 512 nichts mehr
und ich habe ein PWM-Signal was sich nicht weiter in diese Richtung
ändern lässt.
Wenn ich jetzt dekrementieren würde, gehe ich gleich wieder auf 511 usw.
Und am Anfang kann ich ja noch nicht über dem Wert hinaus sein, weil der
Startschuss ja über die Interruptroutine und dem betätigtem Taster an
RB0 gefällt werden soll.Also entweder saust der Wert gleich auf den
maximal möglichen und bleibt dann eben stehen oder es passiert eben
nichts.
Erstmal muss die Variable Counter überhaupt in main ansprechbar werden,
was bis jetzt ja noch nicht der Fall ist.Ich habe undefinierte
PWM-Werte, die sich scheinbar zufällig ändern,und diese kommen aber
Zyklisch konstant(Pausenzeiten), was heißen muss, das das Timerinterrupt
wohl schon zum Einsatz kommen muss.
Ich hatte hier eben die Funktion "int zaehlen()" doppelt verwendet,
Einmal in der Routine und dann nochmals im Hauptprogramm,was hier wohl
zu diesen undefinierten Werten führt.
Also wie bekomme ich den Wert von Variable Counter in die Funktion
PWM1_LoadDutyValue()wenn diese außerhalb der Funktion "int zaehlen"nicht
ansprechbar ist??Das ist doch jetzt der Haken an der Geschichte oder
nicht?
es sieht so aus als wäre dieser Händler jetzt nicht der richtige Weg
dafür.
Also besser alles in einem Block, oder?
Anfänger schrieb im Beitrag #6601472:
> Was stört dich daran, in deutscher Sprache Kommentare zu machen?
Daß die Eigenbegriffe der Sprache, bei C z.B.
if/else/switch/case/integer usw., alle auf englisch sind, und sich dann
zwischendrin deutsche Bezeichner von Variablen und Funktionen
reinmischen. Geht gar nicht. Ich brauche Quelltext mit sowas gar nicht
näher zu analysieren, um zu wissen, daß er auf Anfängerniveau sein wird.
> Es ist ziemlich blöd, das viele Datenblätter nur auf Entgisch vorhanden sind
Die paar Hobbyisten, die nichtmal englisch können, verstehen ohnehin
keine Datenblätter, das wäre also vergeudete Mühe.
Rudi R. schrieb:> Das verstehe ich jetzt nicht.Wenn die Variable in dem Bereich vom> Zahlenwert vorgegeben wird
Wird sie aber in C nicht auf diese Weise, weil man eine Begrenzung des
Wertebereiches so nicht vorgeben kann. Was der Code stattdessen tut,
habe ich oben ja schon geschrieben. Ich weiß nicht, aus welcher Sprache
Du diese Syntax dafür entnommen hast, aber C ist es nicht.
> Erstmal muss die Variable Counter überhaupt in main ansprechbar werden,> was bis jetzt ja noch nicht der Fall ist.
Du kannst die Zählervariable natürlich auch außerhalb der Funktion
deklarieren, also als globale Variable. Da darauf dann vom Interrupt und
der main-Funktion zugegriffen wird, muß sie außerdem als volatile
deklariert werden.
Zur Wertebereichsbegrenzung muß das aber auch dann noch mit einer
if-Abfrage gemacht werden:
Anfänger schrieb im Beitrag #6601494:
> Und schon hat man alles in deutscher Sprache.
Das dürfte einer der Gründe sein, wieso in meiner Firma mindestens ein
Teil des Bewerbungsgespräches auf englisch stattfindet und keine Leute
eingestellt werden, die das nicht hinbekommen. :-)
Nop schrieb:> Rudi R. schrieb:>> return zur variable Counter (siehe Funktion "zaehlen"), die im Bereich>> von 0 bis einschließlich 512 liegen darf.>> Das funktioniert in C so nicht. Was es wirklich tut: Den Zähler mit 0> initialisieren, das Ergebnis (also null) mit 512 vergleichen, und den> wahr/falsch-Vergleichswert wegwerfen.
Das ist falsch.
Bei static int counter=0<=512; wird counter mit dem Ergebnis des
Ausdrucks 0<=512 initialisiert.
Da der Ausdruck wahr ist, ist es somit eine 1.
Hier rufst du jedesmal die Funktion zaehlen() auf und erhöhst somit den
Wert von counter, da dies die main-loop ist, rennt der dier ruckzuck
gegen den Anschlag bzw. Überlauf, mit undefinierten Folgen.
Informa schrieb im Beitrag #6601471:
> Experte schrieb:>> Warum ist das so?>> Das liegt daran, dass ihr in Deiner 4ma keinen Styleguide definiert> habt, der von Seiten der Geschäftsführung oder des Aufsichtsrats> vorgeschrieben wird.
...als wenn die Geschäftsführung oder der Aufsichtsrat Ahnung von
Programmierung hätte. Glaubst du da wirklich dran? ;-)
Nop schrieb:> Ein weiteres Merkmal ist es übrigens, auf deutsch zu programmieren. Das> brennt einem zusammen mit den englischen Eigenbegriffen der Sprache> jedesmal die Augen weg.
Als damals z.B. bei IBM Hochsprachen eingeführt wurden, wurde überlegt,
die Schlüsselworte in Deutsch zu übersetzen. Die Software-Entwickler
waren u.a.(*) dagegen, da sich so viel leichter unterscheiden ließ, was
Schlüsselworte / Library war und was die eigene Kreation.
Genauso wie es sinnvoll sein kann(!), 2 verschiedene Naming-Styles zu
haben, also z.B. CamelCase für den eigenen Code wenn das Framework klein
mit _ ist.
(*)Dass übersetzte Begriffe meist ins Chaos führen sieht man ja
spätestens beim Ärger mit Deutschen/Englischen Menüs in Windows oder
Word.
Experte schrieb:> Warum ist das so?
Interessante Beobachtung. OK, dass die Form egal ist, weil es erstmal
irgendwie klappen soll. Dass man zöllige Rohre anflanscht damit es
irgendwie hält. Geschenkt.
Es scheint noch darüber hinaus zu gehen: Die Angst vor Verschwendung. So
wie Grundschulkindern oft keine neue Zeile anfangen oder gar eine frei
lassen möchten. In Mathe fängt die erste Zahl im obersten linken
Kästchen an, in Deutsch beginnt ein neuer Satz selbst wenn nur noch ein
Buchstabe bis zum Rand Platz ist.
Und die Abneigung, etwas doppelt zu machen: statt durchzustreichen wird
gekillert, weil dann 5 der 7 Buchstaben nicht nochmal geschrieben werden
müssen. Selbst wenn es dreimal so lange dauert. Statt einheitlicher
Formatierung wird die "organische entstandene" heilig gehalten, selbst
wenn dann jede Klammer ihren eigenen Stil hat.
Dirk B. schrieb:> Das ist falsch.>> Bei static int counter=0<=512; wird counter mit dem Ergebnis des> Ausdrucks 0<=512 initialisiert.> Da der Ausdruck wahr ist, ist es somit eine 1.
Stimmt. Ich war davon ausgegangen, daß der Compiler so wie bei
Ausdrücken der Art "a+++b" vorgehen würde. Allerdings ist das, was ich
dabei als "biggest valid chunk" betrachtet hatte, nämlich das hier:
1
staticint(counter=0)<=512;
gar kein valider Ausdruck, weil das nach dem Vergleich zu
uint_16t counter;
void main(void)
{
SYSTEM_Initialize(); // initialize the device
TMR1_SetInterruptHandler(HpwmKrem); //Define interrupt Handler
INTERRUPT_GlobalInterruptEnable(); // Enable the Global
Interrupts
INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral
Interrupts
while (1)
{
;;;;
}
}
int HpwmKrem(void) // interrupt Handler
{
if(PORTBbits.RB0 ==0 && PORTBbits.RB1 ==1)
{ // Eingangspegel (Switch) RB0 und RB1
if (++counter >= 512) counter = 0;
PWM1_LoadDutyValue(counter); // Load PWM1_LoadDutyValue
}
}
Du meinst den Code hier, den du gestern geschickt hattest?
Denn wollte ich ersteinmal verstehen und werde ihn einfach mal
ausprobieren.
Wenn er funktioniert werde ich mal gucken warum er funktioniert! ;o)
"++counter" ist mir hier noch nicht klar, schreibt man inkrementieren
nicht so"counter++"?... und warum man die Variable counter nicht so
anlegen kann"counter=0<=512", ist mir auch noch nicht schlüssig?Ich
dachte ich hätte den Werte bereich hier genau definiert??
Und dann wird die Variable " counter" ja erst in der Funktion des
interrupt Handler deklariert oder wie?
Also ich probier das jetzt mal!
Danke aber ersmal für eure bisherige Hilfe!
Im übrigem arbeite ich mich mit dem Buch zu www.c-howto.de ein.
Da gehts in den Beispielen aber unter anderem um die Programmierung von
Getränkeautomaten!Ich versuche hier Analogien zu finden.
Kann mir jemand ein Buch zu C-Programmierung für PIC´s oder generell für
uC mit C empfehlen? Dieses Umdenken von diesem Beispielen dort macht mir
die Sache hier natürlich umständlicher obwohl es gut geschrieben ist!
A. S. schrieb:> Interessante Beobachtung. OK, dass die Form egal ist, weil es erstmal> irgendwie klappen soll. Dass man zöllige Rohre anflanscht damit es> irgendwie hält. Geschenkt.
Übrigens scheint mich Mathias L (Lippi) verstanden zu haben, also er hat
mein Code da wohl verstanden!
Ich finde es immer traurig was für Bögen in so einem Forum entstehen, wo
es nicht mehr um das eigentliche Thema geht!?
Ich arbeite übrigens mit dem PDF "C HowTo", welches leider nicht so gut
für Mikrocontrollereinsteiger zu sein scheint....Daher wohl auch meine
kurriosen
Codeschnipsel die ich nur gedanklich versuche auch Mikrocontroller zu
übertragen.
Rudi R. schrieb:> uint_16t counter;
Aber sobald sowohl aus dem Interrupt als auch aus dem Hauptprogramm auf
diese Variable zugegriffen wird (das wolltest Du ja erreichen), muß das
so gemacht werden:
1
volatileuint16_tcounter;
Gewöhn Dir bitte auch an, für Code die vorgesehenen Tags zu nutzen. Das
steht direkt über der Forumsbox, wo Du die Postings verfaßt, unter
"Formatierung".
Korrekt. Ein volatile sollte dazu.
>warum man die Variable counter nicht so anlegen kann"counter=0<=512", ist >mir
auch noch nicht schlüssig?
Weil das keine korrekte c Zuweisung ist. Für c ist das ein Vergleich.
Beispiel:
"a=5"
Was ist das? möchtest Du hier a den Wert 5 zuweisen, oder a auf 5
prüfen?
Dieses Problem muss unterschieden werden können. c verwendet für den
Vergleich "a==5", für die Zuweisung "a=5". Andere Programmiersprachen
machen das anders. zb ST/Pascal:
Zuweisung a:= 5
Vergleich a=5
>++counter"
heisst, zuerst inkrementieren.
>counter++
heisst, nachher inkrementieren.
Stehen beide allein (auf einer Zeile da, ist auch kein Unterschied. Bei
Vergleichen oder Zuweisungen aber schon:
a=1;
b=++a; // erst inkrementieren, dann zuweisen
c=a++; // erst zuweisen, dann inkrementieren
// results:
// b=2, c=2, a=3
>if (++counter >= 512)
Hier wird also erst inkrementiert und dann vergleichen. Somit wird der
Wert zwar von 511 auf 512 erhöht, aber danach wird der Vergleich wahr
und somit genullt.
Matthias L. schrieb:> Rudi R. schrieb:>> Rudi R.>> (microwitsch)>> Du solltest nochmal meinen Post ansehen. Da sind alle Deine Fehler> behoben.
SO,also dein Code funktioniert!!...Super,Danke Matthias!
Nun muss "microwitsch" nur noch herausfinden wieso!?
Die Variable uin16_t wird gar nicht ausserhalb deklariert??
Die bekommt doch ihre Werte erst beim Aufruf in der Routine?
Davon steht in dem Buch "C HowTo" nichts?
Also genauso hab ich mir die Funktionsweise vorgestellt wie sie jetzt
auch bei mir funktioniert!
Lässt sich übrigens auch superfein einstellen!
Aktuell dauert es ca 50s bis er beim Wert 512 angekommen ist und wieder
bei 0 anfängt.
Nun muss ich noch sehen wie ich mit den anderen Eingang RB1 wieder
dekrementieren kann. :)
>Die Variable uin16_t wird gar nicht ausserhalb deklariert??
Sie wird global definiert. Also ist sie überall erreichbar.
>Die bekommt doch ihre Werte erst beim Aufruf in der Routine?
Ok, Einen definierten Startwert könnte man ihr noch spendieren:
1
uint_16tcounter;
2
voidmain(void)
3
{
4
...
5
counter=0;
6
while(1)
7
{
8
;;;;
9
}
10
}
>Aktuell dauert es ca 50s bis er beim Wert 512
Der Interrupt scheint alle 100ms zu kommen.
>Nun muss ich noch sehen wie ich mit den anderen Eingang RB1 wieder>dekrementieren kann. :)
RB1 ist doch bereits verwendet.
Sonst:
1
if(upbutton)
2
{
3
if(++counter>=512)counter=0;
4
}
5
if(downbutton)
6
{
7
if(counter>0)counter--;
8
}
Aber generell ist die Tasenabfrage noch weit verbesserbar.
Matthias L. schrieb:>>Die Variable uin16_t wird gar nicht ausserhalb deklariert??>> Sie wird global definiert. Also ist sie überall erreichbar.>>>>Die bekommt doch ihre Werte erst beim Aufruf in der Routine?> Ok, Einen definierten Startwert könnte man ihr noch spendieren:>
1
>uint_16tcounter;
2
>voidmain(void)
3
>{
4
>...
5
>counter=0;
6
>while(1)
7
>{
8
>;;;;
9
>}
10
>}
11
>
>>>Aktuell dauert es ca 50s bis er beim Wert 512> Der Interrupt scheint alle 100ms zu kommen.>>>Nun muss ich noch sehen wie ich mit den anderen Eingang RB1 wieder>>dekrementieren kann. :)> RB1 ist doch bereits verwendet.>> Sonst:>
1
>if(upbutton)
2
>{
3
>if(++counter>=512)counter=0;
4
>}
5
>if(downbutton)
6
>{
7
>if(counter>0)counter--;
8
>}
9
>
> Aber generell ist die Tasenabfrage noch weit verbesserbar.Matthias L. schrieb:> Sie wird global definiert. Also ist sie überall erreichbar.
Nach dem Buch "C HowTo"
würde das so aussehen?? hier mal kopiert
9.2Globale Variablen
Ist eine Variable global, so kann man von jedem Ort aus auf sie
zugreifen. Eine Variable wird global, indem man sienicht in einem Block,
sondern außerhalb der Hauptfunktion deklariert.
#include<stdio.h>
// globale Variable
int counter = 0;
void zaehlen() {
counter += 1;}
int main() {
zaehlen();
printf("Zaehler: %d\n", counter);
return 0;}
Zaehler:1 //Ausgabe Bildschirm
Ist bei Mikrokontroller dann wohl anders?
Wie erhält den Variable uin16_t ihren Wertebereich??verstehe ich noch
nicht ganz?
> Ist bei Mikrokontroller dann wohl anders?
Wieso? Ist doch genauso. Ausserhalb eines (jeden) Blockes. Ein Block ist
zb eine Funktion. Alles was Du innerhalb definierst, gibt es auch nur
dort. Da Du counter an vielen Stellen/Funktionen verwenden willst,
darfst Du sie nicht innerhalb einer definieren. Sondern "über" allen.
> Wie erhält den Variable uin16_t ihren Wertebereich??verstehe ich noch> nicht ganz?
Der Wertebereich ist durch den Datentyp uint16_t festgelegt. DIese
Variable kann also Zahlenwerte zwischen 0 und 65535 speichern. Du bist
selbst für Grenzüberschreitungen verantwortlich
1
x=65535;
2
x++;
3
// hier ist x wieder null
4
5
y=0;
6
y--;
7
// hier ist y jettz 65535
Du musst also dafür sorgen, das der Zahlenwert Deine gewüschten Grenzen
nicht verletzt.
1
//zB Erhöhung/Verkleinerung nur, solange noch nicht Endwert:
Matthias L. schrieb:> Der Wertebereich ist durch den Datentyp uint16_t festgelegt. DIese> Variable kann also Zahlenwerte zwischen 0 und 65535 speichern. Du bist> selbst für Grenzüberschreitungen verantwortlich
ok, ich bin mal den Link in Mplab gefolg und komme hier auf die
Typendefinition, die mir bis dahin auch noch nicht klar war.
,also eine unsigned short ist es, die mit der Defintion zu uin16_t
geklärt wird.
#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t)
typedef unsigned short uint16_t;
#define __DEFINED_uint16_t
#endif
Nun ja, deine Beiträge sind mir gerade eine große Hilfe, danke, danke!
>typedef unsigned short uint16_t;
Das ist nichts weiter als ein neuer Name für "unsigned short".
Der neue Name ist besser:
uint -> unsigned
16 -> 16bit
_t -> type definition
Also:
uint8_t -> 0..255
int8_t -> -128 .. +127
int16_t -> -32768 .. +32767
uint32_t -> 0.. 4'294'967'296
int32_t -> -2'147'483'648 .. +2'147'483'647
allgemein:
unsigned: 0.. 2^(Anzahl_Bits) - 1
signed: -2^(Anzahl_Bits-1) .. +2^(Anzahl_Bits-1)-1
>Ok, Einen definierten Startwert könnte man ihr noch spendieren:
hat sie: uint_16t counter;
sollte mit jedem C-Konformen Compiler mit 0 Initialisiert werden bevor
in die main() gesprungen wird.
Wie erhält den Variable uin16_t ihren Wertebereich??verstehe ich noch
nicht ganz?
uint_16t ist der Wertebereich. 16 Bit unsigned 0 bis 2^16-1
für dein < 512 ginge auch
cntr=(cntr+1)&0x01FF;