SPI передача от ведомого
SPI передача от ведомого
МК - ATmega8. В режиме ведомого, когда кладу данные в SPDR, на ведущий приходят данные сдвинутые на один вправо. Т. е. хочу отправить 0b10000111, а приходит 0b01000011.
Логика программы:
Ведущий (мастер):
установка в 0 SS ведомого, отправка-прием-запись данных, установка в 1 SS ведомого, ждем (например 10 мкс)
Ведомый:
SPDR=0b00000011;
while(1) { //цикл
отправка-прием-запись данных, ждем пока SS не установится в 1, SPDR=0b10000111;
}
Причем самый первый SPDR=0b00000011; приходит верно, а остальные сдвинутым приходят. В чем дело?
Логика программы:
Ведущий (мастер):
установка в 0 SS ведомого, отправка-прием-запись данных, установка в 1 SS ведомого, ждем (например 10 мкс)
Ведомый:
SPDR=0b00000011;
while(1) { //цикл
отправка-прием-запись данных, ждем пока SS не установится в 1, SPDR=0b10000111;
}
Причем самый первый SPDR=0b00000011; приходит верно, а остальные сдвинутым приходят. В чем дело?
- Реклама
- Mishany
- Электрический кот
- Сообщения: 1031
- Зарегистрирован: Чт июн 20, 2013 00:00:58
- Откуда: москва, м.Сходненская
Re: SPI передача от ведомого
надо смотреть настройки SPI, и саму программу... вариантов много
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: SPI передача от ведомого
как вариант: у ведущего и ведомого по разным фронтам SCK синхронизируются данные - у одного по переднему, у другого по заднему.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: SPI передача от ведомого
настройки для ведущего: 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; }
}
}
настройки для ведомого: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
}
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 передача от ведомого
у вас 1 ведущий и 1 ведомый? если да, то тогда не надо использовать SS, соответственно ждать ничего не надо тоже.
остальное, благодаря чудному оформлению кода, смотреть не стал
остальное, благодаря чудному оформлению кода, смотреть не стал
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Реклама
Re: SPI передача от ведомого
Да 1 ведущий, 1 ведомый. При нажатии на кнопку я отправляю-принимаю 10 байт. Если у ведомого на SS будет всегда 0, он же не сможет записать данные в SPDR. Если всегда 1 он будет отключен. Не так?
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: SPI передача от ведомого
кто вам сказал, что не сможет? ведущий от ведомого отличается только тем, что после записи в SPDR ведущий сразу же начинает выдавать такты SCK, а ведомый не начинает.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: SPI передача от ведомого
Ведомый вообще никогда SCK не выдает.ARV писал(а): после записи в SPDR ведущий сразу же начинает выдавать такты SCK, а ведомый не начинает.
- ARV
- Ум, честь и совесть. И скромность.
- Сообщения: 18561
- Зарегистрирован: Чт дек 28, 2006 08:19:56
- Откуда: Новочеркасск
- Контактная информация:
Re: SPI передача от ведомого
ну а я разве что-то другое сказал?Jack_A писал(а):Ведомый вообще никогда SCK не выдает.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Re: SPI передача от ведомого
Я так понял : "начинает, но не сразу " 
Re: SPI передача от ведомого
Тут ведь какое дело , ведомый пока мастер выдает SCK , может подпихивать байты в SPDR , которые мастер может спокойно получить . Главное успевать за мастером.
Re: SPI передача от ведомого
У Мастера ожидание после прием-передачи оставил, а управление SS ведомым убрал (теперь он всегда на 0-ле) у ведомого. У ведомого сразу после окончания прием-передачи записываю новые данные в SPDR. Теперь все данные приходят корректно. Спасибо за ответы!
До этого перед тем как записать новые данные в SPDR у ведомого, я проверял SS. И записывал, только если там 1. Могла ли быть ошибка из-за этого?
Кстати, данные приходили до этого так:
нужные данные - 0b01111111; или 0b10000000;
приходящие данные - 0b00111111; или 0b11000000;
Т. е. 7 бит записывается дважды в 7 и 6 ячейку. Остальные сдвигаются с потерией 0-го бита.
До этого перед тем как записать новые данные в SPDR у ведомого, я проверял SS. И записывал, только если там 1. Могла ли быть ошибка из-за этого?
Кстати, данные приходили до этого так:
нужные данные - 0b01111111; или 0b10000000;
приходящие данные - 0b00111111; или 0b11000000;
Т. е. 7 бит записывается дважды в 7 и 6 ячейку. Остальные сдвигаются с потерией 0-го бита.
Re: SPI передача от ведомого
SS =0 - указывает ведомому , что с ним хотят пообщаться. Но к сожалению , автоматика не предусмотрена и проверять его вроде как необходимо (DS)
Но есть выход - использовать его как сигнал внешнего прерывания , отлавливая фронты.
Но есть выход - использовать его как сигнал внешнего прерывания , отлавливая фронты.
Re: SPI передача от ведомого
Я бы не стал вешать константный 0 на SS . После установки SS в 0 дал бы небольшую задержку перед передачей первого байта, чтобы слейв успел загрузить в регистр данных свой первый предназначенный для отправки байт.


