PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMEGA16 + STK500 - Lauflicht



Kesandal
19.05.2011, 09:52
Hallo,
vermutlich ist es ein einfacher Fehler, doch zunächst mein Quelltext:



#include <avr/io.h>
#include <avr/delay.h>

void main(){
DDRB = 0xFF; // Alle Pins sind Output
PORTB = 0xFF; // Alle LEDs ausschalten

// Hier möchte ich z.B. um 2 nach links shiften

PORTB &= (0<<2);


// Restlicher Code nicht mehr relevant [...]



Mein Problem ist das shiften.

Wenn ich in PortB alles auf 1 setze, sind alle LEDs ausgeschaltet.
Nun möchte ich die dritte Lampe einschalten.
Dementsprechend müsste ich ja an die Stelle eine 0 schreiben wohingegend der Rest weiterhin 1 bleibt.

1111 1111 vorher
1111 1011 shift 0<<2
---------- logisches &
1111 1011


Mein PortB müsste also nach der Operation dem shiften
PortB so 1111 1011 aussehen.

Doch alle LEDs bleiben einfach an.

Hat jemand eine Idee?


Danke
Kesandal

Ceos
19.05.2011, 13:11
jein ^^

du schiebst eine 0 um 2 stellen nach links ...

(0<<2) == 0b0000000_0_ -> 0b00000_0_00

da kannst du nullen schieben so viel wie du willst ^^

die operation die du suchst ist das negieren '~'

PortX = PortX & ~(1<<2)

~(1<<2) == 0b0000000_1_ -> 0b00000_1_00 -> 0b11111_0_111

EDIT: Nur nachträglich zur Erklärung, beim shiften wird der Inhalt der Variable (in dem Falle eine 0, die 8 Stück Nullbits entspricht) um die angegebene Zahl Stellen nach Links bzw. Rechts verschoben, und freiwerdende Stellen werden mit weiteren Nullen aufgefüllt (immer). Daher muss man um einzelne Bits aus einer anderen Zahl zu löschen, erst die entsprechenden Stellen über SHIFT und ODER Operationen auf 1 setzen und dann die ganze Zahl negieren und mit UND die Bits aus der Zielzahl so ausmaskieren.

Wenn ich mehrere Bits löschen will, sieht das dann so aus:

PortX &= ~( (1<<2) | (1<<4) | (1<<7) );

alternativ ginge auch

PortX &= ~(37<<2);

aber so verliert man schnell die Übersicht!

Kesandal
19.05.2011, 22:27
Hallo,
danke für Deine Antwort.

Ich habe das Lauflicht nun so gelöst:



for(counter=0;counter<8;counter++){
tmp = ~PORTB;
tmp = 1<<counter;
PORTB = ~tmp ;
}


Damit läuft das Lauflicht zumindest schonmal von rechts nach links.

Von links nach rechts klappt es aber nicht.

Kann es sein, dass es nicht möglich ist nach rechts zu shiften?

Mein Ansatz als Test war der folgende:



PORTB = 0xFF;

tmp = ~PORTB;
tmp = (1>>2);
PORTB = ~tmp;


Damit müsste das doch eigentlich klappen...
Ergebnis: alle LEDs sind aus.

Ceos
20.05.2011, 07:45
das Ergebnis bei dir ist auch nur logisch, eine Dezimale 1 entspricht 0b0000000_1_, wenn du jetzt nach rechts schiebst, fällt die 1 ins Nirvana und alles steht wieder auf 0

was du brauchst wäre in dem Fall 0b_1_0000000 -> 0x80 -> (128>>n)

ich geb dir mal ein beispiel für ein Lauflicht, bei dem man einfach die LED direkt manipuliert und nicht erst übern Counter geht!



#define LEFT 1
#define RIGHT 2
...
PORTB = 1;
unsigned char direction = LEFT;
while(1)
{
if(PORTB == 0x80) direction = RIGHT;
else if (PORTB == 0x01) direction = LEFT;
else {
if(direction == RIGHT) PORTB = (PORTB>>1);
if(direction == LEFT) PORTB = (PORTB<<1);
'PAUSE' // es gibt in der delay.h eine wait_ms(long) funktion mit der du millisekundenlange Pausen einbauen kannst, würde ich bei mehr Erfahrung durch eine timergesteuerte Variable ersetzen!
}
}
so haste n Knight-Rider-Licht