Programownie w C

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 12 lip 2009, 11:25

Tak

Awatar użytkownika
Tranzystor
Użytkownik
Posty: 889
Rejestracja: 28 sie 2005, 19:19
Lokalizacja: Świętochłowice
Kontakt:

Post autor: Tranzystor » 12 lip 2009, 11:35

No właśnie ;)
& oznacza iloczyn logiczny (bramka AND),
| oznacza sumę logiczną (bramka OR),
^ jest bramką XOR,
~ jest negacją czyli bramka NOT.

Jeżeli chodzi o zapis:

Kod: Zaznacz cały

DDRB |= _BV(DDB7);
to jest on równoznaczny z zapisem:

Kod: Zaznacz cały

DDRB = DDRB | _BV(DDB7);
Myślę, że teraz wszystko jasne :?:

Pozdrawiam ;)

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 12 lip 2009, 11:39

A jak się nie chce stosować tych operatorów to można sobie pisać przykładowo:

Kod: Zaznacz cały

DDRB=0b01011100;
wtedy każda cyfra po "b" oznacza jeden bit rejestru DDRB, czyli każdy pin portu B. Tyle że wtedy trzeba pamiętać o tym żeby po 0b było 8 cyfr. Tyle że taki zapis ma wadę że zmieniamy na raz cały rejestr a przy pomocy operatorów bitowych operujemy w danym momencie tylko na jednym bicie rejestru pozostałe zostawiając w spokoju.

Awatar użytkownika
Tranzystor
Użytkownik
Posty: 889
Rejestracja: 28 sie 2005, 19:19
Lokalizacja: Świętochłowice
Kontakt:

Post autor: Tranzystor » 12 lip 2009, 11:41

Owszem, jednak stosując operacje logiczne zmieniasz tylko jeden bit. A tak zmieniasz całość.

Banan
-
Posty: 10
Rejestracja: 11 lip 2009, 23:15
Lokalizacja: Pisz
Kontakt:

Post autor: Banan » 12 lip 2009, 11:43

AND czyli symbol "&" jest przydatny do przykładania maski, zerowania bitów
np na PORTB mamy stany 10011111 i załóżmy że chcemy wyzerować najstarszy i najmłodszy bit a pozostałe pozostawić bez zmian:
tworzymy maskę ~((1<<7)|(1<<0)) która binarnie wygląda tak 10000001 a po negacji (tej prze nawiasem) wyglądać to będzie tak 01111110
teraz robimy iloczyn logiczny:
10011111
& 01111110
--------------
00011110
OR jest niezastąpione do ustawiania bitów np 10011111 chcąc ustawić przedostatni bit (patrząc od najstarszego) tworzymy maskę 1<<6 czyli 01000000

10011111
| 01000000
--------------
11011110

Zapis PORD |=1<<6 jest tożsamy z zapisem PORD =PORTD | 1<<6
Jest to przypisanie wartości operacji sumy logicznej do PORTD z maską 1<<6 na PORTD :P

Polecam jeszcze raz przerobienie przykładów operacji bitowych z pliczku, który polecałem wcześniej w dowolnym kompilatorze np Dev C++ czy C++ Builder.
Powinno to wszystko rozjaśnić

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 12 lip 2009, 12:04

Dzieki wielkie teraz rozumiem. Jesteście lepsi niż jakikolwiek kursl w necie :mrgreen:

Awatar użytkownika
DarkJarek
-
Posty: 44
Rejestracja: 21 mar 2006, 15:48
Lokalizacja: ...
Kontakt:

Post autor: DarkJarek » 12 lip 2009, 15:51

Najprościej to chyba będzie pokazać na przykładzie.

Weźmy PORTB = 48 (00110000b w zapisie bitowym) przy czym wszystkie nóżki są wyjściami. Chcemy zapalić diodę podłączoną do pinu nr 2 PORTB. Tworzymy maskę (1<<2) = 4 (00000100b). Na koniec robimy operację sumy logicznej:

00110000b
00000100b
-----------
00110100b

W przypadku gdy chcemy wygasić bit nr 5 tworzymy odwróconą maskę ~(1<<5) = ~(00100000b) = 11011111b. ~ jest operatorem negacji logicznej. I jeszcze iloczyn logiczny:

00110000b
11011111b
-----------
00010000b

Prościej to już się chyba tego nie da wytłumaczyć.

//edit: za wolno posty piszę :p

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 12 lip 2009, 19:56

Czyli jeśli dobrze zrozumiałem jeśli mam np

Kod: Zaznacz cały

PORTB=125       bitowo 01111101
i chce zmienic tylko 4 i 5 bit to tworze maske 
PORTB&=~(1<<4) | (1<<5)
Jesli dobrze to chwała wam jeśli nie to się pochlastam :mrgreen: . Kolega Banan popełnił mały błąd chyba bo odwrócona maska ~(1<<5) to bitowo 11101111 :wink:

Awatar użytkownika
DarkJarek
-
Posty: 44
Rejestracja: 21 mar 2006, 15:48
Lokalizacja: ...
Kontakt:

Post autor: DarkJarek » 12 lip 2009, 20:11

Rozumiem, że chciałeś wyzerować bity, lecz popełniłeś drobny błąd: brak nawiasów. Poprawnie powinno wyglądać tak:

Kod: Zaznacz cały

PORTB &= ~((1<<4) | (1<<5))
'~' ma wyższy priorytet i zostało by wykonane wcześniej niż '|'.

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 12 lip 2009, 20:14

Kurde zakapowałem :mrgreen: ten nawias to tylko przeoczenie.

Banan
-
Posty: 10
Rejestracja: 11 lip 2009, 23:15
Lokalizacja: Pisz
Kontakt:

Post autor: Banan » 12 lip 2009, 21:17

Dobrze napisałem:P Do zerowania bitów stosujemy iloczyn logiczny i zanegowaną maskę (tam gdzie chcemy wyzerować tam zera)

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 12 lip 2009, 21:27

Przepraszam chodziło mi o DarkJarka. W każdym razie jeszcze raz dzięki za pomoc.Pozdrawiam

Awatar użytkownika
DarkJarek
-
Posty: 44
Rejestracja: 21 mar 2006, 15:48
Lokalizacja: ...
Kontakt:

Post autor: DarkJarek » 12 lip 2009, 22:13

Nie popełniłem błędu ~(1<<5) to 11011111b. Proszę sobie dokładnie sprawdzić ;)

_Brutus
-
Posty: 26
Rejestracja: 01 gru 2006, 16:08
Lokalizacja: Złotopole / Łódź
Kontakt:

Post autor: _Brutus » 14 lip 2009, 16:55

Zobacz. Operacje na bitach są proste ;)

W skrócie. Jeśli chcesz ustawić jakiś bit, to musisz do niego dodać 1, czyli operacja bitowa OR. Nie ważne, czy wartość początkowa będzie 0 czy 1, to zawsze wynik dodawania będzie 1. ;) np

Kod: Zaznacz cały

00100100 | 00000001 = 00100101
. Ustawiamy najmłodszy bit ;) np.

Kod: Zaznacz cały

PORTC = PORTC | 0x01;
Można dołożyć do tego jeszcze przesunięcie bitowe w lewo. Chcemy ustawić bit 5.

Kod: Zaznacz cały

00000001 << 5 = 00100000
Co daje razem ustawianie bitu 6 portu C.

Kod: Zaznacz cały

PORTC = PORTC | (1<<5);
Co w skrócie można zapisać jako:

Kod: Zaznacz cały

PORTC |= (1<<5);
Jeśli chcesz bit wyzerować, to musisz pomnożyć go przez 0, bo mnożenie przez 0 zawsze daje wynik 0. Bitowa funkcja AND. Obejrzyj sobie w necie tabelki prawdy tych funkcji, jeśli ich nie znasz.

Przykład zerowania bitu 4 portu C:

Kod: Zaznacz cały

PORTC &= (1<<4)
Czyli dla przykładu wartość rejestru PORTC przed i po operacji.

Kod: Zaznacz cały

00111101 & 00010000 = 00101101 

kaliska5
Użytkownik
Posty: 348
Rejestracja: 01 maja 2008, 8:24
Lokalizacja: z nienacka
Kontakt:

Post autor: kaliska5 » 16 sie 2009, 11:36

Nie chce zakładać nowego tematu wiec napisze w starym(temat pasuje).Chce użyć timera1 jako czasomierza.Stworzyłem zlepek z kilku programów z sieci i kursów chciałbym aby mi to ktos sprawdził i w razie potrzeby pomógł.Proszę o wyrozumiałość :smile:

Kod: Zaznacz cały

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#define OSC 8



char jednostki_sekund = 0
char dziesiatki_sekund = 0
char jednostki_minut = 0
char dziesiatki_minut = 0
char jednostki_godzin = 0 
char dziesiatki_godzin = 0



SIGNAL (SIG_OVERFLOW1) 
{
TCNT1H = 0x0B;
TCNT1L = 0xDC; 
 
czas();
}


void czas(void)
{
jednostki_sekund++; 
if(jednostki_sekund == 10) 
{
jednostki_sekund = 0; 
dziesiatki_sekund++;  
if(dziesiatki_sekund == 6)
{
dziesiatki_sekund = 0; 
    jednostki_minut++; 
    if(jednostki_minut == 10)
      {
      jednostki_minut = 0;
      dziesiatki_minut++; 
      if(dziesiatki_minut == 6) 
        {
        dziesiatki_minut = 0; 
        jednostki_godzin++;
        if((dziesiatki_godzin == 2) && (jednostki_godzin == 4)) 
          {
          dziesiatki_godzin = jednostki_godzin = 0; 
          }
        if(jednostki_godzin == 10) 
          {
          jednostki_godzin = 0; 
          dziesiatki_godzin++; 
          }
        }
      }
    }
  }
}



int main(void)
{

DDRB = 0xFF;
DDRD = 0xFC;
PORTB = 0xFF;
PORTD = 0xF7;

TCCR0A = 0x04;
TCCR1B = 0x03;


TCNT0 = 128;

TIMSK = 130;
TCCR1B = _BV(CS10)|_BV(CS12|~_BV(CS11); // preskaler 1024

sei();//globalne zezwolenie na przerwania 

while(1);
return 0;
}
 

ODPOWIEDZ