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

[AVR][C] Atmega8 + SPI ADXL345 = problemy z komunikacją

_yogurt_ 23 Paź 2009 21:37 4708 7
REKLAMA
  • #1 7167015
    _yogurt_
    Poziom 11  
    Witam!
    Posiadam tak jak w tytule akcelerometr ADXL345 (przygotowany układ z buforami i oddzielnym zasilaniem 3.3V<=>5V). Moim celem jest podłączenie go do Atmegi8, która to prześle dane odebrane z wykorzystaniem SPI do komputera przez RS232. O ile komunikacja UARTem działa bez problemu, o tyle mam problemy z komunikacja poprzez SPI. Ustawiam wszystko tak jak jest napisane w manualu i od akcelerometra i od Atmegi. Jedyne co udaje mi się otrzymać to Device ID (0xe5) po wysłaniu komendy o Device ID. Gdy próbuję pobrać inne dane to cały czas SPDR zwraca mi ta samą wartość 0xe5, 0x00 albo 0xf9.
    Jeżeli ktoś mógłby rzucić okiem na kod, bo najprawdopodobniej w nim może być błąd :cry: ??

    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    
    #define F_CPU 1000000
    #define UART_BAUD 4800
    #define UART_CONST F_CPU/16/UART_BAUD-1
    
    #define RANGE_2G	0
    #define RANGE_4G	1
    #define RANGE_8G	2
    #define RANGE_16G	3
    #define	MEASURE		(1<<3)
    #define	DEVID		0x00
    #define	DATA_FORMAT	0x31
    
    #define DATAX0		0x32
    
    #define DATAX1		0x33
    
    #define DATAY0		0x34
    
    #define DATAY1		0x35
    
    #define DATAZ0		0x36
    
    #define DATAZ1		0x37
    #define	FIFO_CTL	0x38
    #define POWER_CTL	0x2D
    #define	BW_RATE		0x2C
    
    #define SELECT_ADXL()	PORTB &= ~(1<<PORT2) //CS dla ADXL
    
    #define UNSELECT_ADXL() PORTB |= 1<<PORT2
    
    //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
    
    void ADXL_write(uint8_t addr, uint8_t data) {  //zapis do ADXL345 - 8bit adresu i 8bit danych
      SELECT_ADXL();
      SPDR = addr;
      loop_until_bit_is_set(SPSR, SPIF);
      SPDR = data;	
      loop_until_bit_is_set(SPSR, SPIF);
      UNSELECT_ADXL();
    }
    
    uint8_t ADXL_read(uint8_t addr) {  // odczyt od ADXL345 - 128+adres, zwraca 8 bit  danych
      uint8_t ans;
    
      SELECT_ADXL();
      SPDR = 0x08 | addr;
      loop_until_bit_is_set(SPSR, SPIF);
      ans = SPDR;
      UNSELECT_ADXL();
      
      return(ans);
    }
    
    void ADXL_spi_init(void) {	//ustawia SPI w tryb MASTER
      DDRB = _BV(PORT5) | _BV(PORT3) | _BV(PORT2);
      PORTB |= _BV(PORT5);
      SPCR = _BV(SPE) | _BV(MSTR) | _BV(CPOL) | _BV(CPHA) | _BV(SPR1);	
      UNSELECT_ADXL();
    }
    
    void ADXL_init() {	//wysyla konfiguracje do ADXL345, rozdz. +-2g, 100Hz, brak bufora FIFO, wlacz pomiar
      ADXL_write(DATA_FORMAT, RANGE_2G);
      ADXL_write(BW_RATE, 0x0a);
      ADXL_write(FIFO_CTL, 0);
      ADXL_write(POWER_CTL, MEASURE);
    }
    
    void UART_putc(uint8_t c) {	//wysyla znak na UART
      loop_until_bit_is_set(UCSRA, UDRE);
      UDR = c;
    }
    
    void UART_puts(uint8_t *s, uint8_t len) {	//wysyla ciag znakow na uart
    	uint8_t i;
    
    	for(i=0; i<len; i++)
    		UART_putc(s[i]);
    }
    
    uint8_t UART_getc(void) {	//pobiera znak z UART
      loop_until_bit_is_set(UCSRA, RXC);
      return(UDR);
    }
    
    void UART_puti(uint8_t data) {	//wysyla liczbe uint8_t w postaci ASCII do UART
    	uint8_t t;
    	
    	t = data/100;
    	UART_putc(t+'0');
    	data -= t*100;
    	t = data/10;
    	UART_putc(t+'0');
    	data -= t*10;
    	UART_putc(data+'0');
    }
    
    //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
    
    int main (void) { //program glowny
    
      uint8_t Xh, Xl, Yh, Yl, Zh, Zl;
      uint8_t gc;
    
      UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
      UBRRL = 12;
      UCSRB = _BV(RXEN) | _BV(TXEN);
    	
      UART_puts("\n\rYogurT wita uP ATMEGA8\n\n\r",27);
    
      ADXL_spi_init();
      _delay_ms(100);
      ADXL_init();
      _delay_ms(100);
    	
      sei();
    	
      while(1) {		
    	gc = UART_getc();
    
    	if(gc=='1') {  //jezeli z komputera przyjdzie '1' to zrob pomiar przyspieszenia
    
    		Xh = ADXL_read(DATAX1);
    		Xl = ADXL_read(DATAX0);
    		UART_putc(Xh);
    		UART_putc(Xl);
    		Yh = ADXL_read(DATAY1);
    		Yl = ADXL_read(DATAY0);
    		UART_putc(Yh);
    		UART_putc(Yl);
    		Zh = ADXL_read(DATAZ1);
    		Zl = ADXL_read(DATAZ0);
    		UART_putc(Zh);
    		UART_putc(Zl);
    
    		_delay_ms(10);
    	} else if(gc=='2') {	//jezeli 2 to wyslij DeviceID
    		UART_putc(ADXL_read(DEVID));
    		_delay_ms(10);
    	}	
      }
    
      return (0);
    }
    
  • REKLAMA
  • #2 7167511
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 7167782
    _yogurt_
    Poziom 11  
    No z datasheeta czasówka wygląda tak:
    [AVR][C] Atmega8 + SPI ADXL345 = problemy z komunikacją
    Nie mam pojęcia o DummyByte, ale na czasówkach tego nie widać ;(
    Ale sprawdzę, może pomoże ;)
  • REKLAMA
  • #4 7167817
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #6 7176606
    _yogurt_
    Poziom 11  
    Nasuwa mi się jeszcze jedno pytanie. Może trzeba jakieś fuse bity ustawić? Nie używam zewnętrznego oscylatora , tylko wewnętrzny. Dodatkowa informacja jest taka, że wejście MISO do Atmegi (wyjście z ADXL'a przez bufor do Atmegi) jest w granicach napięć 0-3.3V. Czy może poziom napięć nie jest za niski dla SPI na zwykłej Atmedze? Może spróbować zastosować Atmege8L?
  • #7 7177709
    Konto nie istnieje
    Poziom 1  
  • #8 11493459
    pentel
    Poziom 13  
    Witam, chce podłączyć się do tematu. Chce podłączyć ADXL345 do Atmegi16A poprzez SPI. Tutaj chciałem się zapytać _yogurt_ czy nie odnotowałeś żadnych problemów z podłączeniem czujnika bezpośredni do atmegi. Moja Atmega zasilana jest 5V zaś czujnik z 3.3V. Czy podłaczenie obydwu elementów nie spowoduje przeciążenia i uszkodzenia czujnika ? Pozdrawiam
REKLAMA