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

[ATmega8]Rezystor sterowany cyfrowo

mateo19851 13 Lip 2010 23:35 1764 5
REKLAMA
  • #1 8289569
    mateo19851
    Poziom 16  
    Witam

    Chciałem zrobić cyfrowe sterowanie głośnością w oparciu o układ DS1806. Nie mogę go rozgryźć. Sterowanie wprowadzaniem danych podpiąłem do portów ATmegi8 poprzez rezystory 20k w kolejności : Din=PC2, CLK=PC3, RST=PC4.
    Po włączeniu zasilania DS1806 ma same zera rejestrach a ja chciałbym (w ramach dobrego początku) wpisać same jedynki w przerwaniu INT0.
    Napisałem program, który niestety nie wywołuje pożądanego skutku :

    
    #define F_CPU 1000000UL
    #include <avr/io.h>                
    #include<util/delay.h>
    #include<avr/interrupt.h>
    void inicjalizacja(void);
    
     
    int main(void) 
    { 
    	inicjalizacja();
    	
    	while(1){
    
    	}
    	return 0;
    } 
    
    ISR(INT0_vect){
    	_delay_ms(30);
    	//ustawienie resetu w stan wysoki
    	uint8_t licznik1=0;
    	uint8_t licznik2=0;
    	PORTB|=_BV(PB0);
    	//RST w stan wysoki
    	PORTC|=_BV(PC4);
    	_delay_us(50);
    	do{
    	
    		do{
    			PORTC|=_BV(PC3);
    			_delay_us(20);
    			
    			PORTC|=_BV(PC2);
    			licznik1=licznik1+1;
    			
    			PORTC&=~_BV(PC3);
    			_delay_us(20);
    		}while(licznik1<=7);
    	licznik1=0;
    	licznik2=licznik2+1;
    	}while(licznik2<=6);
               licznik2=0;
    	PORTC&=~_BV(PC4);
    	PORTB&=~_BV(PB0);
    }
    
    
    void inicjalizacja(void){
    
    /*ustawienie portów do komunikacji*/
    /*dioda PB0 sygnalizuje transfer bitow*/	
    	DDRB|=_BV(PB0);
    	PORTB&=~_BV(PB0);
    	
    	DDRC|=_BV(PC2);
    	DDRC|=_BV(PC3);
    	DDRC|=_BV(PC4);
    	
    	PORTC&=~_BV(PC2);
    	PORTC&=~_BV(PC3);
    	PORTC&=~_BV(PC4);
    /********************************************/
    	/*ustawienie przerwania INT0 
    	aktywne zboczem opadającym*/
    	DDRD&=_BV(PD2);
    	PORTD|=_BV(PD2);
    	sei();
    	MCUCR|=_BV(ISC01);
    	MCUCR&=~_BV(ISC00);
    	GICR|=_BV(INT0);
    	/*koniec ustawiania przerwania int0*/
    /********************************************/
    	
    }
    


    Co mogę robić źle, proszę o podpowiedź.

    Pozdrawiam
  • REKLAMA
  • #2 8289911
    arturt134
    Poziom 27  
    1. Twoja procedura obsługi przerwania jest znakomitym przykładem jak nie powinno się tego robić. Procedury obsługi przerwań muszą być tak krótkie jak to możliwe. Dawanie operacji typu delay_ms jest nieporozumieniem.
    2. W przerwaniu ustawiaj tylko flagę (nie zapomnij zdefiniować jej jako volatile), a w programie głównym sprawdzaj, czy jest ona ustawiona. Jeżeli tak, to wykonaj to co masz w przerwaniu i skasuj flagę.
    3. Inicjalizacja. Najpierw daj cli(), potem ustaw pin jako wejście, wybierz zbocze, później odblokuj przerwanie w GICR, skasuj flagę od przerwania, (bo twoje manipulacje mogły wywołać to przerwanie), a dopiero na koniec daj sei().
    4. Czemu służy sterowanie portem PB0? Nie napisałeś do czego jest on dołączony.
    5. Dlaczego nie wykorzystałeś SPI do transmisji? Miałbyś o wiele prościej.
    6. Czy przerwanie na pewno się wykonuje?
  • REKLAMA
  • #3 8289923
    flapo213
    Poziom 21  
    Witam,

    Zgadzam sie z poprzednikiem w przerwaniu powinno być wyłącznie tyle ile jest to niezbędnie konieczne najlepiej jedynie flagę, absolutnie żadnych delay-i !
  • REKLAMA
  • #4 8289933
    ktrot
    Poziom 20  
    Nie możesz wysyłać samych jedynek bo nic nie uzyskasz - w 1806 dwa najstarsze bity ustawione na 11 powodują, że wartość rejestru nie jest zmieniana (czyli w twoim przypadku zostają same zera). Ponadto bit danych jest zatrzaskiwany na rosnącym zboczu zegara, sprawdź wewnętrzną pętlę do while - tak naprawdę wysyłasz bajt 11111110 a nie same jedynki. To 11 na najstarszych bitach będzie wygodne do stosowania gdy będziesz chciał zmienić tylko niektóre nastawy pozostawiając inne bez zmian.
  • REKLAMA
  • #5 8289936
    Nagus
    Poziom 27  
    Podstawową rzecz, którą robisz źle to nie czytasz kart katalogowych!!
    W nocie DS-a jak wół jest napisane, że wartości 11 bitów 6 i 7 oznaczają: "Do not load wiper value"

    Wywal te wielkie rezystory z portu komunikacji. Jeśli już muszą być to wystarczą 1k.
    Używanie sprzętowego SPI może być ryzykowne, bo łatwo się pomylić w konfiguracji, a i port jest tylko SPI-podobny. Z drugiej strony sterowanie na piechotę bardzo łatwo się koduje na podstawie przebiegów czasowych.
    Pozostałe uwagi jak kolega Arturt134.
  • #6 8290016
    mateo19851
    Poziom 16  
    Przerwanie na pewno się wykonuje, gdyż na port PB0 wysyłam jedynkę która wysterowuje diodę - gdy świeci wiem na pewno, że przerwanie się wykonało.
    Delaye dałem profilaktycznie, robiłem bez nich ale też nie działało. Nie ma wymogu w datasheecie, że przebieg CLK musi być super dokładny.
    Natomiast odnośnie ładowania samych jedynek, doczytałem się oczywiście że jak będą dwie jedynki na początku to nie zmieni pozycji. Spróbuje w takim razie zrobić wszystko jak mówicie na razie bez SPI .
REKLAMA