Atmega8 a převodník AD7710

Zdravím vespolek,

potřeboval bych od vás poradit se zapojením AD převodníku AD7710 s Atmegou. Postupoval jsem sice podle dokumentací k oběma obvodům (AD7710 zde a Atmega8 zde), ale stále se mi to nedaří.

Sestavil jsem si následující obvod:

Knihovnu pro LCD displej používám tuto.

Můj kód:

[code]#define F_CPU 20000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include “lcd/lcd.h”

#define PIN_DRDY _BV(PB0) // vstup
#define PIN_RFS _BV(PB1) // výstup
#define PIN_TFS_A0 _BV(PB2) // výstup
#define PIN_SDATA_WRITE _BV(PB3) // výstup
#define PIN_SDATA_READ _BV(PB4) // vstup
#define PIN_SCLK _BV(PB5) // výstup

unsigned long read_spi_data() {
unsigned long r = 0UL;
while(!(SPSR & _BV(SPIF)));
r |= SPDR;
while(!(SPSR & _BV(SPIF)));
r |= SPDR << 8;
while(!(SPSR & _BV(SPIF)));
r |= (unsigned long) SPDR << 16;
return r;
}

int main(void) {
DDRB = PIN_SDATA_WRITE | PIN_SCLK | PIN_RFS | PIN_TFS_A0;
PORTB &= ~(PIN_SDATA_READ | PIN_DRDY);

PORTB |= PIN_TFS_A0;
PORTB |= PIN_RFS;

// input capture (PB0):
TCCR1B &= ~_BV(ICES1); // sestupná hrana
TIMSK |= _BV(TICIE1);

// SPI:
SPCR = _BV(SPE) | _BV(MSTR);

LCDInit(LS_NONE);
LCDClear();
LCDWriteString("AD7710AN test");

while(1) {
	_delay_ms(500);
}

}

ISR(TIMER1_CAPT_vect) {
PORTB &= ~PIN_RFS;
unsigned long data = read_spi_data();
LCDWriteIntXY(0, 1, data, 5);
PORTB |= PIN_RFS;
}
[/code]

Jasně, že ten kód má plno nedostatků, které ovšem doladím, až rozchodím ten převodník.

Předpokládám, že při měření např. pomocí prvního kanálu zapojím AIN1- do GND a AIN1+ do měřeného úseku (od 0 do 5 V).

Poraďte mi prosím, pokud si s tímto víte rady. Díky.
schema-ad7710.png

Nenapsal jsi, co se Ti na tom nedaří. Jestli komunikace nebo nesmyslný data. Pokud se Ti vrací nesmyslný data, viděl bych problém tady :

Data z převodníku jsou B23,…,B0. Jenže Ty je do r ukládáš B7,…,B0,B15,…,B8,B23,…,B16, protože :
do r uložíš bity B23-B16
přečteš bity B15-B8, posuneš je o 8 pozic doleva a přidáš k r
přečteš bity B7-B0, posuneš je o 16 pozic doleva a přidáš k r

Správně by to měo být takhle :

unsigned long read_spi_data() { unsigned long r = 0UL; while(!(SPSR & _BV(SPIF))); r |= SPDR; while(!(SPSR & _BV(SPIF))); r <<= 8; r |= SPDR; while(!(SPSR & _BV(SPIF))); r <<= 8; r |= SPDR; return r; }

do r uložíš bity B23-B16
otočíš r o 8 bitů doleva
přečteš bity B15-B8 a přidáš k r
otočíš r o 8 bitů doleva
přečteš bity B7-B0 a přidáš k r

Vím, že ve funkci read_spi_data() byla nejspíš chyba, přesto mi právě o tohle nešlo, ale díky za opravu :wink:.

Jde o to, že vůbec nefunguje samotná komunikace. Nejsem si jistý, jestli mám správně nastavený input capture i SPI registry.
V dokumentaci převodníku toho moc o té SPI komunikaci není. Např. nevím, jestli nastavit nějakou konkrétní SCK frekvenci pomocí SPR1, SPR0 v registru SPCR, nebo ponechat frekvenci CPU (tedy 20 MHz).

Ani si nejsem jistý správností zapojení ve schématu a potřeboval bych, aby mi to někdo případně opravil, protože takhle můžu hledat chyby v programu, když v programu třeba vůbec nejsou.

Díky.

A kde máš pull up odpory, ha?

Pokiaľ po zapnutí/resete mcu nie je pin /SS v log.1 “z vonku”, hw modul SPI mcu sa nastavi do režimu slave a zmeniť to až ďalší reset. Samozrejme so správnou hodnotou napätia na /SS.

S týmto som sa “pekne” vyhral na ATmega32. SPI som používal v režime Master a z rôznych príčin som ako /CS pre Flash používal iný pin a natívny /SS som použil na už neviem čo, ale skrátka bol cez 100k pulldown o zem. A SPI nie a nie chodiť.

Nemyslím si, že by ATmega8 bola na tom inak.

A nepomôže ani sw nastavenie /SS na výstup s interným pull up-om po resete. Za tých pár mikrosekúnd to už stavový stroj v mcu nezaujíma.

Skrátka nedodržané základné pravidlo, VŽDY maj definované stavy I/O počas resetu.

Fakt si vy “mladí” myslíte, že vám to tu neustále pripomíname pre srandu králikov?
To sa týka aj tých všetkých pinov na konektor. No strach a hrôza :slight_smile: