Страница 1 из 1
Передача данных по SPI
Добавлено: Пн фев 13, 2012 08:00:17
Prosperous
Здравствуйте! Начал осваивать МК. Нужно передать данные от одного МК другому по SPI. МК atmega 128. Взял готовую реализацию SPI из datasheet. Вроде ничего сложного. Данные как бы передаются, а в порт ничего не выводится. Подскажите, пожалуйста, неучу, где ошибка.
Инициализация мастера
Код: Выделить всё
void SPI_MasterTransmit()
{
unsigned char cData;
/* Запуск передачи данных */
cData = 0x55;
SPDR = cData;
/* Ожидание завершения передачи данных */
while(!(SPSR & (1<<SPIF)))
;
}
void main(void)
{
PORTB=0x00;
DDRB=0x07;
SPCR=0x50;
SPSR=0x00;
SPI_MasterTransmit();
}
Инициализация слэйва
Код: Выделить всё
unsigned char SPI_receive(void)
{
unsigned char data;
data = SPDR;
while(!(SPSR & (1<<SPIF)));
return data;
}
void main(void)
{
PORTB=0x00;
DDRB=0x08;
PORTE=0x00;
DDRE=0xFF;
SPCR=0x40;
SPSR=0x00;
PORTE = SPI_receive();
}
Re: Передача данных по SPI
Добавлено: Пн фев 13, 2012 14:42:16
Prosperous
вопрос решен. Возник еще один. откуда взялись 2 еденицы перед 0х55?
Re: Передача данных по SPI
Добавлено: Пн фев 13, 2012 15:18:02
Engineer_Keen
Не видно что это за единицы, не хватает графика линии CLK.
Re: Передача данных по SPI
Добавлено: Пн фев 13, 2012 15:30:36
Prosperous
перезалил файл
Re: Передача данных по SPI
Добавлено: Пн фев 13, 2012 15:38:29
Engineer_Keen
Как я и думал, это никакие не единицы на SPI, это просто до первой передачи или инициализации нога, которая MOSI висит в "1". Ее при инициализации перед выводом в DDRB нужно сразу в "0" поставить, хотя это не должно влиять на обмен по SPI.
Re: Передача данных по SPI
Добавлено: Пн фев 13, 2012 20:21:19
Prosperous
так вроде судя по инициализации (см код выше) Это нога в нуле
Re: Передача данных по SPI
Добавлено: Сб мар 10, 2012 11:49:54
Prosperous
Добрый день. Есть такая, на мой взгляд, не тривиальная задача. Нужно организовать передачу данных между ПЛИС(slave) и МК(master) по SPI. Т.к. с такими системами отладки я не знаком, то не придумал ничего умнее, как на время отладки заменить ПЛИС микроконтроллером с программным SPI. Полазил по форуму и нашел решение программного SPI для mastera и переделал под slave.
Код: Выделить всё
#define MOSI PINA.0
#define MISO PORTA.1
#define SS PINA.2
#define SCK PORTB.3
char data[96]; // в плисене в очереди на передачу стоит 96 бит данных. м.б. тип данных тут другой нужен?
unsigned char spi(char *data){
unsigned char mosi = 0;
unsigned char mask = 0x01; // если надо начинать со старшего бита - заменить на 0x80
if (SS==0)
{
for( ; mask; mask <<= 1){ // если надо начинать со старшего бита - заменить на mask >>= 1;
MISO = data & mask;
SCK = 1;
if(MOSI) mosi |= mask;
SCK = 0;
}
}
return mosi;
}
void main(void)
{
//инициализацию портов пропускаю
spi(data);
}
пока возникли 2 вопроса:
1. здесь линия SCK программно настраивается, а в ПЛИС она аппаратная. Как реализовать это здесь сохранив программный SPI?
2. Нужно передать 12 байт данных, а тут после байта программа завершает свою работу. Чего не хватает?
Буду благодарен за любую помощь

Re: Передача данных по SPI
Добавлено: Сб мар 10, 2012 17:53:28
s_black
Re: Передача данных по SPI
Добавлено: Вс мар 11, 2012 10:43:54
Meteor
пока возникли 2 вопроса:
1. здесь линия SCK программно настраивается, а в ПЛИС она аппаратная. Как реализовать это здесь сохранив программный SPI?
2. Нужно передать 12 байт данных, а тут после байта программа завершает свою работу. Чего не хватает?
1) Раз у вас МК является ведущим, то так и оставьте. ПЛИС надо только соединить с МК (при наличии конечно конфигурации ПЛИС).
2) Можно сделать просто. Если используется SPI МК - передавать 2 байта один из которых упаковать не полностью или разделить на старший\младший с признаком (полет фантазии неисчерпаем). Если же делается чисто программный протокол (плевать какие выводы МК задействованы), то в рамках него можно сделать передачу и 4 бит и 12 бит и 35 бит - тут опять ничего не держит за руки\ноги\лапы и хвосты
Re: Передача данных по SPI
Добавлено: Пт мар 16, 2012 08:50:49
Prosperous
подумав, сварганил програмку под slave. токо чето не работает. хотя на мой взгляд все логично

Укажите, пожалуйста, где я не прав
Код: Выделить всё
#define BYTES_NUMBER 12 //количество байт, которое над передать
#define MOSI PINA.1
#define MISO PORTA.0
#define SCK PIND.0 // повесил на ногу прерывания
#define SS PINA.2
#include <mega128.h>
char TX_DataBuffer[BYTES_NUMBER]={0xF9,0x55,0x33,0x01,0xBC,0x4A,0x80,0x12,0xCB,0x55,0x73,0x62}; //данные
char TX_Cnt = 0; //счетчик бит
char Bits_Cnt = 0; // счетчик байт
char Flag_Int0 = 0; // выполняет роль нарастающего фронта CLK
unsigned char SPI_receive();
interrupt [EXT_INT0] void ext_int0_isr(void)
{
Flag_Int0++;
}
unsigned char SPI_receive()
{
unsigned char cData = 0;
unsigned char mask = 0x80;
unsigned char temp = 0;
if (SS == 0)
{
for (Bits_Cnt=0; Bits_Cnt<8;Bits_Cnt++)
{
cData << Bits_Cnt;
temp=cData&mask;
MISO = temp;
}
}
else
MISO = 0;
if(Bits_Cnt == 7)
{
Bits_Cnt=0;
TX_Cnt++;
}
if(TX_Cnt < 12)
cData = TX_DataBuffer[TX_Cnt];
if(TX_Cnt == 12)
{
Flag_Int0 = 0;
#asm("cli")
TX_Cnt=0;
Bits_Cnt=0;
}
return MISO;
}
void main(void)
{
PORTA=0x00;
DDRA=0x01;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
PORTF=0x00;
DDRF=0x01;
EICRA=0x03;
EICRB=0x00;
EIMSK=0x01;
EIFR=0x01;
TX_Cnt = 0;
Bits_Cnt = 0;
#asm("sei")
while (1)
{
PORTF = PINC & 1;
if (Flag_Int0>=1)
SPI_receive();
};
}