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

[ATtiny26][C] Źródło zegara dla usi (twi) i implementacja

wladziu22 06 Gru 2009 21:44 3401 14
  • #1 7354728
    wladziu22
    Poziom 17  
    Witam.

    Czytam pdf-a w tej sprawie i nie rozumie wyjaśnienia bitów:
    Cytat:
    Bit 3..2 – USICS1..0: Clock Source Select
    w rejestrze USICR.
    Jak kiedyś programowałem i2c na ARMie...to ustawiało się odpowiednie taktowanie tej linii (zakładając ze Masterem był uC ARM a układ docelowy slave to PCF8574N, wówczas ustawiałem max 100kHz). To samo chciałbym osiągnąć za pomocą ATtiny26. Z tego co zrozumiałem (nie jestem advance in English), że mogę albo softowo sam określić jakieś opóźnienie czasowe (które będzie stosowane pomiędzy komendami/bitami transmisji ramki i2c) lub też podłączyć jakieś zewnętrzne źródło zegara lub też użyć Timera0 i jego flagi przepełnienia.
    Dodatkowo znalazłem definicje w jakimś examplu dla ATTiny26, który wykorzystany jest w IAR-e:
    #define SYS_CLK   4000.0  // [kHz]
    
    #ifdef TWI_FAST_MODE               // TWI FAST mode timing limits. SCL = 100-400kHz
      #define T2_TWI    ((SYS_CLK *1300) /1000000) +1 // >1,3us
      #define T4_TWI    ((SYS_CLK * 600) /1000000) +1 // >0,6us
      
    #else                              // TWI STANDARD mode timing limits. SCL <= 100kHz
      #define T2_TWI    ((SYS_CLK *4700) /1000000) +1 // >4,7us
      #define T4_TWI    ((SYS_CLK *4000) /1000000) +1 // >4,0us
    #endif


    Chcąc się na tym wzorować za SYS_CLK powinien przyjąć moje Fosc jakie mam ustawione w ATtiny26 8MHz? Skąd te liczby (1300, 1000000,4700 etc.)?
    Definicje te uzywają w funkcji __delay_cycles(). Zakładam, ze AVR-GCC nie ma jej odpowiednika. Jak wykonać taka funkcję ilości cykli? Użyć iteracji nop; ?
    Proszę o wyjaśnienie.
  • Pomocny post
    #2 7358738
    janbernat
    Poziom 38  
    Nie znam się na ARM ani na C.
    Ale jeśli IAR w examplu twierdzi że ATtiny ma moduł TWI- to twierdzi.
    Żaden ATtiny nie ma modułu TWI- tylko USI.
    To są zupełnie inne moduły.
    USICS0, USICS1 i USICLK określa źródła sygnału taktującego- zewnętrzne lub programowe.
    A nie żadne opóźnienia.
  • Pomocny post
    #3 7360393
    kamyczek
    Poziom 38  
    Usi a twi to nie to samo Większe mikrokontrolery mają osobno twi i spi małe mają uniwersalny moduł zwany USI który może pracować jako i2c(twi) lub spi a w niektórych przypadkach nawet jako UART. jednak jego uniwersalność okupiona jest pewnymi uproszczeniami (czyt. dodatkowymi wymaganiami od programisty) np związanymi z taktowaniem. Proponuje poczytać notę katalogową układu.
  • #4 7360682
    wladziu22
    Poziom 17  
    ale mi pomogliście....
    to czy zewnętrzne czy softowe to kumam ale nie kapuje w jaki sposob nam wykonać owe zródla sygnału. Czym będzie zewnętrzne a czym będzie softowe i jak tego użyć w kodzie.

    A tak na marginesie...czysto softowa interpretacja I2C jest o wiele prostsza niż uruchomienie USI w trybie TWI. Co za idiota to wymyślił :/
  • #5 7360881
    mirekk36
    Poziom 42  
    wladziu22 napisał:
    A tak na marginesie...czysto softowa interpretacja I2C jest o wiele prostsza niż uruchomienie USI w trybie TWI. Co za idiota to wymyślił :/


    Jaki idiota??? taka wypowiedź świadczy tylko o tobie - niestety.

    Już wcześniej ktoś tu ci napisał, że procki ATtiny i nie tylko są wyposażone w moduły USI. Są one na tyle uniwersalne, że można nieco większym nakładem programisty uzyskać ale uważaj! ... sprzętowe TWI, SPI a nawet UART.

    Jeśli ty nie dostrzegasz różnicy w sprzętowej możliwości obsługi takich interfejsów od softwarowej to jeszcze bardzo mało wiesz ale to nie powód do określania pomysłodawców z ATMEL'a mianem idiotów ;) tym bardziej, że nie rozumiesz jak to działa i jak to można nawet wygodnie oprogramować. Przemyśl więc na drugi raz swoje wypowiedzi.

    A tymczasem , gdybyś był łaskaw choć troszkę użyć swoich zdolności do googla (bo to chyba każdy potrafi) to mógłbyś wpaść np na taki fajny przykład użycia USI jako TWI w prockach ATtiny i to nawet w trybie SLAVE.

    Proponuję więc ci poczytaj PDF'y zawarte w tym załączniku poniżej, obejrzyj sobie źródła przykładowych programów i bardzo ciekawych rozwiązań - to może coś ci się w końcu rozjaśni ;)
  • #6 7360891
    kamyczek
    Poziom 38  
    Proponuję książkę "Mikrokontrolery ATMEGA w praktyce"lub (i) "Mikrokontrolery attiny w praktyce" obie z wydawnictwo BTC.
    Te książki rozwiąże wiele twoich problemów są napisane w zrozumiałym języku i rozwiązują wiele zagadnień wraz z przykładami .
  • #7 7361020
    wladziu22
    Poziom 17  
    Cytat:
    Jaki idiota??? taka wypowiedź świadczy tylko o tobie - niestety.

    Jeśli ty nie dostrzegasz różnicy w sprzętowej możliwości obsługi takich interfejsów od softwarowej to jeszcze bardzo mało wiesz ale to nie powód do określania pomysłodawców z ATMEL'a mianem idiotów ;) tym bardziej, że nie rozumiesz jak to działa i jak to można nawet wygodnie oprogramować. Przemyśl więc na drugi raz swoje wypowiedzi.


    Bylem tego pewien, że za chwile ktoś pojedzie po mnie jak po szmacie ;-)
    Zwyczajnie nie kumam tego USI dlatego tak napisałem. Sporo już siedzeniem nad tym i czytałem o USI lecz nie nie chce mi działać.

    Cytat:
    A tymczasem , gdybyś był łaskaw choć troszkę użyć swoich zdolności do googla (bo to chyba każdy potrafi) to mógłbyś wpaść np na taki fajny przykład użycia USI jako TWI w prockach ATtiny i to nawet w trybie SLAVE.

    ojj chłopcze drogi..... Wzorowałem się na tym .. to chyba AVR310 lub AVR312. Nie działało. Zresztą tam bylo strasznie zagmatwane. A ja potrzebuje jedynie rozszerzyć moja ATtiny o kolejny port czyli jedynie wysłać 8 bitów jednorazowo. Na dodatek to nie jest cel mojego wymyślonego projekciku.

    Cytat:
    Proponuję więc ci poczytaj PDF'y zawarte w tym załączniku poniżej, obejrzyj sobie źródła przykładowych programów i bardzo ciekawych rozwiązań - to może coś ci się w końcu rozjaśni Wink

    Dziękuje....lookne w wolnym czasie na to co jest w załączniku.

    Cytat:

    Proponuję książkę "Mikrokontrolery ATMEGA w praktyce"lub (i) "Mikrokontrolery attiny w praktyce"

    Dziękuje za tytuły. Jednak nie skorzystam bo USI (TWI) to tyko ot tak wymyśliłem, by uprościć sobie życie. Reszta rzeczy zawartych w Procku jest banalna, a przynajmniej lepiej wytłumaczona i bez problemu da sie uruchomić.
  • Pomocny post
    #8 7361187
    Nawigator
    Poziom 33  
    USI ma pożyteczny wynalazek w postaci detektora sygnału startu transmisji w I2C ale dla mastera to niepotrzebne.
    Z kolei UART robi się na nim źle bo nie ma możliwosci sprzętowej wysyłki bajtu w kolejności LSB...MSB.
    Ma kilka przerwań i to jest cenne. W nowszych modelach dodany jest drugi rejestr tymczasowy SPDR co ułatwia życie.
    Dałeś wladziu rezystory podciągające na SDA/SCL bo o nich się często zapomina?

    N.
  • #9 7361232
    wladziu22
    Poziom 17  
    Cytat:
    Dałeś wladziu rezystory podciągające na SDA/SCL bo o nich się często zapomina?

    Jasne ze tak. Ja mam swoja płytkę gdzie tylko procki zmieniam a reszta jest stała. Wcześniej na tej płytce już ARMem odpaliłem I2C i na 1000% mam pull-up.
  • #10 7374373
    wladziu22
    Poziom 17  
    Witam,

    przysiadłem do USI (TWI) raz jeszcze i korzystając ze schematu opisanego w: Link oraz z Waszej udostępnionej pomocy w tym poście wygenerowałem kod:

    
    void I2C_Delay_Short(void)
    {
      asm volatile(\
                    "delayus8_loop%=: \n\t"\
                    "nop \n\t"\
                    "dec %[ticks] \n\t"\
                    "brne delayus8_loop%= \n\t"\
                    : :[ticks]"r"(10) );
    
    // DEC - 1 cykl, BRNE - 2 cykle, nop - 1 cykl
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void initMaster(void)
    {							//set USI in Two-wire mode, no USI Counter overflow hold 
    	USICR = (1<<USIWM1)|(1<<USICS1); 	//Shift Register Clock Source = External, positive edge
    							//4-Bit Counter Source = external, both edges 
    	
    	USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF); //clear all interrupt flags
    	PORTB |= (1<<1)|(1<<0);		// SCL i SDA set as input
    	DDRB  |= (1<<1)|(1<<0);		// SCL i SDA set as output high
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void startConSetUpData(unsigned char add,unsigned char rw)
    {
    	PORTB &= ~(1<<0);            // SDA output low
    	USIDR = add|rw;		     // address + 0 bit
    	I2C_Delay_Short();           // min 4.7us (5us)
    	PORTB &= ~(1<<1);		     // SCL output low
    	USISR |= (1<<USISIF);        // clear start con. flag 
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void sendAdd(void)
    {
    	for(char i=0;i<8;i++)        // 8 bits
    	{
    		I2C_Delay_Short();     // min 4.7us (5us)
    		PORTB |= (1<<1);       // relase SCL as output high
    		while(PINB&(1<<1));    // wait for SCL high
    		I2C_Delay_Short();     // min 4.7us (5us)
    		PORTB &= ~(1<<1);      // SCL output low 
    	}
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    unsigned char getAck(void)
    {
    	unsigned char ack;
    
    	USIDR |= (1<<7);             // release SDA
    
    	                             //clock pulse 
    	I2C_Delay_Short();
    	PORTB |= (1<<1);
    	while(PINB&(1<<1));
    	I2C_Delay_Short();
    	PORTB &= ~(1<<1);
    
    	ack = (USIDR & (1<<0));      // get ack
    
    	return ack; 
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void sendData(unsigned char data)
    {
    	USIDR  = data;            // write data to register
    	
         	for(char i=0;i<8;i++)        // 8 bits
    	{
    		I2C_Delay_Short();     // clock pulse
    		PORTB |= (1<<1);
    		while(PINB&(1<<1));
    		I2C_Delay_Short();
    		PORTB &= ~(1<<1);
    	}	
    }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void stop(void)                    
    {
    	I2C_Delay_Short();
    	PORTB |= (1<<1);              // relase SCL as output high
    	while(PINB&(1<<1));           // wait for SCL high
    	I2C_Delay_Short();
    	PORTB |= (1<<0);              // relase SDA as output high	
    }
    //===========================================================================
    //		program glowny
    //===========================================================================
    int main (void)
    {
    
    	initMaster();
    	I2C_Delay_Short();
    
    	do
    	{
    	   startConSetUpData(0x40,0);
    	   sendAdd();
    	}
    	while( !getAck() );
    	
    	do
    	{
    	   sendData(0x0f);
    	}
    	while( !getAck() );
    
    	stop();
    return 0;	
    }
    


    No niestety...na moje nieszczęście nadal procek jako master nie komunikuje się z PCF8574N :/ A powinny być cztery jedynki na wyjściu układu. Nie mam debuggera...a tym bardziej wyprowadzeń na JTaga w ATtiny26, wiec niestety nie podejrzę co się złego dzieje w rejestrach.
    Osoby obyte w temacie proszę o pomoc, sugestię, co mógłbym ewentualnie zmienić lub dodać w tym kodzie.

    Pozdrawiam

    Dodano po 5 [godziny] 2 [minuty]:

    Trochę siedziałem na necie w poszukiwaniu jeszcze czegoś ciekawego, czegoś co by mi jeszcze pomogło. Znalazłem na innym forum o uC informacje o przesuniętym adresie (<<1) i bitach w układzie. Nie wydaje sie Wam to dziwne? Podaje link do informacji: Link
    A wracając do mojego wątku....nikt nie zna USI?
  • #11 7375768
    kamyczek
    Poziom 38  
    Najmłodszy bit adresu informuje o tym czy chcemy odczytać czy zapisać dane zatem wygląda to tak jak by układ miał dwa fizyczne adresy jeden dla odczytu i o jeden wyższy do zapisu i nic w tym dziwnego nie ma.
  • #12 7377380
    wladziu22
    Poziom 17  
    Zgadza się. Akurat dla mojego typu układu będzie 010000000 z tym że LSB jest zerem dla zapisu. Ten sam adres 0x40 używałem dla ARMa i bylo ok. I nie zauważyłem jakiś problemów. Teraz to wszytko dziwnie sie zachowuje. W ogóle pomijając fakt, że nie mogę nadal się skomunikować po i2c, ten expander dodatkowego portu cały czas ma 5V na prawie wszystkich pinach portu. Dokładnie mówiąc podaje 11111110 :/ Dziwne...
  • #13 7377401
    kamyczek
    Poziom 38  
    przydało by się zapiąć analizator i2c i podglądnąc co tam śmiga po magistrali może coś robisz za szybko. Może przekraczasz częstotliwość wysyłania i pcf się gubi ?
  • #14 7379213
    wladziu22
    Poziom 17  
    Tez o tym myślałem, ale nie mam dostępu do oscyloskopu. Fakt, ze kiedyś na studiach takie problemy to tylko oscyloskop rozwiązywał.
  • #15 7379559
    kamyczek
    Poziom 38  
    Do analizy ttl i2c spi itp to najlepszy jest analizator ttl a ponieważ I2C to nie jest zbyt szybkie to najprostszy model da sobie radę ;)
REKLAMA