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

KAmodMEMS2 - brak komunikacji po I2C

TomXV 18 Wrz 2011 00:52 2763 6
  • #1 9937799
    TomXV
    Poziom 12  
    Ma dole jest rozwiązanie problemu wraz z kodem obsługi KAmodMEMS2 przez I2C

    Witam,
    Chciałbym podłączyć akcelerometr LIS35, używając interfejsu I2C. Problem pojawią z obsługą biblioteki TWI (jest to inna nazwa I2C prawda?), Próbuję zrobić tak:
    
    
    #include <stdlib.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
     
    #include "uart.h"
    #include "TWI.h"
     
    // częstotliwość CPU w MHz
    #ifndef F_CPU
    #define F_CPU 16000000UL
    #endif
    
    // prędkość transmisji 9600
    #define UART_BAUD_RATE      9600      
     
    unsigned int readI2C(unsigned char idx, unsigned char RegAddr)
    {
    	unsigned char tmpL, tmpH;
    	TWI_Start();
    	TWI_Write(0x90 | (idx << 1));
    	TWI_Write(RegAddr);
    	TWI_Start();
    	TWI_Write(0x91 | (idx << 1));
    	tmpH = TWI_Read(ACK);
    	tmpL = TWI_Read(NACK);
    	TWI_Stop();
    	return (unsigned int)(tmpL + (tmpH << 8));
    }
    
    int main(void)
    {
    
    	TWI_Init();	
    
    	unsigned int c;
        
    	// włączenie modułu UART, ustawienie prędkości transmisji
    	uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU)); 
     
        // odblokowanie przerwań (transmisja obsługiwana jest w przerwaniach)
        sei();
    
        // wysłanie ciągu znaków
        uart_puts("TEST\n");
     
    	unsigned int data = 0;
    
        for(;;)
        {	
    
    		data = readI2C(0, 0x00);
    		char str[10];
    		itoa(data, str, 10);
    		uart_puts(&str);
    		uart_puts(" ");
    
    		c = uart_getc();
            if(c & UART_NO_DATA)
            {
                // brak danych w buforze
            }
            else
            {
                // dane dostępne, sprawdzenie, czy nie było błędu
                if(c & UART_FRAME_ERROR)
                {
                    // wykryto błąd ramki (np. brak bitu stopu)
                    uart_puts_P("UART Frame Error: ");
                }
                if(c & UART_OVERRUN_ERROR)
                {
                    // wykryto nadpisanie
                    uart_puts_P("UART Overrun Error: ");
                }
                if(c & UART_BUFFER_OVERFLOW)
                {
                    // wykryto całkowite zapełnienie bufora cyklicznego
                    uart_puts_P("Buffer overflow error: ");
                }
                // odesłanie znaku
                uart_putc((unsigned char)c);
            }
        }
    }
    


    Kod ten jest tak naprawdę połączeniem kodów obsługujących I2C znalezionych w necie. Niestety nie chce działać. Program zawiesza się w funkcji readI2C()
    Bardzo proszę o pomoc, może ktoś ma napisaną obsługę tego modułu przez I2C byłbym bardzo wdzięczny.
  • Pomocny post
    #2 9937864
    kiziu13
    Poziom 17  
    Zgodnie z opisem na http://www.kamami.pl/index.php?productID=138019 jest to dokładnie LIS35DE, a więc DS: http://www.st.com/internet/com/TECHNICAL_RESO...TECHNICAL_LITERATURE/DATASHEET/CD00231405.pdf . Zgodnie z tekstem na stronie 18, adres układu to 0b00111000 | ( SDO << 1) | (R/~W) (że tak symbolicznie napiszę), czyli adresy, jakie może przyjąć ten układ to 0x3A lub 0x38, a więc masz źle wybrany adres w funkcji, która w ogóle dziwne parametry przyjmuje. Proponuje znaleźć porządne funkcje do TWI i z nich skorzystać, posiłkując się tym co napisałem.
  • #3 9942561
    TomXV
    Poziom 12  
    Mam problem z ustawieniami bitów:
    Chodzi o to że powinienem ustawić PD=1 (active mode) lecz niewiem jak to zrobić. Odwołuje się do rejestru następująco:
    i2c_write_byte(0x20);

    gdzie:
    void i2c_write_byte(char byte) {
    TWDR = byte;
    TWCR = (1 << TWINT) | (1 << TWEN); // start address transmission
    while (!(TWCR & (1 << TWINT)));
    }

    Lecz niewiem czy to zmienia PD=1 czy tylko pierwszy rejestr tzn. DR.
    Moje pytanie dotyczy tego jak zmienić DR=1 i PD=1 reszta rejestrów bez zmian.
  • Pomocny post
    #4 9943313
    kiziu13
    Poziom 17  
    Nieprawidłowo wysyłasz dane na szynę (brak adresu slave'a, brak wartości wysyłanej), a przynajmniej tak mi się wydaje, gdyż podałeś nic nie warty wycinek kodu. Popatrz jak wygląda komunikacja:
    KAmodMEMS2 - brak komunikacji po I2C
    Pokaż więcej kodu, a wtedy pomyślimy.
  • #5 9943420
    TomXV
    Poziom 12  
    Ogólnie kod funkcji obsługujących i2c wygląda następująco:
    
    void i2c_start() {  
    	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send start condition  
    	while (!(TWCR & (1 << TWINT)));  
    }  
      
    void i2c_write_byte(char byte) {  
    	TWDR = byte;              
    	TWCR = (1 << TWINT) | (1 << TWEN); // start address transmission  
    	while (!(TWCR & (1 << TWINT)));  
    }  
      
    char i2c_read_byte() {  
    	TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN); // start data reception, transmit ACK  
    	while (!(TWCR & (1 << TWINT)));  
    	return TWDR;  
    }  
    
    char i2c_read_last_byte() {  
    	TWCR = (1 << TWINT) | (1 << TWEN); // start data reception
    	while (!(TWCR & (1 << TWINT)));  
    	return TWDR;  
    }  
      
    void i2c_stop() {  
    	  TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // send stop condition  
    }  


    Mam nadzieje, że wszystko jest tutaj dobrze

    Przejdzmy do obslugi akceleratora:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wykorzystywany rejestr 0x29 jest w obrazku: KAmodMEMS2 - brak komunikacji po I2C
  • Pomocny post
    #6 9943560
    kiziu13
    Poziom 17  
    Nie przestudiowałeś protokołu komunikacji.

    W inicjowaniu zapominasz wysłać wartości, masz start, masz wysłanie adresu slave'a z pisaniem 38h, masz wysłanie adresu rejestru 20h, a po tym powinieneś wysłać wartość którą chcesz wpisać do tego rejestru, czyli np. 47h, a dopiero po tym stop.

    W prośbie o dane wywal pierwszy stop, robisz porprostu kolejny start, czyli tzw. repeated start.

    BTW, 20h nie ma nic wspólnego z prędkością transmisji (jak piszesz w komentarzu), tylko z częstotliwością "wypluwania" danych (100Hz vs 400Hz).

    BTW (2), po co czytasz dwa bajty, skoro po 29h jest 2Ah, który nie jest używany (strona 23 DSa)?
  • #7 9943967
    TomXV
    Poziom 12  
    Bardzo dziękuje, za te informacje zmieniłem trochę kod dzięki nim:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Mimo zmian komunikacja nie działa.

    Dodano po 25 [minuty]:

    Ops znowu mój błąd. Teraz już wszystko działa wielkie dzięki za pomoc.

    Jeżeli jest ktoś zainteresowany obsługą KAmodMEMS2 przez I2C to załączam poniżej kod.
    Mikroprocesor Atmega32.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA