ADEPTPS 0 14 декабря, 2011 Опубликовано 14 декабря, 2011 · Жалоба Проблема: не получается принять данные. В даташите есть функция настройки SPI на мастер: // в ней есль только отправка данных, пытаюсь принимать данные с SPDR, но считываю лишь то что отсылаю! void SPI_MasterInit() { DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);//настраиваем на выход SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//вкл SPI, ведущий, частота fck/16 } //функция передачи байта void SPI_MasterTransmit(char cData) { SPDR = cData;//начинаем передачу while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 14 декабря, 2011 Опубликовано 14 декабря, 2011 (изменено) · Жалоба SPI отсылает и принимает ОДНОВРЕМЕННО. Т.е. чтобы что-то принять, мастер должен что-то отослать. //функция передачи байта char SPI_MasterTransmit(char cData) { SPDR = cData;//начинаем передачу while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится return SPDR; } Вызов: receivedByte = SPI_MasterTransmit(0xFF); Изменено 14 декабря, 2011 пользователем hd44780 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arttab 0 15 декабря, 2011 Опубликовано 15 декабря, 2011 · Жалоба есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 15 декабря, 2011 Опубликовано 15 декабря, 2011 · Жалоба А как мне быть если ответом будет слово? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 15 декабря, 2011 Опубликовано 15 декабря, 2011 · Жалоба есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся.Странно. На меге8 считываю только тогда, когда нужны принятые данные. И все работает. И с прерываниями, и без. Вроде бы дата рождения у них примерно одинаковая, откуда же такое отличие? А как мне быть если ответом будет слово?Принять два байта и склеить из них двухбайтовую переменную? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 15 декабря, 2011 Опубликовано 15 декабря, 2011 · Жалоба судя по последней конструкции, один байт отдали - один приняли, а у меня один байт отдали - слово приняли Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 15 декабря, 2011 Опубликовано 15 декабря, 2011 (изменено) · Жалоба SPI всегда и везде принимает только байты. По крайней мере, в AVR-ах. Если надо слово, то: word rWord = SPI_MasterTransmit(0xFF); /// Старший байт rWord <<= 8; rWord |= SPI_MasterTransmit(0xFF); // Младший Если наоборот - сами напишете. Изменено 15 декабря, 2011 пользователем hd44780 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
usav 0 16 декабря, 2011 Опубликовано 16 декабря, 2011 · Жалоба а у меня один байт отдали - слово приняли ---------------------------------------------------- SPI - синхронный интерфейс с линией СИНХРО. Данные (по ОПРЕДЕЛЕНИЮ!) передвигаются из/в обычные сдвиговые регистры. Значит надо передать поочередно два байта (один - пустой) и т.о. сформировать 8+8 синхроимпульсов, по которым с другой стороны вытолкнутся к вам 8 +8 бит. А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 23 декабря, 2011 Опубликовано 23 декабря, 2011 (изменено) · Жалоба Посмотрите кто-нибудь мой код, если не трудно, на мой взгляд проблема в настройке SPI: это подпрограмма для инициализации и считывания данных с АЦП AD7792. Помогите пожалуйста! #include <avr/io.h> #include <avr/delay.h> #include <string.h> #include <avr/sfr_defs.h> void spi_in(void) { #define DDR_SPI DDRB #define DD_SS 0 #define DD_MOSI 2 #define DD_MISO 3 #define DD_SCK 1 #define SPE 6 #define MSTR 4 #define SPR0 0 #define SPIF 7 PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO); DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_MISO); DDR_SPI &= ~(1<<DD_MISO); //SPSR |= (1<<SPI2X); SPCR |= (1<<SPE)|(1<<MSTR); } uint8_t spi_rw(uint8_t Data) { SPDR = Data;//начинаем передачу while((SPSR & (1<<SPIF)) == 0);//ждем пока передача завершится Data = SPDR; return Data; } //Инициализация АЦП void ad7793_init(void) { int8_t i; spi_in(); for (i = 0; i < 4;i++) spi_rw(0xFF); /* настройка АЦП */ spi_rw(0b00010000); spi_rw(0b00010000); spi_rw(0b00000000); spi_rw(0b00101000); spi_rw(0b00000000); /* Калибровка */ spi_rw(0b00001000); spi_rw(0b11000000); spi_rw(0b10000001); _delay_ms(10); loop_until_bit_is_clear(PORTB,DD_MISO); spi_rw(0b00001000); spi_rw(0b10100000); spi_rw(0b10000001); _delay_ms(10); loop_until_bit_is_clear(PORTB,DD_MISO); } //Установка режима работы void ad7793_mode_set(unsigned char mode) { spi_rw(0b00001000); if (mode == 0) { spi_rw(0b00000000); } else spi_rw(0b00100000); spi_rw(0b10000001); } uint16_t ad7793_data_get(void) { uint16_t t = 0; loop_until_bit_is_clear(PORTB,DD_MISO); spi_rw(0x58); *((uint8_t *)(&t) + 1) = spi_rw(0xFF); *((uint8_t *)(&t)) = spi_rw(0xFF); return t; } А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть! Их я уже насмотрелся.... Изменено 23 декабря, 2011 пользователем ADEPTPS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tolyaha 1 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба Посмотрите кто-нибудь мой код То что я увидел - нужно обратить внимание на сигнал SS (слейв селект PB4) он переключает режим из мастера в слейв низким уровнем на пине, если настроен как вход, если не собираетесь переключаться, то он не должен быть входом (ниже я настроил его выходом), и для этого АЦП, если вы подключаете SCK без инвертирования я поменял фазу и полярность. Попробуйте скорректированное мной (правда смотрел по быстрому, мог ошибиться проверте по даташиту: void spi_in(void) { #define DDR_SPI DDRB #define DD_SS 0 #define DD_MOSI 2 #define DD_MISO 3 #define DD_SCK 1 #define CPOL 3 #define CPHA 2 #define SPE 6 #define MSTR 4 #define SPR0 0 #define SPIF 7 PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO); DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS); DDR_SPI &= ~(1<<DD_MISO); //SPSR |= (1<<SPI2X); SPCR |= (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA); } P.S. А вобще в аврстудии есть инклюдник, описывающий все биты (m8535def.inc) или еще где можно найти и h файл с дефайнами (я думаю обязательно есть в для любой среды программирования) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба Спасибо, сейчас попробую! SPI завелся вроде, но на ЖКИ по прежнему 0... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tolyaha 1 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба Спасибо, сейчас попробую! SPI завелся вроде, но на ЖКИ по прежнему 0... Прошу прощения пошибся просто по тексту увидел Mega8535, а нада 128, тогда оставте это по старому, а остальное попробуйте #define DD_SS 0 #define DD_MOSI 2 #define DD_MISO 3 #define DD_SCK 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба читается какая-то константа.... 12336 которая не зависит от входа на АЦП. но все равно большое спасибо! вот немного поменял, выход с АЦП FFFF Выкладываю обновленный код(без подпрограммы инициализации и вывода ЖКИ - он работает): Подпрограмма АЦП: #include <avr/io.h> #include <avr/delay.h> #include <string.h> #include <avr/sfr_defs.h> void spi_in(void) { #define DDR_SPI DDRB #define CPOL 3 #define CPHA 2 #define SPE 6 #define MSTR 4 #define SPR0 0 #define SPIF 7 #define DD_SS 0 #define DD_MOSI 2 #define DD_MISO 3 #define DD_SCK 1 PORTB |= (1<<DD_SCK)|(1<<DD_MOSI)|(1<<DD_MISO); DDR_SPI |= (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS); DDR_SPI &= ~(1<<DD_MISO); //SPSR |= (1<<SPI2X); SPCR |= (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA); } uint8_t spi_rw(uint8_t Data) { SPDR = Data;//начинаем передачу while((SPSR & (1<<SPIF)) == 0);//ждем пока передача завершится Data = SPDR; return Data; } //Инициализация АЦП void ad7793_init(void) { int8_t i; spi_in(); for (i = 0; i < 4;i++) spi_rw(0xFF); /* настройка АЦП */ spi_rw(0b00010000); spi_rw(0b00010000); spi_rw(0b00000000); spi_rw(0b00101000); spi_rw(0b00000000); /* Калибровка */ spi_rw(0b00001000); spi_rw(0b11000000); spi_rw(0b10000001); _delay_ms(10); loop_until_bit_is_clear(DDR_SPI,DD_MISO); spi_rw(0b00001000); spi_rw(0b10100000); spi_rw(0b10000001); _delay_ms(10); loop_until_bit_is_clear(DDR_SPI,DD_MISO); } //Установка режима работы void ad7793_mode_set(unsigned char mode) { spi_rw(0b00001000); if (mode == 0) { spi_rw(0b00000000); } else spi_rw(0b00100000); spi_rw(0b10000001); } uint16_t t; uint16_t ad7793_data_get(void) { t = 0; loop_until_bit_is_clear(DDR_SPI,DD_MISO); spi_rw(0x58); t = (uint16_t)(spi_rw(0xFF) << 8); t |= spi_rw(0xFF); return t; } Главная программа: #include <avr/io.h> #include <avr/delay.h> #include "lcd.h" #include <stdio.h> #include "adc2.c" void main(void) { char text[6]; unsigned int n=0; double adc; lcd_init(); lcd_write("Autorising..."); ad7793_init(); DDRD = (1 << 4); ad7793_mode_set(0); seconds(1); lcd_init(); lcd_write("Autorising..."); seconds(1); while (1) { adc = ad7793_data_get(); seconds(1); dtostrf(adc,6,0,text); lcd_send(COMMAND, LCD_CLEAR); DDRD = (1 << 4); lcd_write(text); DDRD = 0x00; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tolyaha 1 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба Давай попорядку, проверим связь и прочитаем статус регистр и сравним с Power-On/Reset = 0x80 (AD7792)/0x88 (AD7793) И просле сброса четырех 0xFF нада выдержать паузу необходимую для сброса 500мкс for (i = 0; i < 4;i++) spi_rw(0xFF); _delay_ms(1); /* настройка АЦП */ spi_rw(0b00010000); spi_rw(0b00010000); spi_rw(0b00000000); spi_rw(0b00101000); spi_rw(0b00000000); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ADEPTPS 0 23 декабря, 2011 Опубликовано 23 декабря, 2011 · Жалоба у меня это получается _delay_ms(5000); = 500 мс единички на месте) а сори, многовато, микросекунды нужны тогда _delay_ms(5); так получается из-за того что тактовая частота не прописана (определено экспериментальным путем) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться