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

Dziwne zachowanie sie twi [C]

arikadiusz 17 Lut 2010 12:53 1347 3
REKLAMA
  • #1 7707707
    arikadiusz
    Poziom 12  
    Mecze sie z poprawnym uruchomieniem sprzetowego twi miedzy mega88 i mega128.
    Wyglada to tak ze mam procek mega128 - MASTER RECEIVER i mega88 - SLAVE TRANSMITTER. Uruchamiam oba procki wysylam start, adres+r czytam 3 paczki po 8 bitow - jest ok. Problem pojawia sie kiedy po tych 3 paczkach wysylam Repeted Start i chce odebrac kolejna paczke.

    MASTER
    lcd : Start SLA+R A L A Rs SLA+R L A A
    TWSR: 0x08 0x40 0x50 0x50 0x58 0x10 0x40 0x50 0x50 0x58

    SLAVE
    UART: 0xA8 0xB8 0xB8 0xC0 0xA8 0xB8 0xB8 0xC0
    A L A L A A

    moj kod jest taki:
    MASTER:
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include "twi.h"
    #include "lcd.h"
    
    
    int main(void)
    {
    lcd_init(LCD_DISP_ON_BLINK);
    _delay_ms(3000);
    lcd_clrscr();
    
    	//START SLA+READ
    twi_int();
    // start condition
    	TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    	while (!(TWCR & (1<<TWINT))) ;
            lcd_putc(TWSR);
    // send device adress
    	TWDR = 0x61;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while(!(TWCR & (1<<TWINT)));
            lcd_putc(TWSR);
    
    lcd_putc(twi_read(1));
            lcd_hex(TWSR);
    lcd_putc(twi_read(1));
            lcd_hex(TWSR);
    lcd_putc(twi_read(0));
            lcd_hex(TWSR);
    
    
    	//Rep START SLA+READ
    // start condition
    	TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    	while (!(TWCR & (1<<TWINT))) ;
    	lcd_putc(TWSR);
    // send device adress
    	TWDR = 0x61;
    	TWCR = (1<<TWINT) | (1<<TWEN);
    	while(!(TWCR & (1<<TWINT)));
            lcd_putc(TWSR);
    
    
    lcd_putc(twi_read(1));
            lcd_hex(TWSR);
    lcd_putc(twi_read(1));
            lcd_hex(TWSR);
    lcd_putc(twi_read(0));
            lcd_hex(TWSR);
    
    
    while(1)
    {	
    }
    return 0;
    
    }
    
    unsigned char twi_read(unsigned char ack)
    {
    	TWCR = (1<<TWINT)|(ack<<TWEA)|(1<<TWEN);
    	while(!(TWCR & (1<<TWINT)));
    	return TWDR;
    }
    
    void twi_int(void)
    {
    // predkosc i2c
    	TWSR = (0<<TWPS1) | (0<<TWPS0);
    	TWBR = (F_CPU / 100000UL - 16) / 2;  
    }
    
    


    specjalnie wysylam NACK na koncu pierwszej paczki zeby zobaczyc co sie stanie. Urzadzenia ma domyslnie odpowiadac tylko raz na jakis czas na zawolania od master. Kiedy wysylam dane 'ciurkiem' wszystko jest ok, ale co mi po takim urzadzeniu... Dodam jeszcze ze jak zresetuje mastera to dalej sie zmienia kolejnosc liter. Dopiero jak dam power off / power on dla SLAVE to moge pierwsza paczke, luba pare paczek(ale ciurkiem!) odebrac poprawnie.

    Mam nadzieje ze nie namotalem i da sie zrozumiec cos z tego co napisalem :). Bardzo prosze o pomoc gdyz nie mam oscyloskopu ani analizatora stanow logicznych, a cos czuje ze by sie przydal... Gdzies znalazlem info. o tym ze Atmega 16 dziwnie sie zachowuje przy i2c, no ale ja mam inne procki.
    Bede bardzo wdzieczny za cokolwie co moze mnie przyblizyc do rozwiazania tego niewygodnego problemu.
    Pozdrawiam.
  • REKLAMA
  • #2 7709080
    tadzik85
    Poziom 38  
    nie widzę w kodzie sygnału stop; więc to może być powodem tego błędu

    powtórzenie sygnału START stosowane jest po wysłaniu adresu urządzenie i np komórki pamięci układu slave, a ty stosujesz go pomiędzy odczytami.
  • REKLAMA
  • #3 7710451
    arikadiusz
    Poziom 12  
    nie mam stopu poniewaz kiedy go chce uzyc to magistrala "zawiesza sie" a nic nowego tam nie wymyslam czego nie ma w dokumentacji:

    
    	TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);	
    	while(!(TWCR & (1<<TWINT)));
    


    Nic nie ma wspomniane przy Slave receiver ze ma jakos odpowiedziec na sygnal stop (jakos ustawic bity w TWSR), byc moze to jest tego powodem, nie wiem juz teraz...

    wedlug tych smiesznych rysunkow z dokumentacji (str. 216 mega128) Jedyne co mam zrobic to:
    1. wyslac start (TWSR=0x08) [jest]
    2. wyslac SLA+R na 9 bicie otrzymac ACK (TWSR=0x40) [jest]
    3. wysylac sobie ile bajtow mi sie podoba po kazdym dostawac ACK (TWSR=0x50) [jest]
    4. wyslac ostatni bajt (TWSR=0x58) [jest]
    5. strzalka PRZED stopem wyslac Rs (TWSR=0x10) [jest]
    itd.

    wszystko zgodnie z dokumentacja a jakies smieszne opuznienia sie robia...
  • #4 7807366
    tadzik85
    Poziom 38  
    skoro jeden uP działa zawsze jako slave spróbuj zrobić protokół dokładnie tak jest w przypadku np EEPROMów. bo to co stworzyłeś naprawdę dziwnie wygląda, wyłącz przerwania.
REKLAMA