Скиньте пожалуйста коды SLAVE и Master под SPI и I2C.
В прикрепленном файле пример использования SPI (код написан в avrasm)
Здесь нет телепатов. И теоретически не понятно что вы хотите от этого соединения. Связь должна быть в обе стороны или только в одну. По SPI я думаю будет легче. Генерите код в CV, во вкладке SPI поставте галку чтобы через прерывание. Затем сделайте сначало передачу в одну сторону, от мастера к слейву. Что-то подобное как передача по UART. А там глдядишь и дотумкаете как в обе стороны сделать.Goldkiller писал(а):Здравствуйте уважаемые Коты. У меня проблема с подключением двух контроллеров через SPI или I2C. В инете все проверил, все статьи , форумы, но к сожалению не смог найти нужной информации. Теоретическое подключение мне понятно. Но не получается написать код в Codevision.
Скиньте пожалуйста коды SLAVE и Master под SPI и I2C.![]()
![]()
![]()
Код: Выделить всё
#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){ }
}Goldkiller писал(а): В инете все проверил, все статьи , форумы, но к сожалению не смог найти нужной информации.
s_black писал(а):Goldkiller писал(а): В инете все проверил, все статьи , форумы, но к сожалению не смог найти нужной информации.
Плохо искал.
Если для готового устройства ( флеш, таймкипер, термометр etc. ) - то в соответствии с ДШ на них. Если для самостоятельно программируемого устройства - в соответствии с выбранным протоколом в переданном пакете содержится адрес устройства. Все слейвы слушают линию, и тот, у которого его адрес совпадает с адресом в пакете, отвечает. Адреса у слейвов могут задаваться джамперами, могут быть прошиты ( нежелательно, трудно изменять ) или раздаваться динамически по включению мастера ( мне не нравится, ненадежно, imho ) .Goldkiller писал(а): В) Как в SPI работает Адресация ?![]()
![]()
![]()
Передачу 2 сразу слейвам я не буду делать. Только по очередности.s_black писал(а): Насчёт адресации см. выше и помните, что, если выбрано более одного SLAVE, то они примут данные от MASTER, но вот, что MASTER примет у себя от нескольких SLAVE-ов - это ещё вопрос, т.к. выйдет коллизия с накладкой байтов друг на друга!
Вы не до конца поняли суть SPI интерфейса. В тот момент, когда идёт передача с мастера на слейв по линии MOSI - MOSI , В ЭТО ЖЕ ВРЕМЯ идёт обратная передача со слейва на мастер по линии MISO - MISO. И, после окончания передачи, в регистре данных мастера будет принятый байт от слейва. Вы же хотите реакции от слева на команду. Т.е. слейву нужно принять команду, допустим измерения напряжения, выполнить её (посчитайте, сколько времени займут эти процессы) и, после измерения напряжения, поместить значение напряжения в регистр данных SPI, чтобы потом передать его ПО ТАКТИРУЮЩИМ ИМПУЛЬСАМ от мастера. Таким образом мастер сначала должен выдать команду на измерение напряжения, выждать необходимое время, и снова запустить обмен, чтобы считать значение напряжения, которое слейв к этому моменту поместит в регистр данных SPI. Лучше задействовать дополнительную линию от слейва на мастер, чтобы от по ней информировать мастер об окончании измерения и готовности передать измеренное значение.Goldkiller писал(а): Пока что получилось осуществить отправку к слейв байтов. Сейчас пытаюсь понять как отправить обратно ответ мастеру.
Может у вас есть готовый код двух стороннего обмена данных ?
Категорически нельзя ! Я в одной из своих ранних работ так сделал - ужос ! Если в передаваемый поток случайно попадет лишний бит ( каким образом - помеха или что-нибудь - неважно ) - он там будет циркулировать до скончания века, сдвигая информацию на 1 бит. При выборке же через SS буфер очищается, и в описанном случае будет битым только один пакет.Goldkiller писал(а):Можно ли на Слейве порт SS просто заземлить, а на Мастере SS не куда не подключать ?
Согласен . Кроме того желательно, чтобы слейв, перед загрузкой измеренного значения в регистр данных SPI, предварительно записал туда маркер "измерение завершено", чтобы мастер знал, что следующее считанное значение - результат. Я просто исходил из того что мастер и так загружен какими-то процессами, если по условию ТЗ напряжение и температуру измеряют внешние устройства.Jack_A писал(а): s_black Если там напряг с лишними линиями, можно, подав команду "Начать измерение" затем периодически подавать команду "Выдать данные", получая в ответ или статус "измерение не окончено", или готовые данные. Если, конечно, слейв тоже разрабатывается самостоятельно, и оба устройства можно "подружить" в смысле протокола обмена.
Спасибо вам большое, понял суть подключения SPI и отправку байтов.s_black писал(а): Согласен . Кроме того желательно, чтобы слейв, перед загрузкой измеренного значения в регистр данных SPI, предварительно записал туда маркер "измерение завершено", чтобы мастер знал, что следующее считанное значение - результат.
Код: Выделить всё
#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);
};
}Код: Выделить всё
#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();
}