AVR + proste SPI w C

Witam chcialem sobie odczytac 14 kolejnych bitow na wejsciu uC taktujac uklad zewnetrzny sygnalem SCK. Chodzi tutaj o magistrale SPI. Uklad ten posiada 3 szyny komunikacyjne SCK, CS, SO. W uC niestety nie jest on podlaczony do sprzetowego SPI tylko do portow PD5,PD6,PD7 uC.

Napisalem prosty programik (byc moze zly :)) ktory ma mi te bity pokazac. Zmienna Shift puki co nic nie robi, oraz wiem ze do zmiennej typu char da sie wsadzic tylko 8 bitow. Chodzi o to ze na uarcie widze tylko:

01111111111111 co jest nie prawda poniewaz przedostatni bit zawsze powinien byc zerem. Uklad zaczyna wysylanie danych po CS -> L i nowy bit pokazuje sie po kazdym opadajacym zboczu sygnalu.

#define SPI_PULSE { PORTD &= ~_BV(PD7); PORTD |= _BV(PD7); } //zostaw wysoki do czasu nastepnego pulse.

#define SOIN { DDRD &= ~_BV(PD5); PORTD |= _BV(PD5); } //ustaw jako wejscie, wlacz pullup.

#define CSLOW { DDRD |= _BV(PD6); PORTD &= ~_BV(PD6); } //wyjscie low #define CSHIGH { DDRD |= _BV(PD6); PORTD |= _BV(PD6); } //wyjscie high

unsigned char rspi(void) { uart_puts("-"); register unsigned int BitCnt = 14; register unsigned char Shift; SOIN; CSLOW; do { if(bit_is_set(PORTD,PIND5)) { uart_puts("1"); }else{ uart_puts("0"); } SPI_PULSE; } while (--BitCnt); CSHIGH; return(Shift); }

co robie zle ze to SPI mi nie dziala? wydaje sie proste zrozumienie tego protokolu... ktos mi pomoze?

Pzdr, Mario.

Reply to
angel
Loading thread data ...

Nikt nic mi nie podpowie ? :(

M.

Reply to
angel

Dnia 11-05-2006 o 09:56:43 angel snipped-for-privacy@REMMEszas.uk.to> napisał:

Nie za krótki ten impuls? Dodaj przynajmniej kilka nop-ów. Poza tym nie inicjalizujesz PD7 jako wyjścia.

Reply to
Ostry

Poprawilem nieco program:

#define SPI_INIT { DDRD |= _BV(7); DDRD |= _BV(6); DDRD &= ~_BV(5); /*PORTD |= _BV(5);*/ }

#define SPI_PULSE { PORTD &= ~_BV(7); delay_us(1); PORTD |= _BV(7); }

#define READ_MSO ( PIND & ( 1 << 5))

#define CSLOW { PORTD &= ~_BV(6); } #define CSHIGH { PORTD |= _BV(6); }

unsigned char rspi(void) { uart_puts("-"); SPI_INIT; register unsigned int BitCnt = 14; register unsigned char Shift; CSLOW; do { if(READ_MSO) { uart_puts("1"); }else{ uart_puts("0"); } SPI_PULSE; } while (--BitCnt); CSHIGH; delay_us(10); return(Shift); }

ale dalej nie dziala :( zwraca mi bity 0, jak uruchomilem go na debbugerze w Avr studio i klikam PIND5 (zaznaczony co powinno dac 1 na PD5) program nie reaguje i ciagle zwraca 0. Czy zle czytam port? Czy w debuggerze to nie wyjdzie?

m.

Reply to
angel

angel snipped-for-privacy@REMMEszas.uk.to> napisał(a):

Nie wiem co Ty za pin klikasz , bo u mnie toto działa.

P.

Reply to
Piotrek Sz.

angel snipped-for-privacy@REMMEszas.uk.to> napisał(a):

Dziwne :( Może symulator sumuluje innego proca , a Ty kompilujesz na innego ? Spróbuje tego:

#include <avr/io.h> //ATMega32 #define F_CPU 1000000UL #include <util/delay.h>

#define SPI_INIT { DDRD |= _BV(7); DDRD |= _BV(6); DDRD &= ~_BV(5); /*PORTD |= _BV(5);*/ }

#define SPI_PULSE { PORTD &= ~_BV(7); _delay_us(1); PORTD |= _BV(7); }

#define READ_MSO ( PIND & ( 1 << 5))

#define CSLOW { PORTD &= ~_BV(6); } #define CSHIGH { PORTD |= _BV(6); }

void uart_puts(char *g) //ot,żeby był ;) {

*g>>=1; }

int main(void) { uart_puts("-"); SPI_INIT; register unsigned int BitCnt = 14; register unsigned char Shift; CSLOW; do { if(READ_MSO) { uart_puts("1"); }else{ uart_puts("0"); } SPI_PULSE; } while (--BitCnt);

return(0); }

P.

Reply to
Piotrek Sz.

Masz AVR Studio 4.12 z SP2? Bo kurcze, w innym moim programie podobny fragment zachowuje sie dokladnie tak samo, z kolei "na zywo" dziala. Wydaje mi sie, ze w AVR Studio jest blad w debuggerze. Po kliknieciu na bit w PIN zmienia sie prawidlowo wartosc hex, kratka zaczernia, ale program odczytuje taki bit jako 0, a nie 1. Mozecie to potwierdzic?

Reply to
T.M.F.

Tak, mam 4.12 z SP2.

Docelowo program wyglada tak:

#define SPI_INIT { DDRD |= _BV(7); DDRD |= _BV(6); DDRD &= ~_BV(5); PORTD |= _BV(5); } //2 wyjscia , 1 wejscie dla SO + pullup

#define SPI_PULSE_H { PORTD |= _BV(7); } #define SPI_PULSE_L { PORTD &= ~_BV(7); }

#define READ_MSO ( PIND & ( 1 << PD5))

#define CSLOW { PORTD &= ~_BV(6); } #define CSHIGH { PORTD |= _BV(6); }

unsigned char rspi(void) { uart_puts("-"); register unsigned int BitCnt = 14; register unsigned int w = 0; register unsigned char Shift; CSLOW; asm volatile ("nop"); do { SPI_PULSE_L; asm volatile ("nop");

if(READ_MSO) w++;

SPI_PULSE_H; asm volatile ("nop"); } while (--BitCnt); CSHIGH; uart_puti(w); return(Shift); }

jako wynik dostaje 14, co oznacza ze wszystkie odebrane dane to 1dynki. Jak wylacze pullup dla pind5 dostaje wynik 0 czyli same zera. Czy SPI uzywa pullupow? Ten uklad z ktorym sie komunikuje uzywa sprzetowego SPI i jest domyslnie jako slave. Czemu nie moge go przeczytac? Zmiana czasow trwania zboczy poprzez dodanie delay_us nic nie daje... ciagle nie dziala. Skoro to uC narzuca wygnal taktujacy to w czym jest problem? Sprawdzalem woltomierzem CS ustawia sie na low poprawnie, taktu zegara nie jestem w stanie zlapac :))

M.

Reply to
angel

Czy na porcie D musze cos wylaczac zeby byl on normalnym portem w atmega32 ???

Reply to
angel

Dnia Fri, 12 May 2006 11:21:59 +0200, angel napisał(a):

A zwykłe "blinkanie" diodą czy transmisja stałego znaku na UART działa? Podłączył kolega analogowe zasilanie? Kondensatory odsprzęgające przy procku są? Zasilacz nie sieje jakimiś śmieciami?

Uff! ;) Marcin Stanisz

Reply to
Marcin Stanisz

Wszystko siedzi na jednej plytce za LM7805. Zrodlo zasilania jest jedno.

M.

Reply to
angel

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.