logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATMEGA][C] kopiow. flagi do portu - problem początkującego

gafek 14 Mar 2009 08:22 1319 2
REKLAMA
  • #1 6279169
    gafek
    Poziom 17  
    Witam,

    zaczynam dopiero w AVR GCC, więc pytam, bo nie znalazłem odpowiedzi na forum.

    Jest sobie struktura,która składa się z 4 bitów. Te cztery bity mają być ustawiane i kasowane co pewien okres czasu przez przerwanie.
    Wartości tych bitów mają potem być kopiowane na odpowiednie piny portu D.
    
    #include<avr/io.h> 
    #include <avr/interrupt.h> 
    #include <avr/signal.h> 
    #include <inttypes.h> 
    #define F_CPU 1000000 
    
    unsigned long counter=0; 
    
    struct {
    
    unsigned int f05hz : 1;
    unsigned int f1hz  : 1;
    unsigned int f2hz : 1;
    unsigned int f4hz : 1;
    
    } flash;
    
    int main(void) 
    { 
    
      TCCR0 = 0x03; //presc. 1024 
      TIMSK |= (1 << TOIE0); 
      TCNT0 = 0; 
      sei(); 
     
      DDRD |= _BV(PD3); 
      PORTD &= ~_BV(PD3); 
    
    	while(1)
    	{
    	PORTD |= (flash.f05hz << PD3); 
      	PORTD |= (flash.f1hz << PD2);
    	} 
    } 
    
    
    
    SIGNAL (SIG_OVERFLOW0) 
    { 
     
    if (!(counter%16)) flash.f05hz=~flash.f05hz;
    if (!(counter%32)) flash.f1hz=~flash.f1hz;
    if (!(counter%64)) flash.f2hz=~flash.f2hz;
    if (!(counter%128)) flash.f4hz=~flash.f4hz;
    
    counter++;
    
    } 
    

    Przerwanie działa ok ,bo gdy zamiast:
    
    flash.f05hz=~flash.f05hz; 
    


    wstawię
    
    PORTD ^= (1 << PD3); 
    


    wszystko gra i led błyska co ileś tam przerwań. Ale chciałbym aby w tle "tykały" sobie flagi a nie bezpośrednio piny portów ,a w razie potrzeby kopiować te flagi na port.

    Może ktoś spojrzy na kod i pomoże....

    Program do niczego nie służy. Jedynym jego celem jest to by się czegoś nauczyć.

    Pozdr.
    A.
  • REKLAMA
  • #2 6279342
    BoskiDialer
    Poziom 34  
    Błąd masz tego rodzaju, że przypisanie do PORTD powoduje tylko ustawienie danego pinu (jeśli bit flash.f* jest ustawiony), nie ma możliwości skasowania bitu. Musiał byś przypisania zamienić na takie:
    PORTD = (PORTD & ~(1 << PD3)) | (flash.f05hz << PD3);

    lub:
    if(flash.f05hz)
      PORTD |= (1 << PD3);
    else
      PORTD &=~(1 << PD3);


    Po poprawieniu tego doznasz kolejnego błędu wynikającego z braku volatile.
  • #3 6279393
    gafek
    Poziom 17  
    Chciałem uniknąć instrukcji warunkowej IF. Praktyka w assemblerze nauczyła mnie operowania na bitach za pomocą operatorów logicznych. Dlatego szukałem rozwiązania innego niż IF.

    Rozumiem ,że zmienne bitowe powinienem zdeklarować jako:
    
    volatile unsigned int f05hz : 1;
    volatile unsigned int f1hz  : 1;
    volatile unsigned int f2hz : 1;
    volatile unsigned int f4hz : 1;
    


    Dziękuję - Działa ! Powiem szczerze, że długo bym myslał na tym Volatile. Po zmianie deklaracji zmiennej działają wszystkie rozwiązania, które próbowałem zastosować. Na logikę wszystko było OK, ale nie działało.

    Rozumiem ,że wszystkie zmienne modyfikowane przez przerwania muszę deklarować jako Volatile.


    A.
REKLAMA