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

[atmega32][c]Komunikacja między mikrokontrolerami - I2C

michaelpan 03 Cze 2008 22:45 3757 3
REKLAMA
  • #1 5211148
    michaelpan
    Poziom 11  
    Prosze wszystkic forumowiczow o pomoc z nastepujacym probleme:
    Mam program ktory ma za zadanie obslugiwac I2C.
    Chodzi mi o proste przesyłanie bitów za pomoca tego interfejsu, w zasadzie dla wielu jest to trywialna sprawa.
    Jedank mamy z tym problem, nie mozemy uzyskac odp na slave, tzn. po prostym podlaczeniu diód na port ktory ma byc wyjsciem nic nie widzimy, zero reakcji w zasadzie tylko po nacisnieciu resetu obserwujemy jakas reakcjie(reset mastersa, daje efekt na slave).
    Wiem ze moze zaistniec tak sytuacjia ze poprostu nie zuwazymy jak zmieniaja sie wysyłane bity lecz po zastosowaniu funkcji spowolniajacej proces nic nie mozna zuwazyc na slave wiec to raczej nie to.
    Mozliwe ze blad jest u samoego poczatku tzn.
    powismy wysłac w natepujacej kolejnosci start, adres,dana, stop, start adres, dana, stop....
    Ale wtedy nie ma zadnej reakcji na wyswietlaczu.
    KOdy tuch programow to:
    Slave:
    
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <avr/io.h>
    #include <avr/twi.h>
    
    // init slave
    //
    //
    void init_twi_slave (uint8_t addr) {
    
    	//DDRC = 0xff;
    
    	// set slave addr to 1
    	// do not respond to general call
    	TWAR = (addr<<1)|0;
    
    	// enable twi interface and interrupt and acks
    	TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
    	TWCR |= TWSTO;
    }
    
    // recv data
    //
    //
    volatile uint8_t do_things;
    volatile uint8_t value;
    volatile uint8_t index;
    SIGNAL (SIG_2WIRE_SERIAL) {
    
    	// grab the value
    	value = TWDR;
    	//if(value != 2)
    	//reset
    	if(TWSR == 0)
    		TWCR |= TWSTO;
    
    	// do things
    	//do_things = 1;
    	
    	// allow i2c to continue
    	TWCR |= _BV(TWINT);
    	//PORTC = 0xFF;
    }
    
    // print data
    //
    //
    int main (void) {
    
    	init_twi_slave (1);
    	send_init ();
    	DDRB = 0xFF;
    	sei ();
    	do_things = 0;
    	uint16_t sleep;
    	uint8_t i;
    
    	while (1) {
    		PORTB = ~TWSR;
    		if(TWSR == 0)
    			TWCR |= TWSTO;
    	}
    	
    	return 0;
    }
    

    master:
    
    #include <avr/io.h>
    #include <avr/twi.h>
    #include <avr/interrupt.h>
    
    // init master
    //
    //
    void init_twi_master (uint8_t twbr) {
    
    	// set the scl
    	TWBR = twbr;
    	TWCR = _BV(TWEN);
    }
    
    // send data
    //
    //
    int main (void) {
    
    	init_twi_master (13);
    	DDRB = 0xFF;
    	uint16_t sleep;
    	uint8_t i = 1;
    	while (1) {
    		PORTB = ~TWSR;
    		// send start
    		TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
    		while (!(TWCR & _BV(TWINT)));
    		PORTB = ~TWSR;
    		
    		// send the addr
    		TWDR = (1<<1) | 0;
    		TWCR = _BV(TWINT) | _BV(TWEN);
    		while (!(TWCR & _BV(TWINT)));
    		PORTB = ~TWSR;
    		
    		if ((TWSR & 0xF8) != TW_MT_SLA_ACK){
    			//error(TWSR, 0x01);
    		}
    		//while(1){
    			TWDR = i;
    			TWCR = _BV(TWINT) | _BV(TWEN);
    			while (!(TWCR & _BV(TWINT)));
    			PORTB = ~TWSR;
    			
    			if((TWSR & 0xF8) != TW_MT_DATA_ACK){
    				//error(TWSR, 0x02);
    			}
    		//	i++;
    		//}
    		
    		// send stop
    		TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN) | _BV(TWEA);
    		while( !(TWCR & _BV(TWSTO)) );
    		//while (!(TWCR & _BV(TWINT)));
    		PORTB = ~TWSR;
    		//sleep = 65535;
    		//while(sleep--);
    		//TWCR = TWCR & ~(_BV(TWEN));
    		i++;
    	}
    	
    	return 0;
    }
    


    Prosze o jakas pomoc.
    Wiem ze lopalotogicznie opisalem problem lecz z moja wiedza w tym temacie jest slabo, nawet bardzo...
    pozdrawiam


    >Proszę dostosować się do p.15 regulaminu i poprawić treść wiadomości<
    Zmieniłem tytuł.
    [zumek]
  • REKLAMA
  • #2 5254391
    mieciomiecio
    Poziom 12  
    sprawdź TWSR bo wydaje mi sie ze ostatnie 2 bity to preskaler. A ty go wogule nie ustawiasz, wiec wydaje mi sie ze nie bierzesz go pod uwagę w innych wyliczeniach np. szybkości transmisji.
  • REKLAMA
  • #4 9092673
    jankes3d
    Poziom 11  
    Witajcie, widzę, że dawno tu nikt nic nie naskrobał ;)

    Znalazłem się w dość nieciekawej sytuacji i czas ucieka mi między palcami jak nie powiem co.

    Mój problem rysuje się podobnie jak kolegom na wstępie. Naskrobałem kod do obsługi Master Transmitter AtMegi32, lecz ciężko mi coś spłodzić w części Slave Receiver AtMegi168p. Bo chodzi mi o przesłanie pewnej liczby z jednej do drugiej AtMegi. Jeśli chodzi jak często ma dochodzić do wysyłania to liczba jest wynikiem pomiaru. Tak więc gdy owy pomiar nastąpi to ma go wysłać do drugiego uC.

    Master Transmitter:
    
    #define   F_CPU 16000000UL 
    #define SCL_CLOCK  100000L			//Czestotliwosc magistrali I2C
    //-------------------------------------------------------------------------------------------------
    // Transmisja i2c / TWI
    //-------------------------------------------------------------------------------------------------
    void TWI_INIT(){
    //	TWAR = (1<<TWA3)|(1<<TWA2);				// Adres SLAVE 18H
    	TWSR = 0;                         		// Brak preskalera 
    	TWBR = ((F_CPU/SCL_CLOCK)-16)/2; 		// Szybkoś przesyłu
    } 
    
    void TWI_START(){
     	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);	// Start transmisji TWI Control Register
    	while (!(TWCR & (1<<TWINT)));			// Czekaj na flagę przerwania. To wskazuje na to, że START został wysłany.
    
    }
    void TWI_STOP(){
    	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);	// Zakończenie transmisji
       	while ((TWCR & (1<<TWSTO)));
    }
    
    void TWI_WRITE(unsigned char data){			// Transmisja - wysyłanie
    	TWDR = data;
    	TWCR = (1<<TWINT) | (1<<TWEN);			// Załaduj dane do TWDR (TWI Data Register). Wyczyść TWINT(TWI Interrupt Flag) w TWCR(TWI Register Control) by wystartować transmisję danych
    	while (!(TWCR & (1<<TWINT)));			// Czekaj na ustawienie TWINT(TWI Interrupt Flag).To wskazuje na to, że DANE zostały wysłane i ACK/NACK zostało odebrane.
    }
    int main(void){
    int data;
    data=0x10;                                                         // Przykładowa liczba
    TWI_INIT();
    TWI_START();
    TWI_WRITE(0x18);						// Adres urządzenia
    TWI_WRITE(data);						// Transmisja - wysyłanie
    TWI_STOP();
    _delay_ms(2000);						// Opóźnienie ~2s
    
    
    


    Slave Receiver:

    
    void TWI_INIT(){
    	TWAR = (1<<TWA3)|(1<<TWA2);					// Adres SLAVE 18H
    	TWBR = ((F_CPU/SCL_CLOCK)-16)/2; 			// Szybkoś przesyłu
    } 
    


    Jest tu mało napisanego bo w sumie nie wiem jak to dokończyć;/
    Proszę Was o pewne wskazówki bo siedzę w tym od wczoraj ;/
    Pozdrawiam
REKLAMA