Skocz do zawartości

Atmega8 - niedziałające TWI


esio

Pomocna odpowiedź

Witam. Mam następujący problem z niedziałającym TWI. Mam kod na atmegę w C.

/* 
Czujnik ultradzwiekowy sterowany z magistrali i2c 
C= 2010 Grzegorz Eliszewski 
grzegorz(małpa)eliszewski.pl 
esio.eu 
*/ 
#define F_CPU 12000000UL // czestotliwosc kwarcu 12MHz 

#include <avr/io.h> 
#include <util/delay.h> // obsluga opoznien                
#include <compat/twi.h> // obsluga magistrali i2c 
#include <avr/wdt.h> // obsluga watchdoga 
#include <avr/interrupt.h> // przerwania 

volatile uint8_t time=124; // czas potrzebny na powrot odbitych ultradzwiekow 
volatile uint8_t value; // dane odebrane na magistrali TWI 

// deklaracje wystąpienia funcji 
void pomiar(void); 
void signal(unsigned int o); 
unsigned int distance(unsigned int time); 
void twi_init(char adres); 

// obsluga magistrali i2c 
// przerwanie od TWI 

SIGNAL (SIG_2WIRE_SERIAL) 
{ 
  switch(TWSR) //odczytanie bitu sterujacego 
  { 
     case 0x00:   // nieoczekiwany start lub stop 
        TWCR = (1<<TWSTO); // ustawienie 1 na bicie TWSTO = STOP! 
        TWCR = (1<<TWINT); // ustawienie 1 na bicie TWINT = START! 
        // w wypadku, gdy pojawi sie nieoczekiwany start lub stop na TWI to: 
        // 1. transmisja jest zatrzymywana 
        // 2. transmisja startuje ponownie 
     break; 
  // TWI w trybie MASTER - RECIVER 
     case 0x60:    
        // TWSR = 0b11000000 
        // wlasny SLA+W odebrany ACK nadane 
     break; 

     case 0x68:  
        // utrata kontroli nad magistrala, master odlaczony 
        // wlasny SLA+W odebrany ACK nadane 
     break;       
     case 0x80: 
        // transmisja - odbior! 
        // 1. odebrano SLA+W (adres + W jak write, czyli zapis do slave :)) 
        // 2. odebrano dane 
        // 3. nadano ACK = bit potwierdzenia, oczekuje dalszej transmisji 
        // value = TWDR; // TWDR = rejestr z danymi TWI 
        if (TWDR == 0x01) // jezeli TWDR = 0b00000001 
        { 
           //pomiar(); // wykonanie pomiaru 
           PORTD = 0xFF; 
        } 
     break; 
     case 0x88: 
        // transmisja - odbior! 
        // 1. odebrano SLA+W 
        // 2. odebrano dane 
        // 3. nie nadano ACK (nadano NACK), potwierdzenie i koniec transmisji 
        value = TWDR; // TWDR = rejestr z danymi TWI 
        if (value == 0x01) // jezeli TWDR = 0b00000001 
        { 
           PORTD = 0xFF; 
        //   pomiar(); // wykonanie pomiaru 
        } 
     break; 
  // TWI w trybie MASTER - TRANSMITER 
     case 0xA8: 
        // transmisja - nadawanie! 
        // 1. odebrano SLA+R (adres + odczyt ze slave) 
        // 2. nadano ACK 
        TWDR = time;    // zapisanie zmiennej czasu do TWDR 
        TWCR = (1<<TWINT) | (1<<TWEN);    // wyczyszczenie TWINT 
                    // wlaczenie TWI poprzez 1 na TWEN 
                    // przygotowanie do wyslania danych 
        while(!(TWCR & (1<<TWINT)));    // transmisja danych <- patrz dataszit 
        // sprawdzanie statusu TWI 
        if ((TW_STATUS) & (0xF8 != TW_MT_DATA_ACK)) 
        { 
           // blad nadawania 
        } 
     break; 

  } 
} 


// funkcja generujaca sygnal, o = ilosc okresow 
// generowanie sygnalu zblizonego do 40kHz, zmiana stanu co 12us zamiast co 12.5us 
void signal(unsigned int o) 
{ 
  int i; 
  DDRB = 0xFF; // ustawienie portu B jako wyjscie 
  // sbi(DDRB,6); 
  // sbi(DDRB,2); 
  for(i=0;i<o;i++) 
  { 
     // ustaw 1 na PB2 i 0 na PB1 
     PORTB = 0x04; 
     _delay_us(12); // czekaj 12us 
        PORTB = 0x02; 
     _delay_us(12); 
  } 
  // ustawienie stanu niskiego na porcie nadajnika 
  // tlumienie nadajnika 
  PORTB = 0x00; 
  _delay_ms(1); // odczekanie 1ms = tlumienie nadajnika 
} 

// pomiar odleglosci, o = ilosc okresow 
// wyslanie sygnalu i odbior odbitego od przeszkody 
void pomiar(void) 
{ 
  TCNT1 = 0x0000; // zerowanie licznika T1 
  signal(5); // emitowanie 5 okresow sygnalu sterujacego 
  // _delay_ms(10); // odczekanie 10ms przed pomiarem 
  TCCR1B = 0x05;    // start T1 jako licznik z prescalerem /1024 0b00000010 
        // zliczanie co 12Mhz/1024 
        // czestotliwosc 11.71875kHz 
        // czas jednego impulsu to okolo 85us 

  while(TCNT1 < 0x0FA0) // dopoki licznik nie doliczy do 0x0FA 
  { 
     while(bit_is_clear(ADCSRA,ADIF)); // koniec pomiaru na ADC 
     { 
     // jezeli wartosc na ADC jest mniejsze niz !czulosc! to przerwij odliczanie czasu 
        if(ADCH > 100) 
        { 
           time = TCNT1; // przepisanie wartosci licznika do zmiennej 
           TCNT1 = 0xFFFF; // przepelnienie licznika == wyjscie z petli 
        } 
     }    
  } 
  TCCR1B = 0x00; // wylaczenie licznika 
//   wdt_reset(); // resetowanie watchdoga 
/* 
  for(echo=0;echo<666;echo++)  // petla obliczajaca odleglosc 
  { 
     if(bit_is_set(ACSR,ACO))  // jezeli odebrano sygnal powracajacy 
     { 
        break;  // wyjscie z petli 
     } 
  }*/ 
//   return time; 

} 
// obliczanie rzeczywistej odleglosci w zaleznosci od czasu 
// sprawdzic jak to ma sie do siebie :P 
unsigned int distance(unsigned int time) 
{ 
  unsigned int czas_s; 
  if (time < 60 ) 
  // 60 przebiegow zegara czyli okolo 5ms 
  // mierzymy tylko w jedna strone 
  // wynika z opoznienia na zwarcie czujnikow 
  { 
     return 0; 
  } 
  else 
  { 
     return 50 + time*1.5; 
  } 
  // V_dzwieku w powietrzu +/- 343 m/s 
  // S = (V*t)/2 || droga [m] = predkosc [m/s] * czas [s] 
  // czas [s] = time * 0.000085 | jeden cykl zegara to 85us 
  // jeden cykl zegara to okolo 1.5cm 
} 

// inicjacja i konfiguracja magistrali TWI 
void twi_init(char adres) 
{ 

  DDRC = 0b00000000; // konfiguracja portu C jako wyjscie 
  PORTC = 0b00110011; // PC5 PC4 jako wyjscie 

  TWAR = adres; // przypisanie adresu 
  TWSR = 0; // zerowanie statusu TWI 
  TWCR = 0xC5;    // ustawienie TWCR 0b11000101 
        // TWINT - oczekiwanie na odpowiedzi, uaktywnienie przerwania 
        // TWEA - wlaczenie generowania ACK 
        // TWEN - aktywacja obslugi TWI, aktywacja interface TWI 
        // TWIE - uaktywnienie obslugi przerwan TWI 
} 

// funkcja glowna 
int main(void) 
{ 
  twi_init(0x02); // inicjacja TWI z adresem 0x02 

  // konfiguracja ADC 
  ADMUX = 0x61; // konfiguracja działania ADC 0b01100001 
  ADCSRA = 0xC6; // start ADC prescaler /64, f = 187.5kHz 

//   wdt_enable(WDTO_250MS); // watchdog na 250ms 
  sei(); // wlaczenie obslugi przerwan 

  DDRD = 0xFF; // port D jako wyjscie 
} 

Problem polega na tym, że jak wysyłam do czujnika na adres 0x10 wartość 0x01 to nie zapala mi się dioda, tak samo z odczytem. Testuje za pomocą arduino. Nie mam pojęcia co robię źle, to pierwsze moje spotkanie z TWI i nie wiem, może popełniłem jakiś prosty błąd.

Wrzuciłem program zmodyfikowany do tego, żeby testować sam interfejs.

Kod arduino za pomocą którego testuję magistralę:

Kod:

#include <Wire.h> 
int ledPin =  13; 

void setup() 
{ 
 Serial.begin(9600); 
 Wire.begin(); // join i2c bus (address optional for master) 
 pinMode(ledPin, OUTPUT);      
} 
int zz = 0; 
byte x = 0x01; 

void loop() 
{ 
 Wire.beginTransmission(0x10); // transmit to device #4 
 //Wire.send("x is ");        // sends five bytes 
 Wire.send(0x01);              // sends one byte  
 Wire.endTransmission();    // stop transmitting 
 digitalWrite(ledPin, HIGH);   // set the LED on 
            // wait for a second 
Wire.requestFrom(0x10, 8); 
if (Wire.available()) { 
   zz = Wire.receive(); 
 } 
 else zz = 15; 
 //x++; 
Serial.print(zz); 
  digitalWrite(ledPin, LOW); 
   delay(500); 
} 

Serial pokazuje, że magistrala nie jest gotowa, czyli wywala liczbe 15... zamiast odczytu z czujnika.

Przewaliłem tony dokumentacji i nadal nie wiem co jest...

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.