Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Przetwornik ADC MCP3208 w języku C. Niejasności.

06 Cze 2010 00:48 4316 34
  • Poziom 20  
    Witam
    Mam pytanie odnośnie "sumowania" danych (MSB i LSB) 8 bitowych w liczbę 16 bitową. Czy jest ono dobrze wykonane?
    Oraz czy dobrze zostało napisane pozbycie się 4 znaczących bitów tej liczby 16 bitowej. I czy było to potrzebne? W pdfie wyczytałem, że dane przesyłane są jedynie poprzez 12 bitów, dlatego wolałem wyzerować te cztery.
    Proszę o odpowiedź.
    Pozdrawiam
    Code:

    #include <avr\io.h>

    #define SS_NISKI() (PORTB &= ~0x10); //stan niski na SS
    #define SS_WYSOKI() (PORTB |= 0x10); //stan wysoki na SS

    unsigned char danaH = 0;
    unsigned char danaL = 0;
    unsigned int danaK = 0;


    int main(void)
    {
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Inicjalizacja
    DDRB |= 0xB0; //ustawienie kierunku bitow portu
    SPCR = _BV(SPE) | _BV(MSTR); //tryb nadrzedny, predkosc 4MHz, wlaczenie SPI, big endian, wlaczenie przerwania
    SS_WYSOKI(); //stan wysoki na SS
    // Koniec inicjalizacji
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Wysyłanie i odbieranie danych od MCP3208
    SS_NISKI();
    SPDR = 0x06;
    while(!(SPSR & (1<<SPIF)));
    danaH = SPDR;
    SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
    danaH = SPDR; //MSB
    SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
    danaL = SPDR; //LSB
    SS_WYSOKI(); //stan wysoki na SS
    // Koniec wysyłania i odbierania
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Utworzenie 16 bitowej liczby z MSB i LSB
    danaK = danaH<<8 | danaL; // Liczba 16 bitowa
    danaK = danaK<<4; // Pozbycie się 4 znaczących bitów
    danaK = danaK>>4;
    //
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    return 0;
    }
  • Poziom 25  
    Nie sumowania, tylko łączenia ;)

    W zasadzie jest ok. Co do zerowania, sugerowałbym takie coś (po pierwsze ładniej, po drugie, unikamy niebezpieczeństwa ingerencji optymalizatora kodu, który mógłby te dwie linijki uznać za zbędne):

    Code:

    danaK &= 0x3FFF;
  • Poziom 20  
    Dziękuję za szybką odpowiedź:)
    Dopiero się uczę C. A jeżeli chciałbym zamienić te dane z mcp3208 na napięcie to wystarczy wykonać: V = danaK * 0,001220703 (przetwornik 12 bitowy zasilany z 5V czyli: 5V/4096). Dobrze myślę?
  • Poziom 20  
    Mógłby ktoś potwierdzić moje przypuszczenia?
    I jeszcze mam jedno pytanie: czy można prosto podać sygnał analogowy na wejście mcp3208 i czy można nóżkę VREF podpiąć prosto do 5V. Ponieważ w datasheetcie jest jakiś schemat na którym to jest strasznie skomplikowane (zdjęcie tego schematu poniżej). Jeśli to ważne to przetwornik będzie konwertował sygnały z akcelerometru i żyroskopu.

    Przetwornik ADC MCP3208 w języku C. Niejasności.
  • Poziom 25  
    Ten schemat to po prostu filtr wygładzający sygnał, który ma być poddany obróbce przez przetwornik.
    Co do reszty się nie wypowiem, bo nie wiem.
  • Poziom 20  
    to ja wiem, ze jest to jakiś filtr. Tylko nie wiem, czy muszę go wykonać czy mogę się podpiąć z sygnałem prosto na wejścia mcp. I co z tym VREF?
  • Poziom 15  
    Teoretycznie filtr na wejściu być powinien aby uniknąć zjawiska aliasingu, które wystąpi gdy jakaś składowa sygnału próbkowanego (czyli podanego na wejście przetwornika) będzie miała częstotliwość równą lub większą od połowy częstotliwości próbkowania.

    Tu masz trochę teorii: Twierdzenie Kotielnikowa-Shannona

    Przyjmuje się, że sygnał akustyczny (mowa) mieści się w pasmie 300 Hz - 3500 Hz. Ze względu na "ekonomię przetwarzania" dajesz zwykle najmniejszą możliwość częstotliwość próbkowania.
    Przykładowo, dla mowy (w systemach telekomunikacyjnych, np. w typowej PCM, 64kbps/8bitów) częstotliwość próbkowania to 8kHz, czyli maksymalna częstotliwość sygnału próbkowanego musi być mniejsza niż 4 kHz. Dalego przed przetwornikiem A/C należy zastosować filtr dolnoprzepustowy odpowiedniego rzędu.

    Teraz Twoje pytanie - jeśli jesteś pewien, że w sygnale, który podasz na wejście nie pojawią się składowe o wyższych częstotliwościach, bądź tez dasz próbkowanie na tyle szybkie, że nawet jeśli się pojawią, to będą leżały poniżej częstotliwości Nyquista, to możesz zrezygnować z filtra dolnoprzepustowego (takiego jak na przedstawionym przez Ciebie schemacie) na wejściu. Przy czym nie będzie to rozwiązanie zbyt eleganckie z technicznego punktu widzenia, tak na prawdę nigdy nie wiesz co się pojawi w sygnale (ot, choćby zakłócenia).
  • Poziom 27  
    Jeśli kolega używa przetwornika do analizy sygnału wolnozmiennego to możesz je podać wprost na wejście ale mimo wszystko lepiej jest zastosować bufor który nie będzie obciążał źródła sygnału w układzie wtórnika. Jednak pamiętaj aby był to wzmaczniacz operacyjny rail-to-rail no i generalnie o dobrych parametrach. W kwestii 5 V jako napięcie odniesienia to stosuj go sobie o ile jest dopuszczalne (czytaj notę) i o ile liczysz się z byle jakością przetworzonych napięć. Dobre źródło napięcia odniesienia jest droższe od samego przetwornika, to chyba znamienne ?
  • Poziom 20  
    Dziękuję za odpowiedzi. Wnioskuję z nich, że trzeba zrobić taki filtr.
    Mam jeszcze prośbę o sprawdzenie, czy program jaki stworzyłem ma szansę zadziałać. Ma on wyświetlać napięcie podane na wejście 0 układu MCP3208 na wyświetlaczu LCD ze sterownikiem HD44780. Bardzo proszę o sprawdzenie, jest to dla mnie bardzo ważne.
    Code:

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //      mcp3208.c - plik główny programu obsługi przetwornika anlogowo-cyfrowego 12 bitowego MCP3208
    //
    // Kompilator: WinAVR 20050214
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #include <avr\io.h>
    #include <avr\pgmspace.h>
    #include <inttypes.h>
    #include <stdlib.h>

    #define SS_NISKI() (PORTB &= ~0x10); //stan niski na SS
    #define SS_WYSOKI() (PORTB |= 0x10); //stan wysoki na SS

    // Makra upraszczające dostęp do portów
    // *** Port
    #define PORT(x) XPORT(x)
    #define XPORT(x) (PORT##x)
    // *** Pin
    #define PIN(x) XPIN(x)
    #define XPIN(x) (PIN##x)
    // *** DDR
    #define DDR(x) XDDR(x)
    #define XDDR(x) (DDR##x)

    // Definicje wyprowadzeń
    #define LCD_RS 2
    #define LCD_RSPORT D
    #define LCD_E 1
    #define LCD_EPORT D
    #define LCD_DPORT D
    #define LCD_D4 4
    #define LCD_D5 5
    #define LCD_D6 6
    #define LCD_D7 7

    // Komendy sterujące wyświetlaczem
    #define LCDC_CLS      0x01
    #define LCDC_HOME      0x02
    #define LCDC_MODE      0x04
       #define LCDC_MODER      0x02
       #define LCDC_MODEL      0
       #define LCDC_MODEMOVE   0x01
    #define LCDC_ON         0x08
       #define LCDC_ONDISPLAY   0x04
       #define LCDC_ONCURSOR   0x02
       #define LCDC_ONBLINK   0x01
    #define LCDC_SHIFT      0x10
       #define LCDC_SHIFTDISP   0x08
       #define LCDC_SHIFTR      0x04
       #define LCDC_SHIFTL      0
    #define LCDC_FUNC      0x20
       #define LCDC_FUNC8b      0x10
       #define LCDC_FUNC4b      0
       #define LCDC_FUNC2L      0x08
       #define LCDC_FUNC1L      0
       #define LCDC_FUNC5x10   0x4
       #define LCDC_FUNC5x7   0
    #define LCDC_CGA      0x40
    #define LCDC_DDA      0x80

    //-----------------------------------------

    unsigned char danaH = 0;
    unsigned char danaL = 0;
    unsigned int danaK = 0;
    float danaV = 0;

    // Generowanie opóźnień
    #define delay250ns() {asm volatile("nop"::);}

    #define delayus8(t)\
       {asm volatile( \
          "delayus8_loop%=: \n\t"\
          "nop \n\t"\
          "dec %[ticks] \n\t"\
          "brne delayus8_loop%= \n\t"\
       : :[ticks]"r"(t) );}
       // DEC - 1cykl, BRNE 2cykle, +1xnop. Zegar 4MHz
       
    void delay100us8(uint8_t t)
    {
       while(t>0)
       {
          delayus8(100);
          -t;
       }
    }
    // Koniec opóźnień
    //-----------------------------------------

    #define LCD_EPULSE() \
       {PORT(LCD_EPORT) |= 1<<LCD_E; \
       delay250ns(); \
       PORT(LCD_EPORT) &= ~(1<<LCD_E);}
       
    void LCDsendHalf(uint8_t data)
    {
       data = (data & 0x0F) << LCD_D4;
       PORT(LCD_DPORT) =
          (PORT(LCD_DPORT) & ~(0x0F<<LCD_D4)) | data;
       LCD_EPULSE();
    }

    void LCDsend(uint8_t data)
    {
       // Starsza część
       LCDsendHalf(data>>4);
       // Młodsza część
       LCDsendHalf(data);
       delayus8(120);
    }

    // Funkcje interfejsu
    void LCDcommand(uint8_t command)
    {
       PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
       LCDsend(command);
    }

    void LCDdata(uint8_t data)
    {
       PORT(LCD_RSPORT) |= 1<<LCD_RS;
       LCDsend(data);
    }

    void LCDcls(void)
    {
       LCDcommand(LCDC_CLS);
       delay100us8(48);
    }

    void LCDhome(void)
    {
       LCDcommand(LCDC_HOME);
       delay100us8(48);
    }

    // Funkcja inicjacji wyświetlacza
    void LCDinit(void)
    {
       delay100us8(150);
       PORT(LCD_RSPORT) &= ~(1<<LCD_RS);
       LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
       delay100us8(41);
       LCDsendHalf(LCDC_FUNC|LCDC_FUNC8b);
       delay100us8(2);
       LCDsendHalf(LCDC_FUNC|LCDC_FUNC4b);
       delay100us8(2);
       // Teraz jest już 4b. Koniec korzystania z sendHalf
       LCDcommand(LCDC_FUNC|LCDC_FUNC4b|LCDC_FUNC2L|LCDC_FUNC5x7);
       LCDcommand(LCDC_ON);
       LCDcls();
       LCDcommand(LCDC_MODE|LCDC_MODER);
       LCDcommand(LCDC_ON|LCDC_ONDISPLAY|LCDC_ONCURSOR);
    }
    //-------------------------------------------------------------

    void LCDstr_P(prog_char* str)
    {
       char znak;
       while(0 != (znak =
    pgm_read_byte(str++)))
          LCDdata(znak);
    }

    void LCDstr(char* str)
    {
       char znak;
       while( 0 != (znak = *(str++)) )
          LCDdata(znak);
    }

    // Wypisuje liczbę na wyświetlaczu
    void LCDdec(int val)
    {
       char bufor[7];
       LCDstr(itoa(val, bufor, 10));
    }

    int main(void)
    {
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Inicjalizacja MCP3208
    DDRB |= 0xB0; //ustawienie kierunku bitow portu
    SPCR = _BV(SPE) | _BV(MSTR); //tryb nadrzedny, predkosc 4MHz, wlaczenie SPI, big endian, wlaczenie przerwania
    SS_WYSOKI(); //stan wysoki na SS
    // Koniec inicjalizacji
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Inicjalizacja LCD
    DDR(LCD_DPORT) = 1<<LCD_E | 1<<LCD_RS | 0x0F<<LCD_D4;
       
    LCDinit();
    // Koniec incjacji
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    LCDcls();



    for(;;)
    {
       // Wysyłanie i odbieranie danych od MCP3208
       SS_NISKI();
       SPDR = 0x06;
       while(!(SPSR & (1<<SPIF)));
       danaH = SPDR;
       SPDR = 0x00;
       while(!(SPSR & (1<<SPIF)));
       danaH = SPDR; //MSB
       SPDR = 0x00;
       while(!(SPSR & (1<<SPIF)));
       danaL = SPDR; //LSB
       SS_WYSOKI(); //stan wysoki na SS
       // Koniec wysyłania i odbierania
       ///////////////////////////////////////////////////////////////////////////////////////////////////////////////


       ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       // Utworzenie 16 bitowej liczby z MSB i LSB
       danaK = danaH<<8 | danaL; // Liczba 16 bitowa
       danaK &= 0x3FFF; // Pozbycie się 4 znaczących bitów
       danaV = danaK * 0,00122; // Zamiana odczytanej informacji na napięcie 5V/4096
       LCDstr_P((prog_char*)PSTR("Dane z ADC"));

       LCDcommand(LCDC_DDA | 64);
       LCDdec(danaV);
       LCDstr_P((prog_char*)PSTR("  "));
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    return 0;
    }
  • Poziom 27  
    kolego Twoja bezczelność ma jakieś granice ? :) Nos też chcesz aby Tobie wytrzeć ? Właczaj symulator i do roboty :)
  • Poziom 20  
    Nie jestem bezczelny. Nie potrzebnie wrzucałem całość:) Najbardziej chodzi mi o ostatni fragment, a dokładnie o zamianę danej z MCP3208 na napięcie i wyświetlenie jej na wyświetlaczu:
    Code:

       // Utworzenie 16 bitowej liczby z MSB i LSB
       danaK = danaH<<8 | danaL; // Liczba 16 bitowa
       danaK &= 0x3FFF; // Pozbycie się 4 znaczących bitów
       danaV = danaK * 0,00122; // Zamiana odczytanej informacji na napięcie 5V/4096
       LCDstr_P((prog_char*)PSTR("Dane z ADC"));

       LCDcommand(LCDC_DDA | 64);
       LCDdec(danaV);
       LCDstr_P((prog_char*)PSTR("  "));
    }
  • Poziom 20  
    Mógłby ktoś sprawdzić tylko ten fragmencik. Dopiero zaczynam naukę c. Za bardzo się nie znam na avr studio, dlatego nie wiem jak przeprowadzić tę symulację.
    Pozdrawiam
  • Poziom 38  
    google - avr simulator i BACH !! co wyskakuje ?? http://www.oshonsoft.com/avr.html

    poza tym w avr studio można włączyć tryb debuggingu (gdzieś na pasku jest coś takiego). Dziwnie się tłumaczysz, że nie znasz AVR studio, tak jakby były tam tylko nieopisane przyciski z obrazkami, a czytać umiemy? :P
  • Poziom 20  
    Ściągnąłem AVR Simulator IDE ładuję program ale na tym niby wyświetlaczu nic się nie pojawia. A w ogóle to nie wiem jak symulować dane z MCP3208 przez SPI. A AVR Studio staje na wstawce w asemblerze z opóźnieniami. Jak próbuję użyć opcji 'run to cursor' i ustawiam kursor za tymi wstawkami to program jakby się wiesza i trzeba nacisnąć 'reset'(Shift + F5).
  • Poziom 27  
    Samo złożenie MSB i LSB danej z przetwornika na moje oko jest poprawne a co do reszty nie wiem bo także zależy to od sprzętu a munkcji LCD nie chce mi się analizować. Jeśli nic się nie wyświetla spróbuj cokolwiek na LCD wyświetlić i jeśli jest OK to problem jest z zamianie liczby int na wartośc tekstową jesli jednak wyświetlacz jest czysty bład tkwi albo w złym jego podłaczeniu albo w procdurach odpowiedzialnych za wyświetlanie.
  • Poziom 20  
    Dziękuję za odpowiedź. Nie jestem pewny co do zamiany danej na napięcie:
    Code:

    float danaV = 0;

     danaV = danaK * 0,00122; // Zamiana odczytanej informacji na napięcie 5V/4096
       LCDstr_P((prog_char*)PSTR("Dane z ADC"));

       LCDcommand(LCDC_DDA | 64);
       LCDdec(danaV);
       LCDstr_P((prog_char*)PSTR("  "));


    czy zmienna danaV musi być typu float?
  • Poziom 27  
    Jeśli chcesz uzyskac aptekarską dokłaność to tak :) Gdybyś użył normalnego napięcia odniesienia czyli 4,1V nie miałbyś w ogóle tego problemu poza tym napięcie zasilania nie jest dobrym pomysłem na napięcie odniesienia. W tym przypadku musisz wykonywać niepotrzebne mnożenie a brak ci zamiany float na int. O ile się nie pomyliłem to wystarczy taka deklaracja
    Code:

    float costam;
    unsigned int zmiana;

    zmiana= (int)(costam);

    zdaje się że takie działanie też jest poprawne

    Code:

    zmiana=(int)(costam * 1,234567);

    tylko po co skoro można było się bez tego w ogóle obyć przy 4,1V
  • Poziom 20  
    Dziękuję za odpowiedź:)
    Nie rozumiem czemu brakuje zamiany float na int. Czy ten fragment jej nie realizuje?
    Code:

    // Wypisuje liczbę na wyświetlaczu
    void LCDdec(int val)
    {
       char bufor[7];
       LCDstr(itoa(val, bufor, 10));
    }


    Ten przetwornik będzie przetwarzał sygnały z analogowego akcelerometru i żyroskopu. Projekt to balansujący robot, coś jak segway:)
  • Poziom 27  
    Generalnie nie bardzo rozumiem o co tobie chodzi pytając o braki zamiany float na int ? Natomiast ten fragment kodu zamienia zmienną int na odpowiadający jej ciąg znaków w postaci tekstowej, czyli zamienia wartość numeryczna na ciąg znaków. Innych danych jak wartości kodów ASCII , lcd nie wyświetli i stąd ta zamiana. Niestety Ty kolego uparłeś się (używając swojego napięcia 5V) na jakieś liczby typu float i teraz bujasz się z zamianą, myślę że przy okazji popełniasz jakieś błedy ale kodu zaznaczam nie mam ochoty za ciebie przerabiać.
  • Poziom 20  
    Ok masz racje. Kupię układ, który daje napięcie odniesienia 4,096V (MCP1541). Wtedy wystarczy tylko daną z MCP podzielić przez 1000 i będzie napięcie. Dobrze myślę? Ale jakiego typu musi wtedy być tan zmienna przechowująca napięcie, także float? Czyli to niczego nie uprości?
  • Poziom 27  
    Mylisz się nic nie trzeba będzie robić żadnego dzielenia ani mnożenia. Wartość liczby będzie 12 bitowa czyli maksymalnie 4095 (liczba int) więc aby wyrazić ją w voltach wystarczy między liczbą reprezentującą tysiące a setki wstawić po prostu znak przecinka i będziesz miał "ludzką" postać swojego napięcia.
  • Poziom 20  
    A jak to zapisać w c (jak wstawić ten przecinek?)
  • Poziom 20  
    Mógłbyś napisać jak wstawić tam ten przecinek. Szukałem w Internecie ale nie umiem znaleźć nic na ten temat:/
  • Poziom 27  
    definiujesz sobie bufor jako ciąg znaków string który z miejsca jest wypełniony znakami (masz już tam swój przecinek
    Code:
    unsigned char buffer[]="00,000";

    teraz wyznaczasz resztę z dzielenia przez 10 wpisujesz w odpowiednie miejsce bufora i dzielisz swoją wartość przez 10 i zapamiętujesz w zmiennej, Operację tę powtarzasz dotąd aż wartość twojego napięcia nie osiągnie 0 albo nie osiągniesz początku bufora,oczywiście po kolei zapełniając odpowiednie miejsca w buforze.
    Znaki wstawiasz od końca czyli od jednostek do dziesiątek tysięcy,
    Przecinka nie wstawiasz bo wystarczy że pominiesz ten znak podczas zapełniania bufora dla znaku odpowiadającemu tysiącowi. Odzywiście wartość liczbowa na odpowiednim miejscu nie jest tym samym co odpowiedni znak w ASCII więc trzeba do liczby np 0 dodac wartość 0x30 aby uzyskac tekstowe 0. Czy kolega pojął zasadę ?
  • Poziom 20  
    Nie do końca:) Czyli rozumiem, że najpierw obliczam resztę z dzielenia wartości zapisanej w zmiennej danaK przez 10 i zapisuję ją w buforze w miejscu jedności.
    Teraz biorę znowu zmienną danaK i dzielę przez 10 i zapisuję ją do bufora w miejsce dziesiątek. Teraz biorę danaK/10 i dzielę jeszcze raz przez 10 i zapisuję do bufora na miejscu setek. I tak dalej, aż wartość zmiennej danaK dzielonej ileś tam razy przez 10 nie osiągnie 0 albo nie osiągnie wartości z miejsca dziesięciotysięcznego. Na koniec mam zamienić daną z bufora na ASCII dodając 0x30.
    Tak mniej więcej to zrozumiałem. Ale przypuszczam, że to nie miało tak wyglądać:)
  • Poziom 27  
    Prawie tak ale...
    Na kolejnycm miejscach w buforze wpisujesz zawsze resztę z dzielenia przez 10 jednak po każdym takim cyklu liczbę której to wyznaczasz resztę z dzielenia musisz podzielić przez 10 i przypisac jej nowy wynik np.
    Code:
    liczba=liczba/10;
    bo tym samym nie osiągniesz spodziewanego efektu. No i co także istotne liczbie 1 w ASCII odpowiada 0x31 więc wynik z reszty dzielenia trzeba powiększyć o 0x30.
  • Poziom 20  
    Dziękuję za odpowiedź. Czy chodzi mniej więcej o coś takiego? (danaK to informacja z MCP3208, danaV to reszta z dzielenia /10, n pomocnicza zmienna 0-4)
    Code:

    unsigned char buffer[] = "00,000";
    unsigned int danaV = 0;
    unsigned int n = 0;

    for (danaK !=0; danaK != danaV; n<=4; n++)
    {
       danaV = danaK%10;
       danaV = danaV + 0x30;
       danaV = buffer[n];
       danaK = danaK/10;
    }

    LCDdec(buffer);
  • Poziom 27  
    ja bym to zrobił na przyklad tak
    Code:

    unsigned char buffer[] = "00,000";
    unsigned int danaV = 0;
    unsigned char reszta = 0;
    char licznik=0;
    // tutaj miejsce na odczyt wartości napięcia i zapis jej do danaV
    // bo póki co ma wartość zerową
    for(licznik=5;licznik >0;licznik--){
                 if(licznik==2){
                         licznik--;
                 }
                 reszta=danaV%10;
                 buffer[licznik]=reszta+0x30;
                 danaV=danaV/10;
    }
    LCDdec(buffer);
  • Poziom 12  
    Wydaje mi się, że widzę kilka błędów, ja bym to napisał tak:

    Code:

    unsigned char buffer[] = "00,000";
    unsigned int danaV = 0;
    char n; //bez unsigned, inaczej się zapętli

    danaV = danaK; //żeby nie psuć zmiennej danaK, jeśli Ci to nie robi, to możesz w pętli operować na zmiennej danaK
    for (n=5; n>=0; n--)
    {
       if (n==2) continue; //omijanie przecinka
       buffer[n] = danaV%10 + 0x30;
       danaV /= 10; //taka notacja jest równoważna danaV = danaV/10;
    }


    A tak poza tym, nie rozumiem zupełnie w jaki sposób
    Code:
    danaV = buffer[n];
    miało zmienić tablicę buffer. Zmienną, którą modyfikujemy dajemy po lewej znaku równości, mam nadzieję, że to wiesz :)

    Poza tym, zmieniłem kierunek pętli – musimy pamiętać, że ten sposób konwersji liczb na dziesiętny daje nam najpierw cyfry jedności, więc musimy zaczynać od prawej.

    Swoją drogą, zastanawiam się, czy nie można by skorzystać z biblioteki cstdio w taki np. sposób:

    Code:
    #include <stdio.h>
    
    (...)

    char str[6];
    sprintf(str,"%2d,%03d",danaK/1000,danaK%1000);


    i już byśmy mieli napis str gotowy do wrzucenia na wyświetlacz, bez żadnych pętli. Nie korzystałem jeszcze ze standardowych bibliotek c przy pisaniu na AVRa. Je się includuje tak po prostu, czy trzeba jakoś filozofować?

    Wybaczcie błędy, jak będą, pisałem z głowy.

    Polecam i pozdrawiam,
    krdln

    Edit: miałem błąd w ominijaniu przecinka, omijałem go dwa razy: raz za pomocą n-- i raz za pomocą continue xD
  • Poziom 20  
    bardzo dziękuję za pomoc:)

    Dodano po 2 [minuty]:

    tylko teraz nie wiem od kogo fragment mam zastosować:)

    Dodano po 2 [minuty]:

    Code:
    danaV = buffer[n]; 
    masz rację strasznie głupi błąd. Miało być na odwrót:D

    Dodano po 14 [minuty]:

    Próbowałem z obydwoma fragmentami kodu. W każdym przypadku program się kompiluje, jednak są jakieś błędy (mniej więcej takie same):
    Code:

    ompiling: mcp3208.c
    avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=mcp3208.lst  -std=gnu99 -MD -MP -MF .dep/mcp3208.o.d mcp3208.c -o mcp3208.o
    mcp3208.c: In function `main':
    mcp3208.c:233: warning: array subscript has type `char'
    mcp3208.c:240: warning: passing arg 1 of `LCDdec' makes integer from pointer without a cast
    mcp3208.c: In function `delay100us8':
    mcp3208.c:89: warning: statement with no effect