|
SPI и Atmega128A |
|
|
|
Dec 14 2011, 08:03
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
Проблема: не получается принять данные. В даташите есть функция настройки 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)));//ждем пока передача завершится }
|
|
|
|
|
Dec 15 2011, 07:29
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
А как мне быть если ответом будет слово?
|
|
|
|
|
Dec 15 2011, 07:43
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (arttab @ Dec 15 2011, 03:27)  есть такое. причем когда мастер только передает и входная линия физически отсутствует все равно надо читать из регистра ресивера. на меге8535 c этим столкнулся. Странно. На меге8 считываю только тогда, когда нужны принятые данные. И все работает. И с прерываниями, и без. Вроде бы дата рождения у них примерно одинаковая, откуда же такое отличие? QUOTE (ADEPTPS @ Dec 15 2011, 09:29)  А как мне быть если ответом будет слово? Принять два байта и склеить из них двухбайтовую переменную?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 15 2011, 07:52
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
судя по последней конструкции, один байт отдали - один приняли, а у меня один байт отдали - слово приняли
|
|
|
|
|
Dec 16 2011, 12:21
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 22-01-10
Из: Kiev
Пользователь №: 55 001

|
а у меня один байт отдали - слово приняли ---------------------------------------------------- SPI - синхронный интерфейс с линией СИНХРО. Данные (по ОПРЕДЕЛЕНИЮ!) передвигаются из/в обычные сдвиговые регистры. Значит надо передать поочередно два байта (один - пустой) и т.о. сформировать 8+8 синхроимпульсов, по которым с другой стороны вытолкнутся к вам 8 +8 бит. А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть!
|
|
|
|
|
Dec 23 2011, 10:45
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
Посмотрите кто-нибудь мой код, если не трудно, на мой взгляд проблема в настройке SPI: это подпрограмма для инициализации и считывания данных с АЦП AD7792. Помогите пожалуйста! CODE #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; } Цитата(usav @ Dec 16 2011, 16:21)  А вообще, прежде чем писать (и прогу и сюда) надо хотя бы картинки в DS посмотреть! Их я уже насмотрелся....
Сообщение отредактировал ADEPTPS - Dec 23 2011, 09:51
|
|
|
|
|
Dec 23 2011, 10:55
|
Частый гость
 
Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826

|
Цитата(ADEPTPS @ Dec 23 2011, 11:50)  Посмотрите кто-нибудь мой код То что я увидел - нужно обратить внимание на сигнал SS (слейв селект PB4) он переключает режим из мастера в слейв низким уровнем на пине, если настроен как вход, если не собираетесь переключаться, то он не должен быть входом (ниже я настроил его выходом), и для этого АЦП, если вы подключаете SCK без инвертирования я поменял фазу и полярность. Попробуйте скорректированное мной (правда смотрел по быстрому, мог ошибиться проверте по даташиту: CODE 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 файл с дефайнами (я думаю обязательно есть в для любой среды программирования)
|
|
|
|
|
Dec 23 2011, 11:04
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
Спасибо, сейчас попробую!
SPI завелся вроде, но на ЖКИ по прежнему 0...
|
|
|
|
|
Dec 23 2011, 11:16
|
Частый гость
 
Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826

|
Цитата(ADEPTPS @ Dec 23 2011, 13:04)  Спасибо, сейчас попробую!
SPI завелся вроде, но на ЖКИ по прежнему 0... Прошу прощения пошибся просто по тексту увидел Mega8535, а нада 128, тогда оставте это по старому, а остальное попробуйте CODE #define DD_SS 0 #define DD_MOSI 2 #define DD_MISO 3 #define DD_SCK 1
|
|
|
|
|
Dec 23 2011, 11:48
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
читается какая-то константа.... 12336 которая не зависит от входа на АЦП. но все равно большое спасибо! вот немного поменял, выход с АЦП FFFF Выкладываю обновленный код(без подпрограммы инициализации и вывода ЖКИ - он работает): Подпрограмма АЦП: CODE #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; }
Главная программа: CODE #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; }
}
|
|
|
|
|
Dec 23 2011, 11:59
|
Частый гость
 
Группа: Свой
Сообщений: 116
Регистрация: 2-03-07
Из: Украина
Пользователь №: 25 826

|
Давай попорядку, проверим связь и прочитаем статус регистр и сравним с 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);
|
|
|
|
|
Dec 23 2011, 12:09
|
Участник

Группа: Участник
Сообщений: 41
Регистрация: 5-05-09
Пользователь №: 48 683

|
у меня это получается _delay_ms(5000); = 500 мс
единички на месте)
а сори, многовато, микросекунды нужны тогда _delay_ms(5); так получается из-за того что тактовая частота не прописана (определено экспериментальным путем)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|