Forum: Mikrocontroller und Digitale Elektronik c18 Bit Verschiebung


von Gero N. (geronimo76)


Lesenswert?

Ich baue mir gerade ein kleines Menu (ausgabe über LCD).
Steuerung über 4 tasten an PortB via Interrupt.
die 1. Taste ist dabei immer die "weiter" taste zum nächsten menupunkt.

da ich genau 8 menupunkte habe, dachte ich mir, dies sehr einfach per 
BIT-Rotation zu bewerkstelligen. KLappt aber leider nicht wie geplant^^

Mal der abgespeckte Code wie ich es handhabe:
1
unsigned char MenuFlag = 1;
2
...
3
...
4
... PORTB Interrupt Routine (funzt auch)
5
if(Taste1)   
6
  {
7
  Clear_LCD();
8
  MenuFlag <<=1;
9
  }
10
... ende Interrupt routine ...

also ich schreibe das menu anfänglich als 0b00000001 ...
die Interrupt sollte dann das bit 1 nach links verschieben
aber er schiebt um 2 ... woran kann das liegen? oder fehlt eine 
definition, da er eine rotation ausführt (im ASM kann man ja ums 
carry-flag routieren lassen)

weiß jemand rat?

von Karl H. (kbuchegg)


Lesenswert?

> aber er schiebt um 2 ... woran kann das liegen?

Ich denke mal es liegt daran, dass dein Taster prellt.

Es gibt keinen Grund Taster über einen Interrupt anzuhängen (ausser wenn 
der INterrupt den µC aus dem Tiefschlaf holen muss).
Ganz normales Pollen reicht völlig aus. In Kombination mit einem Timer 
gibt das eine wunderbare Entprellung und Tastenerkennung:

http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29


> oder fehlt eine
> definition, da er eine rotation ausführt (im ASM kann man ja ums
> carry-flag routieren lassen)

In C kann man nicht einfach Bit rotieren.

Machs nicht so kompliziert. Zähl eine Variable hoch und wenn 8 erreicht 
ist, dann setzt du sie zurück auf 0. Das ist einfach, simpel und doch 
effektiv.

von Gero N. (geronimo76)


Lesenswert?

mhh, scheint eindenkfehler in der interrupt routine zu sein.. ändere ich 
den code auf
1
if(Taste1)   
2
  {
3
  Clear_LCD();
4
  MenuFlag +=1;
5
  }
... addiert er auch 2 ^^ ... als würde es ein doppelklick sein .. sehr 
eigenartig

von Bernd M. (bernd_m)


Lesenswert?

Ist das evtl. ein Port Change interrupt?

von Gero N. (geronimo76)


Lesenswert?

ja ,,, deswegen hab ich ja die "IF" anweisung integriert

if(Taste1) => und vorher natürlich: #define Taste1      PORTBbits.RB7

dachte das reicht, damit der code nur ausgeführt wird, wenn taste 
gedrückt = highpegel

von Bernd M. (bernd_m)


Lesenswert?

Ich kenne PORTBbits.RB7 nicht, als was ist das definiert?

Aber ein Port change interrupt ist immerhin eine Möglichkeit für ein 
Doppelklick.

von Gero N. (geronimo76)


Lesenswert?

aso ...
PORTBbits.RB7 bedeutet bei C18 + PIC 18Fxxxx eig. nur das das PORTPIN 7 
an PORT B ist .. ist quasi ein Macro, um einzelne bits / portpins zu 
setzen bzw. auszulesen

Am PIC ist das physisch gesehen PIN 40 ... PORTB ist als change 
interrupt definiert

von Stampede (Gast)


Lesenswert?

Hallo,

das Change Notification Modul loest bei jeder Aenderung einen Interrupt 
aus, also bei steigender und fallender Flanke. Das musst du in deinem 
Sourcecode abfangen!

Gruss
Stefan

von Gero N. (geronimo76)


Lesenswert?

...genau, dieser umstand ist mir bewusst. deswegen hab ich ja in die 
Interrupt-routine jeweils eine port-zustandsabfrage eingebaut mittels
1
if(PORTBbits.RB7) {... tu das ...}

normalerweise müsste die anweisung der if-schleife nur ausgeführt 
werden, wenn RB7 HIGH ist (layout-bedingt bei mir = Taste gedrückt) ,, 
wenn ich taste loslasse erfolgt zwar ein weiterer Interrupt, aber 
softwaremäßig dürfte er nichts ausführen, bis auf flags löschen..
1
#define Taste1      PORTBbits.RB7
2
3
4
5
#pragma interruptlow MY_LOW_HANDLER
6
void MY_LOW_HANDLER(void)
7
{
8
if(INTCONbits.RBIF)
9
  {
10
  INTCONbits.RBIE = 0;                
11
  INTCONbits.RBIF = 0;                
12
  if(Taste1)   
13
    {
14
    Clear_LCD();
15
    MenuFlag += 1;
16
    //MenuFlag <<=1;
17
    }
18
  INTCONbits.RBIE = 1;
19
}

von Master S. (snowman)


Lesenswert?

sieh's doch ein: beim drücken, wird ein interrupt ausgelösst und korrekt 
abgearbeitet (um 1 shiften). da der taster prellt, wird ein zweiter 
interrupt ausgelösst, der nochmals um 1 shiftet. dies geschieht so 
schnell, dass du glaubst, es wäre nur ein interrupt gewesen, der falsch 
ausgeführt würde (um 2 shiften)...

ps: "INTCONbits.RBIF = 0;" erst ganz an den schluss der interruptroutine 
schreiben.

von Gero N. (geronimo76)


Lesenswert?

Master Snowman schrieb:
> ps: "INTCONbits.RBIF = 0;" erst ganz an den schluss der interruptroutine
> schreiben.

das wars^^ nun klappt es einwandfrei ... ich dachte immer, man muss die 
flag nach prinzip "interrupt aus -> flag löschen -> interrupt an" setzen 
...

thx 4 help

von Karl H. (kbuchegg)


Lesenswert?

Gero Nimo schrieb:
> Master Snowman schrieb:
>> ps: "INTCONbits.RBIF = 0;" erst ganz an den schluss der interruptroutine
>> schreiben.
>
> das wars^^ nun klappt es einwandfrei ...

solange bis die Taster älter werden und mehr prellen.

Wieder einer, ders auf die harte Tour lernen muss.

von Master S. (snowman)


Lesenswert?

> sieh's doch ein:
> [...]
> Wieder einer, ders auf die harte Tour lernen muss.
es scheint wohl so :-( ..und wir dürfen dann später aus ein paar infos 
raten, woran es dann liegt ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.