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

[ATmega][MCP320*] Zly odczyt z SPI

Myrek1 11 Sie 2008 21:26 3467 6
REKLAMA
  • #1 5430410
    Myrek1
    Poziom 23  
    Witam.
    Mam problem z komunikacją ATmega - MCP3208 (ADC, są jeszcze wersje 2 i 4-kanałowe).
    Ramka transmisyjna wygląda tak:

    [ATmega][MCP320*] Zly odczyt z SPI

    Czyli rozumiem, że wysyłam ramkę z init i adresem. Przy założeniu, że DIFF=1, a D2=D1=D0=0 (adres 0 kanału ADC) pierwsza ramka to liczba 0x04. Druga ramka to same zera czyli 0x00, a trzecia jest bez znaczenia.
    Podczas wysyłania pierwszej ramki odczytuje tą z MPC i dostaje coś tam, bezużytecznego. Podczas zapisu drugiej, odczytuje bajt, gdzie cztery najmłodsze bity są MSB liczby 12-bitowej z przetwornika. Wysyłając trzecią ramkę odczytuje kolejny bajt, który jest LSB liczby 12 bitowej. Odpowiednio sklejam obie liczby i mam wynik 12-bitowy. Czy tak?

    Mam do tego taki kod:

    SS_NISKI();
    SPDR = 0x04;
    while(!(SPSR & (1<<SPIF)));
    danaH = SPDR; 
    
    SPDR = 0x00; 
    while(!(SPSR & (1<<SPIF)));
    SPDR = 0x80; 
    danaH = SPDR;
    
    SPDR = 0x00;//wszystko jedno co sie przesle
    while(!(SPSR & (1<<SPIF)));
    danaL = SPDR;
    SS_WYSOKI();


    I nie działa. Odczytuje jakieś dziwne wartości, cały czas się zmieniające w nieprzewidywalny sposób, a na wejście podane jest Vref, czyli wynik przetwarzania to liczba 0x0FFF, a wyskakuje bardzo różna. Czy coś jest nie tak?
  • REKLAMA
  • #2 5430517
    __Grzegorz__
    Poziom 30  
    skoro DIFF=1, to pierwszy bajt będzie 6 nie 4...
  • REKLAMA
  • #3 5430656
    Myrek1
    Poziom 23  
    No fakt, ale to i tak nie zmienia sytuacji. Przy 5V dostaje:
    MSB: LSB
    0x00 0x08
    0xFF 0xFE

    itd, bezsensowne wartości, które nie powinny się aż tak zmieniać.
    Powinno być:

    0x0F 0xFF albo coś w tych granicach.
  • REKLAMA
  • #4 5430711
    __Grzegorz__
    Poziom 30  
    Pokaż kod, którym ustawiasz SPI w procesorze...

    plus napisz jak sterujesz pin CS (automat z MASTER, czy czysto software-owo).
  • REKLAMA
  • #5 5430822
    Myrek1
    Poziom 23  
    Reszta jest ok, bo steruje też z SPI ekspanderem i działa. Procek to ATmega128

    To jest init:
    void spi_init(void)
    {
    	DDRB |= 0b00000111; //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
    }


    SS (CS) jest programowo, tak jak w pierwszym poście, czyli po prostu wyzerowanie albo ustawienie pinu.
    #define SS_NISKI() (PORTB &= ~0x01); //stan niski na SS
    #define SS_WYSOKI() (PORTB |= 0x01); //stan wysoki na SS
  • #6 5431524
    __Grzegorz__
    Poziom 30  
    
    SS_NISKI();
    SPDR = 0x04;
    while(!(SPSR & (1<<SPIF)));
    danaH = SPDR;
    
    SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
    SPDR = 0x80;
    danaH = SPDR;
    
    SPDR = 0x00;//wszystko jedno co sie przesle
    while(!(SPSR & (1<<SPIF)));
    danaL = SPDR;
    SS_WYSOKI();
    

    czyli:
    - ustawiasz CS (OK),
    - wysyłasz 0x04 i czekasz aż wypchniesz dane (OK)
    - wysyłasz 0x00 i czekasz aż wypchniesz dane (OK)
    - wysyłasz 0x80 (?)
    - wysyłasz 0x00 i czekasz (OK)
    - zdejmujesz CS (OK)

    czyli - próbujesz wysłać 1 bajt za dużo....
  • #7 5431616
    Myrek1
    Poziom 23  
    Faktycznie o jeden za dużo, poprawiłem, mam taki kod:

    SS_NISKI();
    			SPDR = 0x06;
    			while(!(SPSR & (1<<SPIF)));
    			danaH = SPDR;
    			SPDR = 0x00;
    			while(!(SPSR & (1<<SPIF)));
    			danaH = SPDR; 
    			SPDR = 0x00;
    			while(!(SPSR & (1<<SPIF)));
    			danaL = SPDR; 
    			SS_WYSOKI();

    I dalej to samo. Dostaje po dwa bajty 0x00 albo po 2 0xFF

    EDIT:

    OK, już działa. Problemem było połączenie w układzie.
    Dzięki
REKLAMA