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

[ATMEGA32][C] PCF8574 - jak skomunikować po I2C?

03 Wrz 2008 12:14 7835 22
  • #1 5502062
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #2 5502079
    snow
    Poziom 31  
    Na 10 str. masz wyjaśnione jak coś zapisać do PCF'a.
    Przede wszystkim przy zapisie adres PCF'a ci się nie zgadza - bit0 musi być 0 a u ciebie jest 1. No i zapis bitowy zmiennej inaczej się w C oznacza.
  • #3 5502102
    bobbyAIR
    Poziom 20  
    
    #include <util/twi.h>
    #define PCFADDR 0x40
    #define TW_STOP() 	TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
    unsigned char ReadPcf(unsigned char);
    void SetPcf(unsigned char,unsigned char);
    unsigned char ReadPcf(unsigned char pcf){ // pcf to numer ukladu definiowany na liniach A[0-2]
      unsigned char data;
    	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);     //  START
    	while (!(TWCR & (1<<TWINT)));               //  czekanie na koniec transmisji
    	if (TW_STATUS != TW_START) {TW_STOP();return 0x00;}
    
    	TWDR = PCFADDR|TW_READ|(pcf<<1);             // adres slava, zapis
    	TWCR = (1<<TWINT) | (1<<TWEN);              // transmisja adresu	
    	while (!(TWCR & (1<<TWINT)));               // czekanie do zakonczenia transmisji
    	if (TW_STATUS != TW_MR_SLA_ACK) {TW_STOP();return 0x00;}
    
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while (!(TWCR & (1<<TWINT)));
    	if (TW_STATUS != TW_MR_DATA_NACK){TW_STOP();return 0x00;}
    	data = TWDR;
    	TW_STOP();
    	return data;
    }
    
    void SetPcf(unsigned char pcf,unsigned char value){// pcf to numer ukladu definiowany na liniach A[0-2]
    
    	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);     //  START
    	while (!(TWCR & (1<<TWINT)));               //  czekanie na koniec transmisji
    	if (TW_STATUS != TW_START) {TW_STOP();return;}
    
    	TWDR = PCFADDR|TW_WRITE|(pcf<<1);             // adres slava, zapis
    	TWCR = (1<<TWINT) | (1<<TWEN);              // transmisja adresu	
    	while (!(TWCR & (1<<TWINT)));               // czekanie do zakonczenia transmisji
    	if (TW_STATUS != TW_MT_SLA_ACK) {TW_STOP();return;}
    
    	TWDR = value;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while (!(TWCR & (1<<TWINT)));
    	if (TW_STATUS != TW_MT_DATA_ACK){TW_STOP();return;}
    
    	TW_STOP();
    
    
    }
    
  • #4 5502129
    Konto nie istnieje
    Konto nie istnieje  
  • #6 5502191
    Konto nie istnieje
    Konto nie istnieje  
  • #8 5502220
    Konto nie istnieje
    Konto nie istnieje  
  • #10 5502528
    Konto nie istnieje
    Konto nie istnieje  
  • #12 5502758
    bobbyAIR
    Poziom 20  
    raczkujacy napisał:

    Zworki mam obecnie w stanie A0-1, A1-0, A2-1.

    to daje liczbę 5 czili to PCF o adresie 5 dla funkcji którą ci dałem (sama we wnętrzu zna adres bazowy PCF bo jest dla niego dedykowana) czyli wywołanie to
    
    SetPcf(0x05,0x00);
    

    A kod dziala na pewno bo działa w niejednej mojej aplikacji ;)
  • #14 5502926
    Konto nie istnieje
    Konto nie istnieje  
  • #15 5503042
    bobbyAIR
    Poziom 20  
    Ja bym dał 10k. Do tego sprawdz ustawienia TWI, moj kod nie inicjuje interfjesu, trzeba dac jeszcze
    
    ///I2C
    #define TWI_BAUD 153600ul          // wiecej nie pociagnie jako master
    /// SCLf = CPUf/(16 + 2*TWBR*4^TWPS)
    #define TWI_CONST (F_CPU/(8ul*TWI_BAUD)-2)
    

    i potem
    
    /// TWI(I2C) dla pamieci
    TWBR = (unsigned char)TWI_CONST; // ustawienie baud rate
    

    W rejestrach DDRC i PORTC nic nie ustawiaj, Interfejs I2C sam kontroluje piny
  • #16 5503218
    Konto nie istnieje
    Konto nie istnieje  
  • #18 5505346
    bobbyAIR
    Poziom 20  
    A od kiedy standard I2C definiuje opornik podciągający? Bo ja wiem, że tylko impedancję linii.

    A z ciekawości z jaką częstotliwością pracuje twój kontroler? Bo kod
    
    ///I2C
    #define TWI_BAUD 153600ul          // wiecej nie pociagnie jako master
    /// SCLf = CPUf/(16 + 2*TWBR*4^TWPS)
    #define TWI_CONST (F_CPU/(8ul*TWI_BAUD)-2) 
    

    jest dla 14.7456 MHz. Jeśli masz mniejsza częstotliwość trzeba proporcjonalnie zwolnić magistralę i2c
  • Pomocny post
    #20 5505474
    bobbyAIR
    Poziom 20  
    Nie, mój błąd. Chodziło mi o
    
    Note: TWBR should be 10 or higher if the TWI operates in Master mode. If TWBR is lower than
          10, the master may produce an incorrect output on SDA and SCL for the reminder of the
          byte. The problem occurs when operating the TWI in Master mode, sending Start + SLA
          + R/W to a slave (a slave does not need to be connected to the bus for the condition to
          happen).
    

    więc przyspieszenie magistrali

    EDIT:
    Nie dobrze mówię. Przy kwarcu 14.7456 jest częstotliwość magistrali 153,6 kHz ( oczywiście maksymalna przy jakiej pracuje ona prawidłowo ) daje to TWBR =10. Aby uzyskać taką częstotliwość dla np kwarcu 7.3728 MHz trzeba by wpisać do rejestry TWBR wartość 5. Jednak minimum w trybie master to wartość 10 więc magistrala MUSI pracowac dwa razy wolniej aby pracowała poprawnie. Więc może trzeba zwolnic magistralę (na pewno jeśli kwarc kolegi jest mniejszy niż 14,7456).
  • #21 5507939
    Konto nie istnieje
    Konto nie istnieje  
  • #23 5517554
    Konto nie istnieje
    Konto nie istnieje  
REKLAMA