URAN 0 21 января, 2008 Опубликовано 21 января, 2008 (изменено) · Жалоба Пытаюсь наладить связь 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 Изменено 21 января, 2008 пользователем URANst Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Master 0 21 января, 2008 Опубликовано 21 января, 2008 · Жалоба ... 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); //Посылаем данные из второго регистра Удачи! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
URAN 0 21 января, 2008 Опубликовано 21 января, 2008 · Жалоба 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. Что за ерунда кто скажет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aesthete Animus 0 21 января, 2008 Опубликовано 21 января, 2008 · Жалоба 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); // Младший байт } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
URAN 0 21 января, 2008 Опубликовано 21 января, 2008 · Жалоба До чтения данных оцифровки я еще не дошел (комманда 0x01 по моему она используется без байта параметров). Я хотел пока прочитать настройки АЦП (регистры SETUP и т.д.) вот сдесь используются команды по 2 байта. Так вот с этим непонятки. В даташите в Data Transfer Sequence еще стоит задержка с которой тож не совсем ясно. С SPI работаю первый раз, так что кто чем может, кто работал уже подскажите как ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aesthete Animus 0 21 января, 2008 Опубликовано 21 января, 2008 · Жалоба 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); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
URAN 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба Люди подскажите что за ерунда ! #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 Посоветуйте что нить, а то уже сил нет ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Master 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба ... После этого принимаю постоянно разные значения UART налажен нармально - до этого тестился. CPU_cloc 7.3728 baund rate 9600 UBBR 47 Посоветуйте что нить, а то уже сил нет ! Во-первых, научитесь при создании сообщения вставлять исходный текст с помощью соответствующей кнопки (#) - она ведь для этого и создана. Во-вторых, приведите полный исходник. В данном случае не понятно, что делается в main(). В-третьих, убедитесь сами (а не предлагайте другим считать делители) раз и навсегда, что данные по UART'у передаются корректно: киньте посылку из разных байт и проверьте её приём на другом конце (можете дополнительно сделать это в цикле). Ну и в-четвёртых, а какие собственно разные данные приходят от ADS1242? P.S. Для корректности ставьте DESELECT по окончании работы с SPI. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
URAN 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба Выкладываю полный текст программы. После прихода комманды 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] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aesthete Animus 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба Выкладываю полный текст программы. После прихода комманды 0x32 и еще чего нибудь нужно выполнить запись и чтение из АЦП. Подозрение что не работает задержка. Кстати, очень может быть - у меня вечно с задержкой _delay_us/_delay_ms были разные проблемы. Лучше пользоваться _delay_loop_2 и вручную рассчитывать задержку. Скажите, какая у вас частота кварца контроллера и кварца ацп? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 22 января, 2008 Опубликовано 22 января, 2008 (изменено) · Жалоба Кстати, очень может быть - у меня вечно с задержкой _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. Анатолий. Изменено 22 января, 2008 пользователем aesok Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
proba 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба исползую 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);//пытаюсь прочитать присланные данные Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
URAN 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба Уважаемый 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 вы пользуетесь, и где ее можно скачать ? мож у меня версия кривая. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба #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 Анатолий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
proba 0 22 января, 2008 Опубликовано 22 января, 2008 · Жалоба переписал в более п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);//пытаюсь прочитать присланные данные } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться