SPI передача от ведомого

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
KaiTheKat
Открыл глаза
Сообщения: 56
Зарегистрирован: Чт сен 04, 2014 18:21:01

SPI передача от ведомого

Сообщение KaiTheKat »

МК - ATmega8. В режиме ведомого, когда кладу данные в SPDR, на ведущий приходят данные сдвинутые на один вправо. Т. е. хочу отправить 0b10000111, а приходит 0b01000011.
Логика программы:
Ведущий (мастер):
установка в 0 SS ведомого, отправка-прием-запись данных, установка в 1 SS ведомого, ждем (например 10 мкс)
Ведомый:
SPDR=0b00000011;
while(1) { //цикл
отправка-прием-запись данных, ждем пока SS не установится в 1, SPDR=0b10000111;
}

Причем самый первый SPDR=0b00000011; приходит верно, а остальные сдвинутым приходят. В чем дело?
Реклама
Аватара пользователя
Mishany
Электрический кот
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Re: SPI передача от ведомого

Сообщение Mishany »

надо смотреть настройки SPI, и саму программу... вариантов много
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: SPI передача от ведомого

Сообщение ARV »

как вариант: у ведущего и ведомого по разным фронтам SCK синхронизируются данные - у одного по переднему, у другого по заднему.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
KaiTheKat
Открыл глаза
Сообщения: 56
Зарегистрирован: Чт сен 04, 2014 18:21:01

Re: SPI передача от ведомого

Сообщение KaiTheKat »

настройки для ведущего: SPCR=(1<<SPE)|(1<<MSTR);
настройки для ведомого:SPCR=(1<<SPE);
Данные с ведущего на ведомый приходят верные, а с ведомого на ведущий со сдвигом, кроме первого байта.
Код целиком
Ведущий (Мастер):
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <string.h>

char txbuf[10]; //буфер для передачи
char rxbuf[10]; //буфер для приема
uint8_t a=0;
bool clk=false; // против дребезга

char sendSpi(uint8_t data) { SPDR=data; while(!(SPSR&(1<<SPIF))); return SPDR; } // отправка-прием-запись

int main(void)
{
DDRB=(1<<2)|(1<<3)|(1<<4)|(1<<5); // все порты SPI на выход
DDRD=(1<<0); // для управления SS ведомого
PORTD=(1<<5)|(1<<6); // для кнопок
DDRC=255; PORTC=0; // для вывода полученных данных
SPCR=(1<<SPE)|(1<<MSTR); // SPI включен, режим Мастер

txbuf[0]=0b00000001; txbuf[1]=0b00001101; txbuf[2]=0b01101000; // запись в буфер передачи

while(1)
{
if((clk==false)) {
if(!(PIND&(1<<5))) { clk = true; // после нажатия на кнопку отправляем данные 10 раз (буфер состоит из 10-ти байтов)
for(uint8_t i=0; i<10; i++) { PORTD&=~(1<<0); _delay_ms(1); rxbuf=sendSpi(txbuf); _delay_ms(1); PORTD|=(1<<0); _delay_ms(1); //устанавливаем SS ведомого на 0, отправка данных, устанавливаем SS ведомого на 1, ждем 1 мс }
}
else if(!(PIND&(1<<6))) { clk = true; // после нажатия выводим на портс полученные данные по очереди.
PORTC=rxbuf[a]; a++; if(a>9) { a=0; }
}
}
if((clk==true)&&(PIND&(1<<5))&&(PIND&(1<<6))) { clk = false; // антидребезг }
}
}

Ведомый:
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <string.h>

char txbuf[10]; //буфер для передачи
char rxbuf[10]; //буфер для приема
uint8_t a=0; bool clk=false; // против дребезга

bool waitSendByte() { // ждем больше 100мс, пока не придут данные от ведущего. Если данные не пришли переходим на след. действие.
for(uint32_t i=0; i<110000; i++) {
if((SPSR&(1<<SPIF))) { return true; }
}
return false;
}
void setSPDR() { // ждем пока SS не установится в 1 (деактивацию SPI)
while(1) {
if((PINB&(1<<2))) { break; }
}
}
int main(void)
{
DDRB=(1<<4); //MISO на выход
DDRD=0; PORTD=(1<<5)|(1<<6); // для кнопок
DDRC=255; PORTC=0; // для вывода полученных данных
SPCR=(1<<SPE); // SPI включен

txbuf[0]=0b0000111; txbuf[1]=0b11110000; txbuf[2]=0b00011100; // запись в буфер передачи
SPDR=0b00000011; // самый первые данные для передачи. они приходят успешно.

while(1)
{
for(uint8_t i=0; i<10; i++) {
if(waitSendByte()) { rxbuf=SPDR; setSPDR(); SPDR=0b00001111; (или SPDR=txbuf;) //отправка-прием-запись данных } else { break; }
}
if((clk==false)) { // после нажатия выводим на портс полученные данные по очереди.
if(!(PIND&(1<<6))) { clk = true; // после
PORTC=rxbuf[a]; a++; if(a>9) { a=0; }
}
}
if((clk==true)&&(PIND&(1<<6))) { clk=false; }
}
}
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: SPI передача от ведомого

Сообщение ARV »

у вас 1 ведущий и 1 ведомый? если да, то тогда не надо использовать SS, соответственно ждать ничего не надо тоже.

остальное, благодаря чудному оформлению кода, смотреть не стал :dont_know:
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
KaiTheKat
Открыл глаза
Сообщения: 56
Зарегистрирован: Чт сен 04, 2014 18:21:01

Re: SPI передача от ведомого

Сообщение KaiTheKat »

Да 1 ведущий, 1 ведомый. При нажатии на кнопку я отправляю-принимаю 10 байт. Если у ведомого на SS будет всегда 0, он же не сможет записать данные в SPDR. Если всегда 1 он будет отключен. Не так?
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: SPI передача от ведомого

Сообщение ARV »

кто вам сказал, что не сможет? ведущий от ведомого отличается только тем, что после записи в SPDR ведущий сразу же начинает выдавать такты SCK, а ведомый не начинает.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6312
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: SPI передача от ведомого

Сообщение Jack_A »

ARV писал(а): после записи в SPDR ведущий сразу же начинает выдавать такты SCK, а ведомый не начинает.
Ведомый вообще никогда SCK не выдает.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18561
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: SPI передача от ведомого

Сообщение ARV »

Jack_A писал(а):Ведомый вообще никогда SCK не выдает.
ну а я разве что-то другое сказал?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6312
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: SPI передача от ведомого

Сообщение Jack_A »

Я так понял : "начинает, но не сразу " :)
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Re: SPI передача от ведомого

Сообщение ILYAUL »

Тут ведь какое дело , ведомый пока мастер выдает SCK , может подпихивать байты в SPDR , которые мастер может спокойно получить . Главное успевать за мастером.
Аватара пользователя
KaiTheKat
Открыл глаза
Сообщения: 56
Зарегистрирован: Чт сен 04, 2014 18:21:01

Re: SPI передача от ведомого

Сообщение KaiTheKat »

У Мастера ожидание после прием-передачи оставил, а управление SS ведомым убрал (теперь он всегда на 0-ле) у ведомого. У ведомого сразу после окончания прием-передачи записываю новые данные в SPDR. Теперь все данные приходят корректно. Спасибо за ответы!

До этого перед тем как записать новые данные в SPDR у ведомого, я проверял SS. И записывал, только если там 1. Могла ли быть ошибка из-за этого?

Кстати, данные приходили до этого так:
нужные данные - 0b01111111; или 0b10000000;
приходящие данные - 0b00111111; или 0b11000000;

Т. е. 7 бит записывается дважды в 7 и 6 ячейку. Остальные сдвигаются с потерией 0-го бита.
Аватара пользователя
ILYAUL
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср мар 28, 2012 21:45:24
Откуда: ВО

Re: SPI передача от ведомого

Сообщение ILYAUL »

SS =0 - указывает ведомому , что с ним хотят пообщаться. Но к сожалению , автоматика не предусмотрена и проверять его вроде как необходимо (DS)

Но есть выход - использовать его как сигнал внешнего прерывания , отлавливая фронты.
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6312
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: SPI передача от ведомого

Сообщение Jack_A »

Я бы не стал вешать константный 0 на SS . После установки SS в 0 дал бы небольшую задержку перед передачей первого байта, чтобы слейв успел загрузить в регистр данных свой первый предназначенный для отправки байт.
Ответить

Вернуться в «AVR»