Страница 1 из 1
ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Чт апр 05, 2012 16:43:09
Goldkiller
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Чт апр 05, 2012 17:29:14
ds1307
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Чт апр 05, 2012 20:48:14
Goldkiller
От этого соединения мне нужно что бы МК MASTER давал команды SLAVE.
Т.е. При замыкании кнопки на MASTERe, загорался LED на SLAVE.
Я просто еще новичок , не совсем понимаю как сделать передачу на SLAVE.
А затем на SLAVE ее принять.
Если вам не сложно, множите написать код ?
Вот сгенерированный код CV:
Код: Выделить всё
#include <mega8.h>
#include <alcd.h>
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data;
data=SPDR;
}
void main(void)
{
PORTB=0x00;
DDRB=0x2C;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
ACSR=0x80;
SFIOR=0x00;
SPCR=0xD0;
SPSR=0x00;
#asm
in r30,spsr
in r30,spdr
#endasm
lcd_init(16);
#asm("sei")
while (1){ }
}
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Пт апр 06, 2012 13:34:43
ds1307
Так сделать на слейве
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data;
data=SPDR;
// Place your code here
PORTD=data;
}
А так на мастере
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
// unsigned char data;
// data=SPDR;
// Place your code here
}
...
while (1){
когда произойдет что-то SPDR = 0bXXXXXXXX;
вместо X поставь 0 или 1
}
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Пт апр 06, 2012 14:29:47
s_black
Goldkiller писал(а): В инете все проверил, все статьи , форумы, но к сожалению не смог найти нужной информации.
Плохо искал.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Пт апр 06, 2012 22:31:12
Goldkiller
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Сб апр 07, 2012 00:18:49
Jack_A
Если для готового устройства ( флеш, таймкипер, термометр etc. ) - то в соответствии с ДШ на них. Если для самостоятельно программируемого устройства - в соответствии с выбранным протоколом в переданном пакете содержится адрес устройства. Все слейвы слушают линию, и тот, у которого его адрес совпадает с адресом в пакете, отвечает. Адреса у слейвов могут задаваться джамперами, могут быть прошиты ( нежелательно, трудно изменять ) или раздаваться динамически по включению мастера ( мне не нравится, ненадежно, imho ) .
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Сб апр 07, 2012 02:32:17
s_black
To Jack_A.
Гм.. Как бы Вам, коллега, сказать помягче, что Вы ошибаетесь

То, что Вы озвучили - это адресация для I2C. В протоколе SPI адресация устройства осуществляется подачей на SLAVE низкого уровня на вывод "выбор кристалла". Чаще всего - это вывод CS "Chip Select". В AVR, если он работает как SLAVE - это вывод SS.
To Goldkiller.
Насчёт Протеуса ничего не скажу - я в нём не работаю, предпочитаю отладку на железе. Насчёт адресации см. выше и помните, что, если выбрано более одного SLAVE, то они примут данные от MASTER, но вот, что MASTER примет у себя от нескольких SLAVE-ов - это ещё вопрос, т.к. выйдет коллизия с накладкой байтов друг на друга!
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Сб апр 07, 2012 08:17:00
Jack_A
Да, малость того... Повелся на название темы, не вникнув. С UARTом пробовал, фурычет. Выходы TxD слейвов объединял по И. Но надежнее - мультиплексировать опять же с выборкой слейва, как бы CS.
Впрочем, немного поизвращавшись над линией MISO, можно этот вариант замутить и для SPI. Но, как говорил Суворов, это уже будет через Альпы.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Вс апр 08, 2012 08:47:47
Goldkiller
s_black писал(а):
Насчёт адресации см. выше и помните, что, если выбрано более одного SLAVE, то они примут данные от MASTER, но вот, что MASTER примет у себя от нескольких SLAVE-ов - это ещё вопрос, т.к. выйдет коллизия с накладкой байтов друг на друга!
Передачу 2 сразу слейвам я не буду делать. Только по очередности.
Я хочу что бы на одном МК (Slave1) производился расчет АЦП. например 12v.
На другом МК(Slave2) производился расчет температуры. например 20 С.
Мастер посылал запрос сначала на Slave 1 - 'volt' и в ответ приходил ответ 12, затем посылал запрос на Слейв 2 и получил ответ 20. А затем мастер чтоб все вывел на экран.
Пока что получилось осуществить отправку к слейв байтов. Сейчас пытаюсь понять как отправить обратно ответ мастеру.
Может у вас есть готовый код двух стороннего обмена данных ?
Я на одном сайте нашел как они это делают , но там все на Асемблере, а я к сожалению плохо на Асемблее ориентируюсь. в Основном в Codevision .
http://avr.ru/ready/inter/spi/spi Множите помочь если вам не сложно. Просто я пишу диссертацию и это единственный форум в котором мне ответили, а до защиты диссертации остался месяц.
Еще вопрос: Можно ли на Слейве порт SS просто заземлить, а на Мастере SS не куда не подключать ?
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Вс апр 08, 2012 10:09:48
Goldkiller
Вроде бы получилось отправить мастером '0xFF' и слейвом отправить ответ '0x7F' , но в SPI-debugger вышли какие то строчки.
Можете расписать значения их ? Может это какие то ошибки при отправке ? вот скрин.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Вс апр 08, 2012 12:00:34
s_black
Goldkiller писал(а):
Пока что получилось осуществить отправку к слейв байтов. Сейчас пытаюсь понять как отправить обратно ответ мастеру.
Может у вас есть готовый код двух стороннего обмена данных ?
Вы не до конца поняли суть SPI интерфейса. В тот момент, когда идёт передача с мастера на слейв по линии MOSI - MOSI , В ЭТО ЖЕ ВРЕМЯ идёт обратная передача со слейва на мастер по линии MISO - MISO. И, после окончания передачи, в регистре данных мастера будет принятый байт от слейва. Вы же хотите реакции от слева на команду. Т.е. слейву нужно принять команду, допустим измерения напряжения, выполнить её (посчитайте, сколько времени займут эти процессы) и, после измерения напряжения, поместить значение напряжения в регистр данных SPI, чтобы потом передать его ПО ТАКТИРУЮЩИМ ИМПУЛЬСАМ от мастера. Таким образом мастер сначала должен выдать команду на измерение напряжения, выждать необходимое время, и снова запустить обмен, чтобы считать значение напряжения, которое слейв к этому моменту поместит в регистр данных SPI. Лучше задействовать дополнительную линию от слейва на мастер, чтобы от по ней информировать мастер об окончании измерения и готовности передать измеренное значение.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Вс апр 08, 2012 12:20:11
Jack_A
Goldkiller писал(а):Можно ли на Слейве порт SS просто заземлить, а на Мастере SS не куда не подключать ?
Категорически нельзя ! Я в одной из своих ранних работ так сделал - уж
ос ! Если в передаваемый поток случайно попадет лишний бит ( каким образом - помеха или что-нибудь - неважно ) - он там будет циркулировать до скончания века, сдвигая информацию на 1 бит. При выборке же через SS буфер очищается, и в описанном случае будет битым только один пакет.
Отправка и прием байта чрезвычайно просты. Вот из работающего проекта :
putSPI: out SPDR,r16
putin: sbis SPSR,SPIE
rjmp putin
ret
getSPI: ldi r16,0xF1
rcall putSPI
in r16,SPDR
ret
Оно на асме, но если надо перевеси на С - думаю, это не проблема. Да и вообще - отстой тот компилятор, что не допускает ассемблерные вставки. Всякие котавижны не люблю.
Причина граблей при обмене может быть в том, что для мастера и слейва назначены разные SPI MODE. Это легко ущучивается осциллом.
А еще не люблю диссертантов за то, что они заявление "Прошу повысить мне зарплату" пишут на 400стр. да еще и в твердом переплете
s_black Если там напряг с лишними линиями, можно, подав команду "Начать измерение" затем периодически подавать команду "Выдать данные", получая в ответ или статус "измерение не окончено", или готовые данные. Если, конечно, слейв тоже разрабатывается самостоятельно, и оба устройства можно "подружить" в смысле протокола обмена.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Вс апр 08, 2012 16:40:52
s_black
Jack_A писал(а):
s_black Если там напряг с лишними линиями, можно, подав команду "Начать измерение" затем периодически подавать команду "Выдать данные", получая в ответ или статус "измерение не окончено", или готовые данные. Если, конечно, слейв тоже разрабатывается самостоятельно, и оба устройства можно "подружить" в смысле протокола обмена.
Согласен . Кроме того желательно, чтобы слейв, перед загрузкой измеренного значения в регистр данных SPI, предварительно записал туда маркер "измерение завершено", чтобы мастер знал, что следующее считанное значение - результат. Я просто исходил из того что мастер и так загружен какими-то процессами, если по условию ТЗ напряжение и температуру измеряют внешние устройства.
Re: ATMEGA8: подключение к другому контролеру(SPI,I2C)
Добавлено: Пн апр 09, 2012 07:22:49
Goldkiller
s_black писал(а):
Согласен . Кроме того желательно, чтобы слейв, перед загрузкой измеренного значения в регистр данных SPI, предварительно записал туда маркер "измерение завершено", чтобы мастер знал, что следующее считанное значение - результат.
Спасибо вам большое, понял суть подключения SPI и отправку байтов.
Сделал все как вы написали, но почему то как и писал Jack_A, в конце отправленного байта добавляется лишний ноль. Т.е. отправляю 0b1110 а отправляется 0b11100 ? И как теперь с этим бороться ?
Можете оценить код и написать мои ошибки пожалуйста ?
Master:
Код: Выделить всё
#include <mega8.h>
#include <spi.h>
#include <delay.h>
float res;
unsigned char SPI_transmit(unsigned char data)
{
SPDR = data; //отправка байта data
while(!(SPSR & (1<<7))); //Ожидание завершении отправки
data = SPDR; //получение байта от Слейва и присвоении к переменной data
return(data);
}
void main(void)
{
PORTB=0x00;
DDRB=0x2C; //Инициализация порта В MISO IN
PORTC=0xFF;
DDRC=0x00;
SPCR = 0x50; //записываем Регистр управления SPE=1 MSTR=1
SPSR = 0x00;
res=0x80;
while (1)
{
if(PINC.0==0)
{
res=SPI_transmit(0x7F); //Отправляем запрос
delay_ms(200); //Ждем
res=SPI_transmit(0x80); //Получаем ответ на первый запрос
while(PINC.0==0){}; //Пока кнопка зажата программа зацикливается
}
delay_ms(200);
};
}
Slave:
Код: Выделить всё
#include <mega8.h>
#include <spi.h>
int res;
unsigned char SPI_receive(void)
{
unsigned char data;
while(!(SPSR & (1<<7))); //Жду завершении передачи
data = SPDR; //присваиваю переменной принятый байт от мастера
if(data==0b1110){SPDR=0b1110;}
if(data==0x80){SPDR=0x80;}
else if(data!=14&&data!=0x80){SPDR=data;}
return data;
}
void main(void)
{
PORTB=0x00;
DDRB=0x10; //инициализация порта MISO IN
SPCR=0xC0; //записываем Регистр управления SPIE=1 SPE=1
SPSR=0x00;
res=SPI_receive();
}