Перейти к содержанию
    

Пытаюсь наладить связь ATmega8 (7.3728 MHz) с ADS1242 (2.4576 MHz) по SPI (WinAVR).

Вопрос : как узнать что пришли данные от ADS1242.

Инициализирую SPI ATmega8 как мастер:

void SPI_MasterInit(void) {

// MOSI,SCK,SS на выход, MISO на вход

DDRB=0x2E;

// Включение SPI, мастер, частота /32

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);

SPSR = (1<<SPI2X);

PORTB|=(1<<2);

void SPI_Transmit(unsigned char cData) {

/* Запуск передачи данных */

SPDR = cData;

/* Ожидание завершения передачи данных */

while(!(SPSR & (1<<SPIF)));

 

В документации на ADS1242 написано, что для чтения данных из регистра нужно послать команду

Encoding: 0001 rrrr xxxx nnnn (rrrr - номер первого регистра для чтения, nnnn читать колличество регистров после первого )

 

Читаю так:

PORTB&=(~(1<<2));//выбор чипа SS=0;

SPI_Transmit(0x10);//читать регистр с номером 0x00

SPI_Transmit(0x01);// читать 2 регистра начиная с первого

_delay_us (25);// задержка по даташиту мин. 50 Tosc(2.4576)

USART_Transmit(SPDR);//пытаюсь прочитать присланные данные

PORTB|=(1<<2);//SS выставляю в 1 для сброса

читаються то 0x00 то 0xFF

Как понять что данные о первом регистре уже пришли их нада прочитать, ну а затем соответственно и данные от второго регистра

Подскажите что не так

ADS1242.pdf

Изменено пользователем URANst

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

PORTB&=(~(1<<2));//выбор чипа SS=0;

SPI_Transmit(0x10);//читать регистр с номером 0x00

SPI_Transmit(0x01);// читать 2 регистра начиная с первого

_delay_us (25);// задержка по даташиту мин. 50 Tosc(2.4576)

USART_Transmit(SPDR);//пытаюсь прочитать присланные данные

PORTB|=(1<<2);//SS выставляю в 1 для сброса

читаються то 0x00 то 0xFF

Как понять ...

SPI ведь у нас как работает? Для того, чтобы прочитать, нужно послать :) Ну, в общем, наиболее частом случае.

Если хотите прочитать 2 регистра, то читаем доку, стр.19, и обращаем внимание на Data Transfer Sequence.

Попробуйте вместо выделенной строки вставить что-нибудь вроде:

SPI_Transmit(0xAA); //На самом деле, неважно что посылать
USART_Transmit(SPDR); //Посылаем данные из первого регистра
SPI_Transmit(0xAA); //Тут тоже неважно что посылать
USART_Transmit(SPDR); //Посылаем данные из второго регистра

Удачи!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SPI_Transmit(0xAA); //На самом деле, неважно что посылатьUSART_Transmit(SPDR); //Посылаем данные из первого регистраSPI_Transmit(0xAA); //Тут тоже неважно что посылатьUSART_Transmit(SPDR); //Посылаем данные из второго регистра

 

Что то я вас не пойму : что значит неважно что посылать ? Там помойему четко написано : для того что бы прочитать регистр нужно записать 0001 - номер регистра(4 бита) - количество регистров(8 бит): всего 2 байта.

Может вы не совсем поняли USART_Transmit(SPDR); читает принятые от АЦП данные и посылает по RS232.

Так вот я спрашивал как мне узнать что из 2-ух байт, которые должны прити, сейчас пришел первый из них, а потом второй . Я имею ввиду может SPIF какой устанавливается или еще что. И еще как поступать если програмирую ATmega8 по SPI. Это оказывает какое влияние на АЦП и если да то что делать. Пока при попытке прочитать шлю 00010000 00000000 (прочитать значение регистра с номером 0x00) принимаю строго 0xFF. Что за ерунда кто скажет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2URANst

 

Я полагаю, что должно быть так:

 

#include <avr\io.h>

#define SPI_PORT PORTB
#define SPI_DDR DDRB

#define MOSI_P PB3 
#define MISO_P PB4
#define SCK_P PB5
#define SS_P PB2

// При этом, SS_P подключен к чип-селектку ведеомого устройства


// Эта функция сдвигает по SPI один байт, и возвращает байт,
// прочитанный со слейва
uint8_t spi_shift_byte(uint8_t data)
{    
    SPI_PORT &= ~(1 << SS_P);

    SPDR = data;
    while(!(SPSR & (1 << SPIF)));
    
    SPI_PORT |= (1 << SS_P);
    
    return SPDR;
}


int main(void)
{

    uint8_t data[3]; // Данные прочитанные с АЦП
    
    //////////////////////////////////////////////////////////////////////////
    // Настройки SPI    
    SPI_DDR = (1 << MOSI_P)|(1 << SCK_P)|(1 << SS_P);
    SPI_PORT = (1 << SS_P); // Чипселект в еденице - приемник неактивен
    SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR1); 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    // Далее, судя по документации, делать нужно так:
    
    spi_shift_byte(0x01); // Код команды
    spi_shift_byte(0); // Байт параметров (как я понял). Оставляем пустым
    
    // Далее читаем три байта ригистра АЦП:
    data[2] = spi_shift_byte(0); // Старший байт
    data[1] = spi_shift_byte(0); // Средний байт
    data[2] = spi_shift_byte(0); // Младший байт    
    
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

До чтения данных оцифровки я еще не дошел (комманда 0x01 по моему она используется без байта параметров).

Я хотел пока прочитать настройки АЦП (регистры SETUP и т.д.) вот сдесь используются команды по 2 байта. Так вот с этим непонятки. В даташите в Data Transfer Sequence еще стоит задержка с которой тож не совсем ясно. С SPI работаю первый раз, так что кто чем может, кто работал уже подскажите как ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2URANst

Вот я попытался изобразить функции чтения/записи группы регистров. Плюс, некоторые изменения вне в функцию spi_shift_byte.

 

#include <avr\io.h>
#include <util/delay.h>

#define SPI_PORT PORTB
#define SPI_DDR DDRB

#define MOSI_P PB3 
#define MISO_P PB4
#define SCK_P PB5
#define SS_P PB2

#define SELECT() SPI_PORT &= ~(1 << SS_P)
#define DESELECT() SPI_PORT |= (1 << SS_P)

// При этом, SS_P подключен к чип-селектку ведеомого устройства


// Эта функция сдвигает по SPI один байт, и возвращает байт,
// прочитанный со слейва
uint8_t spi_shift_byte(uint8_t data)
{

    SPDR = data;
    while(!(SPSR & (1 << SPIF)));    
    
    return SPDR;
}

adc_read_registers(uint8_t start_address, uint8_t count, uint8_t* buffer)
{
    start_address &= 0x0F;
    count &= 0x0F;

    SELECT();
    
    spi_shift_byte(0x08 | (start_address)); // 0001 rrrr
    spi_shift_byte(count - 1); // xxxx nnnn, почему "минус 1" - написано в документации
   
    // Задержку, я думаю подберете сами...
    _delay_us(25);
    
    for (;count; count--, buffer++)
        *buffer = spi_shift_byte(0); // Читаем count регистров в массив buffer

    DESELECT();
}

adc_write_registers(uint8_t start_address, uint8_t count, uint8_t* buffer)
{
    start_address &= 0x0F;
    count &= 0x0F;
    
    SELECT();
    
    spi_shift_byte(0x50 | (start_address)); // 0101 rrrr
    spi_shift_byte(count - 1); // xxxx nnn, почему "минус 1" - написано в документации
    
    for (;count; count--, buffer++)
        spi_shift_byte(*buffer); // Передаем count значений из массива buffer
        
    DESELECT();
}


int main(void)
{
    //////////////////////////////////////////////////////////////////////////
    // Настройки SPI    
    SPI_DDR = (1 << MOSI_P)|(1 << SCK_P)|(1 << SS_P);
    SPI_PORT = (1 << SS_P); // Чипселект в еденице - приемник неактивен
    SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR1); // F_CPU/128
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    uint8_t buffer[2] = {0xAA, 0xBB}; // Значения от балды...
    
    // Пишем два регистра и buffer, начиная с решистра №1
    adc_write_registers(1, 2, buffer); 
    
    // Читаем 2 регситра в buffer, начиная с регистра №5
    adc_read_registers(5,2,buffer);    
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Люди подскажите что за ерунда !

#define SPI_PORT PORTB

#define SPI_DDR DDRB

 

#define MOSI_P PB3

#define MISO_P PB4

#define SCK_P PB5

#define SS_P PB2

 

#define SELECT() SPI_PORT &= ~(1 << SS_P)

#define DESELECT() SPI_PORT |= (1 << SS_P)

 

void SPI_init(void) {

 

SPI_DDR = (1 << MOSI_P)|(1 << SCK_P)|(1 << SS_P);

SPI_PORT = (1 << SS_P); // Чипселект в еденице

SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR1)|(1 << SPR0);// делим 7.3728/128

}

 

void RREG (void) {

if (SPDR) {};//на всякий случай сбрасываем SPIF

SELECT();// выбор чипа

SPDR = 0x1B;//команда для чтения регистра 0x0B

while(!(SPSR & (1 << SPIF)));

SPDR = 0x00;// читаем колличество регистров 1 + 0x00

while(!(SPSR & (1 << SPIF)));

_delay_us(50);// задержка по даташиту 50 Tosc (2.4576)

SPDR = 0xAA;//записываем что бы прочитать

while(!(SPSR & (1 << SPIF)));

SPI_buf = SPDR;// читаем содержимое регистра 0x0B

USART_Transmit(SPI_buf); посылаем значение по RS 232

DESELECT(); //выключаем чим ведомый

}

 

После этого принимаю постоянно разные значения

UART налажен нармально - до этого тестился.

CPU_cloc 7.3728

baund rate 9600

UBBR 47

 

Посоветуйте что нить, а то уже сил нет !

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

После этого принимаю постоянно разные значения

UART налажен нармально - до этого тестился.

CPU_cloc 7.3728

baund rate 9600

UBBR 47

 

Посоветуйте что нить, а то уже сил нет !

Во-первых, научитесь при создании сообщения вставлять исходный текст с помощью соответствующей кнопки (#) - она ведь для этого и создана.

Во-вторых, приведите полный исходник. В данном случае не понятно, что делается в main().

В-третьих, убедитесь сами (а не предлагайте другим считать делители) раз и навсегда, что данные по UART'у передаются корректно: киньте посылку из разных байт и проверьте её приём на другом конце (можете дополнительно сделать это в цикле).

Ну и в-четвёртых, а какие собственно разные данные приходят от ADS1242?

 

P.S. Для корректности ставьте DESELECT по окончании работы с SPI.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выкладываю полный текст программы. После прихода комманды 0x32 и еще чего нибудь

нужно выполнить запись и чтение из АЦП. Подозрение что не работает задержка.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>



#define UBRRVAL 47

#define SPI_PORT PORTB
#define SPI_DDR DDRB

#define MOSI_P PB3 
#define MISO_P PB4
#define SCK_P PB5
#define SS_P PB2

#define SELECT() SPI_PORT &= ~(1 << SS_P)
#define DESELECT() SPI_PORT |= (1 << SS_P)

unsigned char command,statbuf,buf;


[code]void USART_init(void) {
    //Set baud rate



    UBRRL=UBRRVAL;            //low byte
    UBRRH=(UBRRVAL>>8);    //high byte
    //Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size
    UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);    
    //Enable Transmitter and Receiver and Interrupt on receive complete
    UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
}
void USART_Transmit(unsigned char data) {

    while ( !( UCSRA & (1<<UDRE)) ) {};
    UDR = data;
}

void SPI_init(void) {

    SPI_DDR = (1 << MOSI_P)|(1 << SCK_P)|(1 << SS_P);
    SPI_PORT = (1 << SS_P); // Чипселект в еденице - приемник неактивен
    SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR1)|(1 << SPR0); // F_CPU/128
    
}
unsigned char spi_shift_byte(unsigned char data) {
    
    SPDR = data;
    while(!(SPSR & (1 << SPIF)));    
    return SPDR;
}

unsigned char RREG(unsigned char start_address) {
    unsigned char buffer;
    SELECT();
    spi_shift_byte(0x10 | (start_address)); // 0001 rrrr
    spi_shift_byte(0x01); // xxxx nnnn, почему "минус 1" - написано в документации
    _delay_loop_2(250);
    buffer = spi_shift_byte(0xAA); // Читаем count регистров в массив buffer
    DESELECT();
    return buffer;
}

void WREG(unsigned char address, unsigned char value) {
    SELECT();
    spi_shift_byte(0x50 | (address)); // 0101 rrrr
    spi_shift_byte(0x00); // xxxx nnn, почему "минус 1" - написано в документации
    spi_shift_byte(value); // Передаем count значений из массива buffer
    DESELECT();
}

ISR (USART_RXC_vect) {
    
    while ( !(UCSRA & (1<<RXC)) );
    buf=UDR;
    statbuf=0x01;
}

void processing (void) {

    unsigned char SPI_buf;
    
    if ((statbuf==0x01) && (command==0x00)) {
            command=buf;
            buf=0x00;
            statbuf=0x00;
    }
    if  (command!=0x00) {
        switch (command) {
                case 0x31: {
                            USART_Transmit(0x01);
                            command=0x00;
                            break;    
                }
                case 0x32: {
                            if (statbuf==0x01) {
                                                USART_Transmit(0x02);
                                                
                                                SELECT();
                                                
                                                SPDR = 0x51;
                                                while(!(SPSR & (1 << SPIF)));
                                                SPDR = 0x01;
                                                while(!(SPSR & (1 << SPIF)));    
                                                SPDR = 0x05;
                                                while(!(SPSR & (1 << SPIF)));    
                                                SPDR = 0x07;
                                                while(!(SPSR & (1 << SPIF)));
                                                
                                                DESELECT();
                                                
                                                _delay_ms(10000);
                                                
                                                SELECT();
                                                
                                                SPDR = 0x11;
                                                while(!(SPSR & (1 << SPIF)));
                                                SPDR = 0x01;
                                                while(!(SPSR & (1 << SPIF)));
                                                _delay_ms(25);
                                                SPDR = 0xAB;
                                                while(!(SPSR & (1 << SPIF)));    
                                                SPI_buf=SPDR;
                                                USART_Transmit(SPI_buf);
                                                SPDR = 0xAC;
                                                while(!(SPSR & (1 << SPIF)));
                                                SPI_buf=SPDR;
                                                USART_Transmit(SPI_buf);
                                                
                                                DESELECT();
                                                
                                                    buf=0x00;
                                                    statbuf=0x00;
                                                    command=0x00;
                                                }
                            break;                    
                }
                
                default: {
                           command=0x00;
                           break;
                          }
        }                  
    
    }
}


int main (void) {

    USART_init();
    SPI_init();
    sei();
    
    while (1) {
        processing ();
    }
}[/code]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Выкладываю полный текст программы. После прихода комманды 0x32 и еще чего нибудь

нужно выполнить запись и чтение из АЦП. Подозрение что не работает задержка.

Кстати, очень может быть - у меня вечно с задержкой _delay_us/_delay_ms были разные проблемы. Лучше пользоваться _delay_loop_2 и вручную рассчитывать задержку. Скажите, какая у вас частота кварца контроллера и кварца ацп?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, очень может быть - у меня вечно с задержкой _delay_us/_delay_ms были разные проблемы. Лучше пользоваться _delay_loop_2 и вручную рассчитывать задержку.

 

Если у Вас были проблеммы с , то это не причина рекомендовать людям ими не пользоваться.

 

2 URANst:

 

1. Совпадат ли значения макроса F_CPU в makefile с реальной частотой контроллера?

 

2. Какой уровень оптимизации вы используете. Для корректного использования макросов _delay_us/_delay_ms должна быть не менее -01. (Перед включением оптимизации не забудте что в стандарте языка С есть слово 'volatile').

 

3. В описании функци _delay_ms обратите внимание на предложение:

The maximal possible delay is 262.14 ms / F_CPU in MHz.

 

Анатолий.

Изменено пользователем aesok

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

исползую ADS1243 ( 2,43MHz) с Mega16 ( 4,0MHz ).

режим SPI : SPCR = 0x55; ( перечитаите в зависимости частоты atmega) SPSR=0;.

я тоже немного мучился с SPI перед тем как нормально работать стал.

 

так должно работать, но задержки перечитаите в зависимости частоты atmega.

 

PORTB&=(~(1<<2));//выбор чипа SS=0;

SPI_Transmit(0x10);//читать регистр с номером 0x00

delay !!! a = 6; while (a--); // @ 4MHz

SPI_Transmit(0x01);// читать 2 регистра начиная с первого

delay !!! a= 60 ; While (a--); // @4MHz

SPI_Transmit(0);

delay a =6; while (a--) // @4MHz

PORTB|=(1<<2);//SS выставляю в 1 для сброса

USART_Transmit(SPDR);//пытаюсь прочитать присланные данные

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Уважаемый proba, что вы имели ввиду под

 

delay !!! a = 6; while (a--); // @ 4MHz

delay !!! a= 60; While (a--); // @4MHz

 

Я так понимаю что

a = 6

и

a= 60

- это задержка в периодах, тока подскажите

в периодах чего ? тактовой ATmega8 (7.3728 MHz) или ADS1242 (2.4576 MHz) или частоты SPI (7.3728 MHz/128).

proba может вы мне вышлите какую нить вашу схемку с ADS1242 и файл прошивки (.с) (очень интересно посмотреть) mail:[email protected]

А зачем задержка

delay !!! a = 6; while (a--); // @ 4MHz

, в даташите вроде ненаписано что

такую нада использовать.

 

 

Подскажите как описать задержку.

Я делаю так:

#include <avr/delay.h> или #include <util/delay.h>
_delay_loop_2(100) ? - 100 в каких единицах ?
_delay_us(50);

Похоже что не работает.

 

aesok !

 

1. Совпадат ли значения макроса F_CPU в makefile с реальной частотой контроллера?

да

 

2. Какой уровень оптимизации вы используете.

s

 

3. В описании функци _delay_ms обратите внимание на предложение:
The maximal possible delay is 262.14 ms / F_CPU in MHz.

то есть у меня макс 262,14/7,3728=35 ms, а если мне нужна задержка в 1 сек так что цикл лепить.

Как делаете вы задержки.

 

Извините за ламерские вопросы с WinAVR тока начал работать, сразу понравильсь а ща вот так :))

И еще подскажите какой WinAVR вы пользуетесь, и где ее можно скачать ? мож у меня версия кривая.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#include <avr/delay.h> или #include <util/delay.h>
_delay_loop_2(100) ? - 100 в каких единицах ?

в циклах контроллера.

 

3. В описании функци _delay_ms обратите внимание на предложение:
The maximal possible delay is 262.14 ms / F_CPU in MHz.

то есть у меня макс 262,14/7,3728=35 ms, а если мне нужна задержка в 1 сек так что цикл лепить.

Как делаете вы задержки.

 

Если у вас старая версия WinAVR, то да лепить циклы, или дополнительную функцию задержки. Если WinAVR 20071221 то возможно нет, недавно меняли макрос _delay_ms, и возможно он сам вставит цикл. Посмотрите описание или код _delay_ms в файле util/delay.h

И еще подскажите какой WinAVR вы пользуетесь, и где ее можно скачать ? мож у меня версия кривая.

WinAVR

 

Анатолий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

переписал в более пoнятныи формат.

в даташите там многого нет либо трудно понимат.

но без этих маленких задержек не работал.

в вашем случае вместо 6 > 12 , 60>110.

 

{

unsigned char a;

PORTB&=(~(1<<2));//выбор чипа SS=0;

SPI_Transmit(0x10);//читать регистр с номером 0x00

a = 6;

while (a--); // delay @ 4MHz

SPI_Transmit(0x01);// читать 2 регистра начиная с первого

a= 60 ;

While (a--); // delay @4MHz

SPI_Transmit(0);

a =6;

while (a--); // delay @4MHz

PORTB|=(1<<2);//SS выставляю в 1 для сброса

USART_Transmit(SPDR);//пытаюсь прочитать присланные данные

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...