B_Sergey_N 0 21 августа, 2008 Опубликовано 21 августа, 2008 · Жалоба Всем привет. Подключил АЦП 12 битовый к ATmega32 по SPI. Но никак не могу понять как принимать данные с АЦП. У SPI есть 8-разрядный сдвиговый регистр, мне же надо принять сразу 12 (точнее 16, но первые 4 бита нули). Каким образом? Как двигать и записывать эти биты. Прикрепляю datasheet АЦП, может кто захочет взглянуть. Инициализация SPI вроде правильна: // Установить PB5(MOSI), PB7(SCK) как выходы DDRB = (1<<PB5)|(1<<PB7)|(1<<PB4); PORTB = 0xFF; DDRC = (1 << PC0); // PС0(/СS) выход PORTC |= (1 << PC0); // Включаю SPI в режиме мастер с SCK = CK/4 = 4МГц SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL); SPSR = (1<<SPI2X); // Удваиваю скорость до 8МГц После этого написал так, светодиоды использ. для проверки. while(1) { PORTC &= ~(1 << 0); // Включаю АЦП _delay_ms(1); //while(PINB6 == 0); while (!(SPSR & (1<<SPIF))); PORTC |= (1 << 0); // Отключил АЦП if (SPDR <= 256) { // Мигаю светодиодом _delay_ms(50); PORTA |= (1 << 1); _delay_ms(500); PORTA &= ~(1 << 1); } else { // Подмигиваю _delay_ms(50); PORTA |= (1 << 2); _delay_ms(50); PORTA &= ~(1 << 2); } } Знаю, что не правильно, поэтому спрашиваю. Буду очень признателен за помощь, а то уже не знаю сколько перечитал всего, так и не разобрался. Было бы совсем не плохо, если бы выложили код. А и еще, программатор подключен тоже по SPI. Могут ли возникнуть с этим проблемы? На всякий случай отрубаю его от схемы перед подачей сигнала на АЦП. Спасибо, Сергей. ___AD7476_7477_7478.pdf Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aesok 0 21 августа, 2008 Опубликовано 21 августа, 2008 · Жалоба Знаю, что не правильно, поэтому спрашиваю. Буду очень признателен за помощь, а то уже не знаю сколько перечитал всего, так и не разобрался. Было бы совсем не плохо, если бы выложили код. Порочтите "AVR151: Setup and use of the SPI" http://www.atmel.com/dyn/resources/prod_do...nts/doc2585.pdf И код: http://www.atmel.com/dyn/resources/prod_documents/AVR151.zip Анатолий. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 22 августа, 2008 Опубликовано 22 августа, 2008 · Жалоба попробуйте, для начала, поуправлять АЦП "в ручную" - подёргать битики SPI программно. Вот пара моих кусочков кода для разных АЦП - по аналогии попробуйте... Для ad7276: unsigned long BoardReadADC() { unsigned long val = 0; prog_select(targetadc1, 1); SCLK_SET(); SCLK_CLR(); for (int i = 0; i < 12; ++ i) { SCLK_SET(); SCLK_CLR(); unsigned v = (lpt_readb_status() & 0x08) == 0; val = (val << 1) | v; } prog_select(targetadc1, 0); return val; } Для ad7810 void sclk_pulse(void) { SCLK_CLR(); SCLK_SET(); } // ADC conversion start signal void convstart_pulse(void) { prog_select(targetadc1, 1); prog_select(targetadc1, 0); } unsigned ad7810_read( void //unsigned char target /* addressing to chip */ ) { unsigned val = 0; // ADC conversion start signal convstart_pulse(); // for (int i = 0; i < 10; ++ i) { unsigned v; sclk_pulse(); // //v = (PIND & 0x08) != 0; v = (lpt_readb_status() & 0x08) == 0; val = (val * 2) | v; } // sclk_pulse(); sclk_pulse(); return val; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 22 августа, 2008 Опубликовано 22 августа, 2008 · Жалоба if (SPDR <= 256) Это условие никогда не выполнится, потому что SPDR 8и разрядный и максимальное его значение 255 или 0xFF. Вам надо Во первых сперва записать в SPDR любое число(обычно 0xff) чтобы SPI начал передавать клоки подчиненному, после передачи в регистре SPDR вы получите то что вам передал подчиненный, затем содержимое SPDR надо где то сохранить, и повторить передачу(записью в SPDR=255), чтобы получить второй байт от подчиненного, вот теперь вы имеете 2 байта от АЦП(тот что вы сохранили ранее и тот что лежит в SPDR теперь. Примерно так: short adc_in; SPDR = 255; while (!(SPSR & (1<<SPIF))); adc_in = (short)SPDR << 8; SPDR = 255; while (!(SPSR & (1<<SPIF))); adc_in |= SPDR; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
B_Sergey_N 0 23 августа, 2008 Опубликовано 23 августа, 2008 · Жалоба Заработало!!! Всем спасибо, особенно GDI. Но я так и не могу понять, зачем перед тем как что-то принять, надо каждый раз чем-то забивать SPDR? Неужели только из-за подачи клоков? А я не могу разве просто дергать ногой SCLK и следить за спадом и поднятием фронтов? А и еще, читал что задержки всякие надо делать, между клоками и еще чем-то, хотя они настолько малы, там всего ns какие-то. Вроде без задержек всяких работает. Спасибо, Сергей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 23 августа, 2008 Опубликовано 23 августа, 2008 · Жалоба Примерно так: //... adc_in = (short)SPDR << 8; //... adc_in |= SPDR; А почему бы не вот так? //... *(((unsigned char *) &adc_in) + 1) = SPDR; //... *((unsigned char *) &adc_in) = SPDR; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 24 августа, 2008 Опубликовано 24 августа, 2008 · Жалоба А почему бы не вот так? //... *(((unsigned char *) &adc_in) + 1) = SPDR; //... *((unsigned char *) &adc_in) = SPDR; Потому что контроллеры и процессоры бывают как Little-Endian, так и Big-Endian, а Ваш вариант этого совсем не учитывает - следовательно это unsafe:). Посмотрите для самообразования: Порядок байтов — Википедия Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 24 августа, 2008 Опубликовано 24 августа, 2008 · Жалоба Потому что контроллеры и процессоры бывают как Little-Endian, так и Big-Endian, а Ваш вариант этого совсем не учитывает... Ну само собой! При попытке чего-то оптимизировать теряем в универсальности.. :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 25 августа, 2008 Опубликовано 25 августа, 2008 · Жалоба Но я так и не могу понять, зачем перед тем как что-то принять, надо каждый раз чем-то забивать SPDR? Неужели только из-за подачи клоков? А я не могу разве просто дергать ногой SCLK и следить за спадом и поднятием фронтов? МК у вас выступает как мастер, значит именно он должен генерировать клоки, а чтобы он начал это делать на до что то поместить в регистр данных SPI, т.е. в SPDR. Клоки при этом генерируются аппаратно и все времянки определяются настройками SPI. А если вы сами будете дергать ногой CLK то это будет уже программный SPI и вам самому надо будет организовывать считывание битов с MISO и размещение их в какой то переменной, что работает намного медленнее аппаратной реализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 25 августа, 2008 Опубликовано 25 августа, 2008 · Жалоба Ну само собой! При попытке чего-то оптимизировать теряем в универсальности.. :( Что называется, почувствуйте разницу. Я не думал что будет ТАКОЕ: gcc 4.1.2 Os volatile unsigned short a; volatile unsigned short b; volatile unsigned short с; a = (unsigned short)SPDR<<8; // Hi b6: 8f b1 in r24, 0x0f; 15 b8: 99 27 eor r25, r25 ba: 98 2f mov r25, r24 bc: 88 27 eor r24, r24 be: 9e 83 std Y+6, r25; 0x06 c0: 8d 83 std Y+5, r24; 0x05 a |= SPDR; // Low c2: 2d 81 ldd r18, Y+5; 0x05 c4: 3e 81 ldd r19, Y+6; 0x06 c6: 8f b1 in r24, 0x0f; 15 c8: 99 27 eor r25, r25 ca: 28 2b or r18, r24 cc: 39 2b or r19, r25 ce: 3e 83 std Y+6, r19; 0x06 d0: 2d 83 std Y+5, r18; 0x05 *((unsigned char*)&b + 1) = SPDR; // Hi d2: 8f b1 in r24, 0x0f; 15 d4: 8a 83 std Y+2, r24; 0x02 *((unsigned char*)&b + 0) = SPDR; // Low d6: 8f b1 in r24, 0x0f; 15 d8: 89 83 std Y+1, r24; 0x01 c = a+b; da: 8d 81 ldd r24, Y+5; 0x05 dc: 9e 81 ldd r25, Y+6; 0x06 de: 29 81 ldd r18, Y+1; 0x01 e0: 3a 81 ldd r19, Y+2; 0x02 e2: 82 0f add r24, r18 e4: 93 1f adc r25, r19 e6: 9c 83 std Y+4, r25; 0x04 e8: 8b 83 std Y+3, r24; 0x03 Так будет лучше, но.... gcc 4.3.0 Os a = (unsigned short)SPDR<<8; // Hi b0: 2f b1 in r18, 0x0f; 15 b2: 92 2f mov r25, r18 b4: 80 e0 ldi r24, 0x00; 0 b6: 9a 83 std Y+2, r25; 0x02 b8: 89 83 std Y+1, r24; 0x01 a |= SPDR; // Low ba: 29 81 ldd r18, Y+1; 0x01 bc: 3a 81 ldd r19, Y+2; 0x02 be: 8f b1 in r24, 0x0f; 15 c0: 90 e0 ldi r25, 0x00; 0 c2: 82 2b or r24, r18 c4: 93 2b or r25, r19 c6: 9a 83 std Y+2, r25; 0x02 c8: 89 83 std Y+1, r24; 0x01 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
B_Sergey_N 0 25 августа, 2008 Опубликовано 25 августа, 2008 · Жалоба МК у вас выступает как мастер, значит именно он должен генерировать клоки, а чтобы он начал это делать на до что то поместить в регистр данных SPI, т.е. в SPDR. Клоки при этом генерируются аппаратно и все времянки определяются настройками SPI. А если вы сами будете дергать ногой CLK то это будет уже программный SPI и вам самому надо будет организовывать считывание битов с MISO и размещение их в какой то переменной, что работает намного медленнее аппаратной реализации. Аа..Все, вот теперь понял, Огромное спасибо! С Уважением, Сергей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
NullPointer 0 25 августа, 2008 Опубликовано 25 августа, 2008 · Жалоба Я не думал что будет ТАКОЕ... Вот и я как-то посмотрел какое там чудовисче генерится, и решил что как-то не позволительно делать такое. Ну а об неуниверсальности должен помнить программер, иначе зачем он вообще нужен?.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
B_Sergey_N 0 31 августа, 2008 Опубликовано 31 августа, 2008 · Жалоба Хорошо, спасибо большое за подсказки. Возник теперь такой вопрос: Как передать 16-ти разрядное число по USARTу, можно так настроить USART, что бы он понимал что передается одно число 2-мя байтами? Это для того что бы на приемной стороне не надо было самому склеивать два полученных байта в одно число. По USARTу подключен Bluetooth к атмеге, передача происходит фактически по беспроводному COM порту на комп. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dmitry_volkov 0 31 августа, 2008 Опубликовано 31 августа, 2008 · Жалоба Понадобится самому организовывать протокол передачи данных (2 байта, цепочку байтов...), поскольку usart передает или получает за один кадр до 8 битов информации (без учеты старт-стоповых) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться