Skocz do zawartości

Pomocna odpowiedź

Napisano

Mam taki problem a mianowicie poniższy kod kompiluje się ale nie działa jak trzeba.

#include <avr/io.h> 
#define F_CPU        1000000                                      
#define CYCLES_PER_US ((F_CPU+500000)/1000000) 
#define klawiszD DDRD
#define klawiszP PORTD
#define pin PD2
#define LED_ON sbi(DDRB,PB1);sbi(PORTB,PB1) 
void delay(unsigned int us) 

{ 

   unsigned int delay_loops; 

   register unsigned int  i; 

   delay_loops = (us+3)/5*CYCLES_PER_US; 

   for (i=0; i < delay_loops; i++) {}; 

} 

unsigned char klawiatura(void) 

{ 

unsigned char zwrot=0; 

sbi(klawiszD,pin); 

sbi(klawiszP,pin); 

delay(5); 


cbi(klawiszD,pin); 



if(bit_is_clear(klawiszD,pin)) 
{ 

zwrot=zwrot+1; 

} 


return zwrot; 

} 

void zaswiec(void) 

{ 

if(klawiatura()==1) 

                       { 

                       LED_ON; 

                       } 



} 

int main (void) 

{ 

    for (;;) 

  { 
zaswiec(); 

  } 

   return (0);            

}

Rozumiem, że program w ogóle działa, ale nie takiego zachowania oczekiwałeś;

napisz precyzyjnie ( bardzo precyzyjnie !), co twój program powinien robić.

Program miał zaświecić diodą podłączoną do PB1 po naciśnięciu przycisku podłączonego do PD2. Program działa ale dioda świeci cały czas i nie reaguje na przycisk.

Jeśli funkcja 'klawiatura' ma po prostu odczytać stan wyprowadzenia PD2 uC, to bym ją przerobił tak :

/* Stan linii PD2 należy odczytać z rejestru PIND, nie z DDRD */
#define klawiszI PIND    

unsigned char klawiatura(void) 
{ 
  unsigned char zwrot=0; 

   /* Linia PD2 pracuje jako wejście "podciągnięte do jedynki" */
  cbi(klawiszD,pin); 
  sbi(klawiszP,pin);  

       /* Odczyt stanu linii PD2 */
  if(bit_is_clear(klawiszI ,pin)) 
  { 
     zwrot=zwrot+1; 
  } 
  return zwrot; 
}
  • Pomogłeś! 1

Uczę się C na przykładach i innych znalezionych programach. Działa dzięki. Jak wygląda zapis : cbi(klawiszD,pin); sbi(klawiszP,pin); w WinAVR 2007 bo narazie używam 2005

Mała ściąga

zmienna |= _BV(numer_bitu); ustawienie bitu

zmienna &= ~_BV(numer_bitu); zgaszenie bitu

zmienna ^= _BV(numer_bitu); przełączenie bitu

No i przerobiony programik :

#include <avr/io.h> 
#define F_CPU        1000000                                     
#define klawiszD DDRD
#define klawiszP PORTD
#define klawiszI PIND    
#define pin PD2

/* #define LED_ON sbi(DDRB,PB1);sbi(PORTB,PB1) */
#define LED_ON    DDRB|=_BV(PB1);PORTB|=_BV(PB1);  

unsigned char klawiatura(void) 
{ 
  unsigned char zwrot=0; 

  /* Linia PD2 pracuje jako wejście "podciągnięte do jedynki" */

  /*  cbi(klawiszD,pin); */
  klawiszD &= ~_BV(pin); 
  /* sbi(klawiszP,pin);*/  
  klawiszP |= _BV(pin);   

  /* Odczyt stanu linii PD2 */
  if(bit_is_clear(klawiszI ,pin)) 
  { 
     zwrot=zwrot+1; 
  } 
  return zwrot; 
} 
/* Dalej bez zmian */

Używam avr-gcc v4.0.2, więc WinAVR 2007 też powinien powyższy programik “łyknąć”.

  • Pomogłeś! 1

a pętla if(bit_is_clear(klawiszI ,pin)) odczytuje czy na PD2 jest stan niski ? Jak będzie dla stanu wysokiego ?? Czy jeżeli PD2 jest ustawiony jako wejście to czy po podaniu - na ten port będzie on w stanie niskim czy wysokim, podaje się na mikroprocesor tylko - czy także + ??

/* Czy na PD2 jest stan wysoki */
if( bit_is_set(klawiszI,pin) ) 
/* lub tak */  
if( klawiszI & _BV(pin) )

Dalszej części pytania nie rozumiem, może użyjesz konkretnego przykładu

  • Pomogłeś! 1

chodzi o to czy na mikroprocesor mogę na np. PC4 podać + czy nie ??

Jak zrobić aby dana instrukcja była wykonywana przez jakiś czas np. sbi(DDRB,PB1) przez 10s ????

Co zrobić aby w/w programie dioda świeciła tylko gdy przycisk będzie trzymany, jak puszcze to gaśnie ??

Gdzie mogę znaleźć programy dla uC w C wraz z opisami ??

Wbiję się do dyskusji.

Kolego Turboasm proponuję zakupienie TEGO oraz jakiejś książki z BTC z programowaniem w C(zależnie od tego co chcesz programować). Sam niedawno zaczołem zabawę z programowaniem w C właśnie na tym zestawie.

Pozdrawiam Decado

Sory za OT

Hmm a jaką książkę polecasz ?? Bo ja dla mnie to najlepsza pytania i odpowiedzi no i jeszcze przykłady.

PS. Byłbym bardzo wdzięczny za odp. na powyższe pytania.

chodzi o to czy na mikroprocesor mogę na np. PC4 podać + czy nie ??

Oczywiście,że można na porty we/wy AVRa podawać napięcie odpowiadające niskiemu lub wysokiemu stanowi sygnału cyfrowego, ale tylko, gdy dana linia portu pracuje jako wejście, w przeciwnym razie można uszkodzić port.

Żeby skonfigurować którąś linię portu jako wejście, należy wyzerować odpowiadający tej linii bit w rejestrze DDRx (gdzie x to A,B,C,D); gdy bit jest ustawiony (ma wartość 1), linia portu pracuje jako wyjście. Po starcie uC AVR wszystkie linie portów we/we są skonfigurowane jako wejścia.

Następnie można sprawdzić stan na wyprowadzeniu uC badając wartość odpowiedniego bitu w rejestrze PINx.

Przykład:

/* Zeruje bit nr. 4 rejestru DDRC- linia PC4 ma pracować jako wejście*/
DDRC &= ~ _BV(PC4); 
/* Odczyt wartość bitu nr.4 w rejestrze PINC */
/* Czy na PC4 jest stan wysoki? /
if( bit_is_set(PINC,PC4) ) 
/* Czy na PC4 jest stan niski? / 
if( bis_is_clear(sfr,bit) )

Dodatkowo, jeśli port pracuje jako wejście i odpowiedni bit w rejestrze PORTx ustawi się na wartość 1, to linia ta będzie wewnętrznie "podciągnięta" przez rezystor do zasilania (ang. with internal pull-up resistors).

Tak jest w twoim programiku; do PD2 przyłączony został przycisk zwierający wyprowadzenie do masy. Gdy przycisk jest zwolniony, to na wejściu jest stan wysoki mimo, że przycisk nie podaje napięcia odpowiadającego wysokiemu stanowi sygnału; natomiast po wciśnięciu przycisku, wyprowadzenie PD2 zostaje zwarte do masy i na wejściu odczytuje się 0.

DDRD &= ~ _BV(PD2); /* Zeruje bit nr 2 rejestru DDRD,  linia PD2 będzie wejściem */
PORTD |= _BV(PD2);  /* Ustawia  bit nr.2 rejestru PORTD, wyprowadzenie PD2 będzie wewnętrznie podciągnięte przez rezystor do zasilania */
Jak zrobić aby dana instrukcja była wykonywana przez jakiś czas np. sbi(DDRB,PB1) przez 10s ??

Jeśli, na przykład, chcesz, żeby dioda przyłączona do PB1 zapaliła się i świeciła przez 10s, po czym na powrót zgasła, można to zrobić tak: zapalasz diodę, czekasz 10 sek., gasisz diodę - czy o to Ci chodziło ? Jeśli tak, to program poniżej dokładnie to robi.

#define F_CPU  1000000L	          /* Częstotliwość kwarcu */
#include <avr/io.h> 
#include <util/delay.h>			  /* Żeby można było korzystać z funkcji  '_delay_ms'  */

int main(void) 
{ 
  int i; /* zmienna przyda się w pętli 'for' */

  /* Ustawia bin nr. 1 rejestru DDRB, linia PB1 będzie wyjściem */
  DDRB  |= _BV(PB1); 

  /* Ustawia  bit nr.1 rejestru PORTB, na wyprowadzeniu PB1 pojawi się stan wysoki  */
  PORTB |= _BV(PB1); 

  /* Wykonanie tego fragmentu zajmie uC 10s */
  for (i = 0; i < 10*100; i++) 
               _delay_ms(10);      /* Każdym razem wykonanie funkcji  "_delay_ms" zajmie uC  10ms */

  /* Kasuje bit nr.1 rejestru PORTB, na wyprowadzeniu PB1 pojawi się stan niski */
  PORTB &= ~_BV(PB1); 

  while(1){};  /*  Nieskończona pętla "uwięzi" program w tym miejscu */ 

  return 0; 
} 
Co zrobić aby w/w programie dioda świeciła tylko gdy przycisk będzie trzymany, jak puszcze to gaśnie ??

Przerób funkcję 'zaswiec()' w ten sposób:

#define LED_OFF    DDRB|=_BV(PB1);PORTB&=~_BV(PB1);  

void zaswiec(void) 
{ 
   if(klawiatura()==1) 
   { 
      LED_ON; 
   } 
   else
   { 
      LED_OFF; 
   } 
} 
Gdzie mogę znaleźć programy dla uC w C wraz z opisami ??
  • Pomogłeś! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...