Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

LPC2148 (komunikacja po i2c z kamerą podczerwoną IR - trudności)

pawelma17 03 Cze 2012 17:15 1258 6
  • #1 03 Cze 2012 17:15
    pawelma17
    Poziom 9  

    Witam serdecznie Szanownych forumowiczów. Po raz pierwszy umieszczam post na tym forum co wynika z problemów jakie napotkałem w czasie próby skomunikowania się uC LPC2148 z kamerą podczerwoną poprzez interfejs I2C. Mam nadzieję, że nie powtarzam żadnego tematu. Przeczytałem wątki o podobnym charakterze i uznałem, że spokojnie mogę założyć nowy temat. Tak więc w czym tkwi problem? Mianowicie od jakiegoś czasu jestem w posiadaniu wyżej wymienionego uC oraz kamery podczerwonej wymontowanej z kontrolera Wii. Projekt który, mam wykonać jest odzwierciedleniem tego projektu : http://letsmakerobots.com/node/7752 lecz mój realizowany jest na ARM'ie. Głównym celem projektu jest zwracanie przez kamerę (w jednym z 3 trybów) współrzędnych X,Y każdego z maksymalnie 4 źródeł promieniowania podczerwonego.
    Poniżej umieszczam program konfiguracji I2C oraz programy do wysyłanie oraz odbierania danych z kamery.

    Code:

    #include "lpc214x.h"
    #include "i2c.h"
    #include "uart.h"

    void i2c_inicjalizacja(void)
    {
       //ustawienie linii P0.2 i P0.3 jako SCL0 i SDA0
       PINSEL0&=~(15<<4);   //wyzeruj pinsel0=00000000
       PINSEL0|=0x50;
          //ustawienie predkosci transmisji 400kHz
       I2C0SCLL=75;
       I2C0SCLH=75;
          //wyzeruj flagi
       I2C0CONCLR=0x7c;
          //wlacz i2c jako master transmitter
       I2C0CONSET=0x40;

    }
    int i2c_start(void)
    {
       I2C0CONSET=0x20;
       return 0;
    }
    /////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////WYSLIJ DO KAMERY///////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////
    int wyslij_I2C(unsigned char licznik)
    {
       int i,liczba_bajtow;
       char element[21];
       char p0=0xAA;
       char p1=0x64;
       char p2=0x63;
       char p3=0x03;
       element[0]=0x30;element[1]=0x01;element[2]=0x00;element[3]=0x02;
       element[4]=0x00;element[5]=0x00;element[6]=0x71;element[7]=0x01;
       element[8]=0x00;element[9]=p0;element[10]=0x07;element[11]=0x00;
       element[12]=p1;element[13]=0x1A;element[14]=p2;element[15]=p3;
       element[16]=0x33;element[17]=0x03;element[18]=0x30;element[19]=0x08;




       element[20]=0x36;
       switch(licznik)
       {
       case 1:
          liczba_bajtow=1;
          I2C0CONSET=0x20;   // ustaw bit startu

          while(I2C0STAT==0xF8)
            {
             while(1)

             {
                switch(I2C0STAT)
             {
             case 0xf8:   // stan jalowy nic sie nie dzieje na magistrali
                wypisz_String("0xF8 I2C0STAT\n");
                break;
             case 0x00:      // blad na magistrali. Enter not addressed Slave mode and release bus.
                wypisz_String("stan 0x00 blad na magistrali");
                I2C0CONSET=0x14;    // ustawienie stop oraz aa
                I2C0CONCLR=0x08;   // zerowanie flagi SI
                break;
             case 0x08:      // gdy nadany bit startu
                wypisz_String("nadany bit startu stan 0x08 \n");
                I2C0DAT=0xB0;      // wyslij adres cam IR
                //I2C0CONSET= 0x04;   // wlaczenie bitu potwierdzenia
                I2C0CONCLR=0x20;   // kasowanie bitu startu
                I2C0CONCLR= 0x08;   // czyszczenie flagi SI
                break;
             case (0x18):      // adres urzadzenia zostal nadany ->zapis z ACK
                wypisz_String("adres urzadzenia zostal nadany ->zapis z ACK\n");
                I2C0DAT=element[0];      // wyslij - do kamery - konfiguracja
                //I2C0CONSET=0x04;   // wlaczenie bitu potwierdzenia
                I2C0CONCLR=0x08;   // wyczysc flage SI
                czekaj(150);
                break;
             case (0x20):      // adres zostal nadany ->zapis  bez potwierdzenia ACK
                czekaj(100);
                wypisz_String("adres zostal nadany ->zapis  bez potwierdzenia ACK\n");
                I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             case (0x28):      // dane zostaly wyslane z potwierdzeniem ACK
                if (liczba_bajtow==1)
                {
                   wypisz_String("\ndane zostaly wyslane z potwierdzeniem ACK\n");
                   I2C0DAT=element[1];      // wyslij kolejna dana
                   I2C0CONSET=0x04;   // wlaczenie bitu potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   czekaj(150);
                }
                else
                {
                   wypisz_String("\nostatnia dana zostala wyslana z potwierdzeniem ACK\n");
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return 0;
                }
                liczba_bajtow++;
                break;
             case (0x30):      // dane zostaly wyslane bez potwierdzenia ACK
                   czekaj(100);
                   wypisz_String("dane zostaly wyslane bez potwierdzenia ACK\n");
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return 1;         // zwroc 1 blad
                break;
             case (0x38):      // utrata magistrali- inne urzadzenie master przejelo magistrale
                   wypisz_String("utrata magistrali 0x38\n");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             default :         // inne zdarzenie
                   czekaj(100);
                   wypisz_String("inne zdarzenie na magistrali ");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   wypisz_Znak(I2C0STAT);
                   return (I2C0STAT);         // zwroc  gdy katastrofa;]
                break;

                }}}


    Argument "licznik" przyjmuje wartości od 1-7 ponieważ kamera konfigurowana jest w sposób następujący:
    Start --> Wysłanie określonej liczby bajtów --> Stop --> Czekaj ok 50ms --> Start...
    Funkcja wypisz_String służy mi do sprawdzania do jakiego momentu wykonywany jest program.
    Pytanie brzmi czy program jest napisany poprawnie? Chodzi o to, że gdy rozpocznę transmisję wszystko wygląda fajnie do momentu w którym rozpoczynam świecić diodą IR. Gdy to zrobię po ok. 2 min program zatrzymuje się na tym miejscu :
    while(I2C0STAT==0xF8)
    po resecie, wgraniu programu od nowa program staje w tym miejscu. Ba nawet wgranie innego programu do transmisji po I2C nie działa (inne programy działają bez I2C). Kompletnie nie wiem jak to interpretować co jest nie tak. Czy to wina układu z kamerą podczerwoną, który jest w zasadzie robiony pod uC Atmega. Może rezystory pull-up mają być ok 10k a nie 2k2.

    Poniżej zamieszczę jeszcze program do odbierania danych :
    Code:
     char odczytaj_i2c(char tryb)
    
    {
     char x;
       //I2C0CONSET=0x20;      //ustaw bit startu
           while(1){
               while(I2C0STAT==0xF8);
          switch(I2C0STAT){
             case 0xf8:   // stan jalowy nic sie nie dzieje na magistrali
                   wypisz_String("0xF8 I2C0STAT\n");
                   I2C0CONSET=0x08;      // zerowanie flagi SI
                break;
             case 0x00:      // blad na magistrali. Enter not addressed Slave mode and release bus.
                   wypisz_String("stan 0x00 blad na magistrali");
                   I2C0CONSET=0x14;    // ustawienie stop oraz aa
                   I2C0CONCLR=0x08;   // zerowanie flagi SI
                break;
             case 0x08:      // gdy nadany bit startu
                   wypisz_String("nadany bit startu stan 0x08 \n");
                   I2C0CONCLR=0x20;   // kasowanie bitu startu
                   I2C0DAT=0xB1;      // wyslij adres cam IR kierunek odczyt
                   I2C0CONSET= 0x04;   // wlaczenie bitu potwierdzenia
                   I2C0CONCLR= 0x08;   // czyszczenie flagi SI

                break;
             case (0x40):      // adres urzadzenia zostal nadany <--odczyt z ACK
                   wypisz_String("adres urzadzenia zostal nadany <--odczyt z ACK\n");
                   I2C0CONSET=0x04;   // wlaczenie bitu potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             case (0x48):      // adres zostal nadany <--odczyt bez potwierdzenia ACK
                   czekaj(1000);
                   wypisz_String("adres zostal nadany <--odczyt  bez potwierdzenia ACK\n");
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             case (0x50):      // dane zostaly odebrane i wyslano potwierdzenie ACK
                   if(tryb==ACK)//// z ack
                   {
                      //wypisz_String("dane zostaly odebrane i wyslano potwierdzenie ACK\n");
                      x=I2C0DAT;
                      I2C0CONSET=0x04;   // ustaw bit potwierdzenia AA
                      I2C0CONCLR=0x08;   // wyczysc flage SI
                      return x;
                   }
                   else
                   {
                      //wypisz_String("dane zostaly odebrane bez ACK\n");
                      x=I2C0DAT;
                      I2C0CONSET=0x10;   // ustaw warunek STOP oraz bit potwierdzenia AA
                      //I2C0CONCLR=0x08;   // wyczysc flage SI
                      I2C0CONCLR=0x0C;   // wyczysc flage SI i AA
                      return x;
                   }
                break;
             case (0x58):      // dane zostaly odebrane bez potwierdzenia ACK
                   wypisz_String("dane zostaly odebrane bez potwierdzenia ACK\n");
                   x=I2C0DAT;
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return x;         // zwroc 1 blad
                break;
             case (0x38):      // utrata magistrali- inne urzadzenie master przejelo magistrale
                   wypisz_String("utrata magistrali 0x38\n");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             default :         // inne zdarzenie
                   czekaj(1000);
                   wypisz_String("inne zdarzenie na magistrali ");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return (I2C0STAT);         // zwroc  gdy katastrofa;]
                break;
          }}}


    Za wszelką formę zainteresowania tematem z góry dziękuję.
    P.S Przepraszam za mało profesjonalny wygląd programu ale jestem jeszcze amatorem .

    0 6
  • #2 03 Cze 2012 20:04
    Freddie Chopin
    Specjalista - Mikrokontrolery

    pawelma17 napisał:
    switch(licznik)
       {
       case 1:
          liczba_bajtow=1;
          I2C0CONSET=0x20;   // ustaw bit startu

          while(I2C0STAT==0xF8)
            {
             while(1)

             {
                switch(I2C0STAT)
             {
             case 0xf8: 

    Co to za potwór? Napisz to porządnie, to zacznie działać, bo to powyżej to jest... po prostu czysty chaos.

    4\/3!!

    0
  • #3 04 Cze 2012 00:21
    pawelma17
    Poziom 9  

    Ok rozumiem. Faktycznie nie wygląda to dobrze. Nie jest to wersja pierwotna natomiast któraś z kolei zmodyfikowana ponieważ szukałem rozwiązanie tego problemu. Pierwotnie wyglądało to tak :

    Code:
    switch(licznik)
    
       {
       case 1:
          liczba_bajtow=1;
          I2C0CONSET=0x20;   // ustaw bit startu
          while(1)
          {
             while(I2C0STAT==0xF8);
             switch(I2C0STAT)
             {
             case 0xf8:   // stan jalowy nic sie nie dzieje na magistrali
                wypisz_String("0xF8 I2C0STAT\n");
                break;
             case 0x00:      // blad na magistrali. Enter not addressed Slave mode and release bus.
                wypisz_String("stan 0x00 blad na magistrali");
                I2C0CONSET=0x14;    // ustawienie stop oraz aa
                I2C0CONCLR=0x08;   // zerowanie flagi SI
                break;
             case 0x08:      // gdy nadany bit startu
                wypisz_String("nadany bit startu stan 0x08 \n");
                I2C0DAT=0xB0;      // wyslij adres cam IR
                //I2C0CONSET= 0x04;   // wlaczenie bitu potwierdzenia
                I2C0CONCLR=0x20;   // kasowanie bitu startu
                I2C0CONCLR= 0x08;   // czyszczenie flagi SI
                break;
             case (0x18):      // adres urzadzenia zostal nadany ->zapis z ACK
                wypisz_String("adres urzadzenia zostal nadany ->zapis z ACK\n");
                I2C0DAT=element[0];      // wyslij - do kamery - konfiguracja
                //I2C0CONSET=0x04;   // wlaczenie bitu potwierdzenia
                I2C0CONCLR=0x08;   // wyczysc flage SI
                czekaj(150);
                break;
             case (0x20):      // adres zostal nadany ->zapis  bez potwierdzenia ACK
                czekaj(100);
                wypisz_String("adres zostal nadany ->zapis  bez potwierdzenia ACK\n");
                I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             case (0x28):      // dane zostaly wyslane z potwierdzeniem ACK
                if (liczba_bajtow==1)
                {
                   wypisz_String("\ndane zostaly wyslane z potwierdzeniem ACK\n");
                   I2C0DAT=element[1];      // wyslij kolejna dana
                   I2C0CONSET=0x04;   // wlaczenie bitu potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   czekaj(150);
                }
                else
                {
                   wypisz_String("\nostatnia dana zostala wyslana z potwierdzeniem ACK\n");
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return 0;
                }
                liczba_bajtow++;
                break;
             case (0x30):      // dane zostaly wyslane bez potwierdzenia ACK
                   czekaj(100);
                   wypisz_String("dane zostaly wyslane bez potwierdzenia ACK\n");
                   I2C0CONSET=0x14;   // ustaw warunek STOP oraz bit potwierdzenia AA
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   return 1;         // zwroc 1 blad
                break;
             case (0x38):      // utrata magistrali- inne urzadzenie master przejelo magistrale
                   wypisz_String("utrata magistrali 0x38\n");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                break;
             default :         // inne zdarzenie
                   czekaj(100);
                   wypisz_String("inne zdarzenie na magistrali ");
                   I2C0CONSET=0x24;   // ustaw warunek startu oraz bit potwierdzenia
                   I2C0CONCLR=0x08;   // wyczysc flage SI
                   wypisz_Znak(I2C0STAT);
                   return (I2C0STAT);         // zwroc  gdy katastrofa;]
                break;

                }}

    Obawiam się jednak, że sama ta zmiana nie wystarczy (chyba że nadal jest nie tak jak być powinno;)). Tak było na samym początku i efekt był ten sam . Obecnie nie mam żadnego uC bo już 4... (nie wiem nawet jak to nazwać) uszkodziłem? zepsułem? Szczerze mówiąc dziwi mnie fakt uszkodzenia jednego układu peryferyjnego.

    0
  • #4 04 Cze 2012 18:08
    Jado_one
    Poziom 22  

    Ja to zawsze zaczynałem zabawę z I2C w nowej rodzinie procesorów od podłączenia takiego scalaka - PCF8574. To jest po prostu jeden port I/O (expander) ustawiany/odczytywany przez I2C. Można łatwo sprawdzić czy na którymś z jego pinów pojawił się odp. stan logiczny po wysłaniu bajtu przez I2C - i odwrotnie - wymuszając dany stan logiczny na danym pinie PCF'a możemy go potem przez I2C odczytać (stan całego portu PCF'a).
    W ten sposób można łatwo sprawdzić poprawność działania transmisji I2C - warunek startu, adresowanie, zapis i odczyt, warunek stopu. Jak to już działa, to można pisać bardziej skomplikowaną komunikację z innymi scalakami.

    No, chyba, że ktoś ma analizator stanów logicznych - to może od razu z ekranu analizować I2C ;-)

    0
  • #5 04 Cze 2012 23:05
    pawelma17
    Poziom 9  

    No właśnie expander ten posiadam. Zmontowałem układ zgodny z książką pana Majewskiego z wydawnictwa BTC. Wykorzystałem też program z tej książki do tego expandera ale nic nie poszło. Więc i2C w tym uC raczej na pewno padł tylko dlaczego?

    0
  • #6 04 Cze 2012 23:53
    Jado_one
    Poziom 22  

    A włączasz peryferium I2C0 w rejestrze PCONP?
    np. tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #7 05 Cze 2012 13:15
    pawelma17
    Poziom 9  

    No właśnie nie "majstrowałem" przy tym rejestrze tak więc zgodnie z manualem wszystkie układy peryferyjne są włączone. Dla pewności odczytałem stan PCONP i bit uruchamiający I2C jest ustawiony.

    0
TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo