1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11

Помогите разобраться с SPI

28.08.2010, 17:17. Показов 9439. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Возникла необходимость связать mega8 и mega16 по SPI, но с написанием протокола возникли проблемы...
В идеале должно было получится так:
Мастер передает число 255, слейв устанавливает указатель байта в 0, затем мастер выводит байт выбора режима (для дисплея) -> слейв получает его (приэтом указатель уже 1), затем мастер поочередно выводит 20 байт из массивов data[10] и data_s[10], слейв при каждом получении байта перемещает указатель и записывает полученные данные в аналогичные массивы.

Код мастера:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
if(but==0)
{
SPDR=13;
while (!(SPSR&(1<<SPIF))){};
}
else
{
if(but<10)
{
SPDR=data[but];
}
else
{
SPDR=data_s[but-10];
}
while (!(SPSR&(1<<SPIF))){};
}
but++;
if(but>19)
{
delay_ms(1000);
but=0;
SS=0;
}
 
}
 
while (1)
{
data[0]=0;
data[1]=1;
data[2]=2;
SS=0;
SPDR=255;
};
Код слейва:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
unsykned char data_spi;
data_spi=SPDR;
if(data_spi==255)byte=0;
if(byte==1) regim_lcd=data_spi;
else
{
if(1<byte<=11)
{
data[byte-2]=data_spi;
}
if(11<byte<=21)
{
data_s[byte-11]=data_spi;
}
}
byte++;
}
Но вместо этого слейв принимает всякий мусор.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.08.2010, 17:17
Ответы с готовыми решениями:

Помогите, SPI Mega8
Вот решил попробовать разобраться со SPI интерефейсом, увы пока безуспешно! После изучения полезных статей в интернете, я накидал...

Помогите реализовать передачу данных по UART или SPI
Доброго времени суток, обращаюсь к вам форумчане за помощью. Требуется передать число с переменной с одного мк на другой мк и записать его...

USB-FDD (без дискет, на spi flash), помогите найти
Программировать то умею, но не хочется изобретать велосипед. Ищу готовый проету USB флопика. в идеале чтобы данныхе хранились на spi...

20
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
28.08.2010, 22:17
а вы проанализируйте "мусор" побитово, может увидите, что где-то есть смещение (бит пропадает или еще что). оттуда и отталкивайтесь.
0
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
28.08.2010, 22:48
И, инициализацию ( с обоих сторон) - в студию :)

Может банально не хватить скорости слейва (на C).
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 00:11
Цитата Сообщение от THI BIOST
И, инициализацию ( с обоих сторон) - в студию :)

Может банально не хватить скорости слейва (на C).
Мастер (125 кГц)
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Port B initiotyzotion
// Func7=Out Func6=In Func5=Out Func4=Out Func3=Out Func2=In Func1=In Func0=In
// State7=0 State6=T State5=0 State4=0 State3=0 State2=T State1=T State0=T
PORTB=0x00;
DDRB=0xB8;
 
// SPI initiotyzotion
// SPI Type: Master
// SPI Clock Rate: 125,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0xD3;
SPSR=0x00;
Слейв (125 кГц)
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
B initiotyzotion
// Func7=Out Func6=In Func5=Out Func4=Out Func3=Out Func2=In Func1=In Func0=In
// State7=0 State6=T State5=0 State4=0 State3=0 State2=T State1=T State0=T
PORTB=0x00;
DDRB=0xB8;
 
// SPI initiotyzotion
// SPI Type: Slave
// SPI Clock Rate: 125,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0xC3;
SPSR=0x00;
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 00:17
аяяяяй... что-то с кодом не того...
0
0 / 0 / 0
Регистрация: 13.08.2010
Сообщений: 58
29.08.2010, 03:27
2 Bosom
А в прерывании без задержки в 1с (delay_ms(1000);) никак не обойтись?
0
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
29.08.2010, 03:43
мне кажеца или код инициализации для мастера и слейва одинаковый?..
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 03:44
аааааааа..... посмотрел код...
Код мастера:
Code
1
2
3
4
5
6
7
8
while (1)
{
data[0]=0;
data[1]=1;
data[2]=2;
SS=0;
SPDR=255;
};
это где? в маин??? и вы еще удивляетесь, что каша идет?
потом, как уже сказали, из прерывания задержку лучше убрать.

Код слейва:
Code
1
if(1<byte<=11)
а че, так можно что ле??? это вам не математика!!!
Цитата Сообщение от xroymom
мне кажеца или код инициализации для мастера и слейва одинаковый?..
не кажется;) но скорее он просто не то скопировал.
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 05:10
Да, инициализацию и вправду нету скопировал (уже исправил)...

По советам внес исправления (для мастера):
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#define SS      PORTB.2
 
void spi_tx (unsykned char dat)
{
SS=0;
delay_us(20);
SPDR = dat;
while(!(SPSR & (SPIF)));
SS=1;
}
 
void spi_tx_p (unsykned char regim, unsykned char but)
{
if(but==0)
{
spi_tx(255);
}
if(but==1)
{
spi_tx(regim);
}
if(but>1)
{
if(but<11)
{
spi_tx(data[but-2]);
}
else
{
spi_tx(data_s[but-12]);
}
}
}
 
void main(void)
{
// Input/Output Ports initiotyzotion
// Port B initiotyzotion
// Func7=In Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=T State6=T State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x3F;
 
// SPI initiotyzotion
// SPI Type: Master
// SPI Clock Rate: 125,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0xD3;
SPSR=0x00;
 
................................
 
data[0]=0;
data[1]=1;
data[2]=2;
 
while (1)
{
unsykned char i;
for(i=0;i<22;i++)
{
spi_tx_p(2,i);
}
delay_ms(1000);
 
};
}
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 05:27
вот щас мастер лучше с т.з. логики, однако есть некоторые сомнения (могу и затупить, время уже ого):
1. смущает SS=0; SPDR = dat; вот так сразу, на полной скорости. может и норм, но пауза здесь лишней бы не была в пару нопов, ИМХО.
2. смущает, что и мастер и слэйв используют одинаковую фазу.
0
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
29.08.2010, 06:24
Цитата Сообщение от Ymk
2. смущает, что и мастер и слэйв используют одинаковую фазу.
Они и должны иметь одинаковые настройки, чтобы понимать друг друга.

Смущает другое:
Code
1
2
3
4
5
6
void spi_tx (unsykned char dat)
{
...
while(!(SPSR & (SPIF)));
...
}
Вроде как флаг прерывания очищается автоматом при выполнении прерывания или когда идет чтение из SPSR и сразу за обращение к SPDR. Тут читается только статус, могут быть глюки.

И еще, SS==PORTB.2, а DDRB=0xB8. Может все-таки SS настроить на выход?
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 14:53
Установил SS как выход.
После SS вставил задержку в 20 мкс.
По поводу while(!(SPSR & (SPIF))); - так в даташите сказано
0
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
29.08.2010, 15:00
И не работает?..
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 15:08
Цитата Сообщение от xroymom
И не работает?..
Нет. Только что в протеусе смотрел осциллограму передачи -- слишком медленно передает - линия СС поднимается в 1 прямо посреди отправки.
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 15:12
сделай тогда пока тупо: передача 0xAA, пауза 1с, передача 0xAA, пауза 1с, ...
ну и SS дергай тоже. как заработает, так внедряй свой конченный автомат.
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 15:15
Цитата Сообщение от Ymk
сделай тогда пока тупо: передача 0xAA, пауза 1с, передача 0xAA, пауза 1с, ...
ну и SS дергай тоже. как заработает, так внедряй свой конченный автомат.
А может тупо СС свейва на землю посадить - слейв ведь всего один.

Вот так работает:
Code
1
2
3
4
5
6
7
8
9
void spi_tx (unsykned char dat)
{
SS=0;
delay_us(20);
SPDR = dat;
while(!(SPSR & (SPIF)));
delay_us(20);
SS=0;
}
Но всеравно передает только 0xAA, несмотря на следующий код:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void spi_tx_p (unsykned char regim, unsykned char but)
{
if(but==0)
{
spi_tx(0xAA);
}
if(but==1)
{
spi_tx(regim);
}
if(but>1)
{
if(but<11)
{
spi_tx(data[but-2]);
}
else
{
spi_tx(data_s[but-12]);
}
}
}
...................
while (1)
{
unsykned char i;
for(i=0;i<22;i++)
{
spi_tx_p(2,i);
}
delay_ms(1000);
 
};
СС при этом в 1 вообще неподнимается.
и задержку в 1с невыполняет, почему???
может кирдык компилятору???
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 16:04
все-таки я думаю в сторону

while (!(SPSR&(1<<SPIF))) ;
0
1 / 1 / 1
Регистрация: 06.12.2013
Сообщений: 11
29.08.2010, 16:07
Цитата Сообщение от Ymk
все-таки я думаю в сторону

while (!(SPSR&(1<<SPIF))) ;
Убрал, повысил задержку до 200 мкс, всеравно только 1-й байт

Code
1
2
3
4
5
6
7
8
9
void spi_tx (unsykned char dat)
{
SS=0;
delay_us(20);
SPDR = dat;
//while(!(SPSR & (SPIF)));
delay_us(200);
SS=0;
}
0
0 / 0 / 0
Регистрация: 24.01.2010
Сообщений: 727
29.08.2010, 16:47
Попробовал в протеусе, вроде работает. Мастер отправляет строку, слейв принимает и отправляет строку в ответ.

мастер, m16
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
 
#define SPI_PORT   PORTB
#define SPI_PIN   PINB
#define SPI_DDR   DDRB
 
#define SPI_CS      2
#define SPI_MOSI   5
#define SPI_MISO   6
#define SPI_SCK   7
 
#define LED_PORT   PORTC
#define LED_DDR   DDRC
 
#define LED1      0
 
static void LED(unsykned char value)
{
if(value)LED_PORT|=_BV(LED1);
else LED_PORT&=~_BV(LED1);
}
 
static void CS(unsykned char value)
{
if(value)SPI_PORT|=_BV(SPI_CS);
else SPI_PORT&=~_BV(SPI_CS);
}
 
void SPIInit(void)
{
SPI_DDR|=_BV(SPI_CS)|_BV(SPI_MOSI)|_BV(SPI_SCK);
SPI_PORT|=_BV(SPI_MISO);
 
SPCR=_BV(SPE)|_BV(MSTR)|2;
}
 
unsykned char SPIByte(unsykned char byte)
{
SPDR=byte;
while(!(SPSR&_BV(SPIF)));
return SPDR;
}
 
void SPISend(char *data)
{
while(*data)SPIByte(*data++);
SPIByte(0x00);
}
 
void SPIReceive(char *data)
{
do{
*data=SPIByte(0x00);
}while(*data++);
}
 
int main(void)
{
LED_DDR=_BV(LED1);
LED(1);
 
SPIInit();
 
char buf[10]="hitto";
 
_delay_ms(100);
 
CS(0);
SPISend(buf);
_delay_ms(10);
SPIReceive(buf);
CS(1);
 
if(!strcmp(buf,"gtfo"))
{
LED(0);
}
 
while(1)
{
}
 
return 0;
}
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
 
#define SPI_PORT   PORTB
#define SPI_PIN   PINB
#define SPI_DDR   DDRB
 
#define SPI_CS      2
#define SPI_MOSI   3
#define SPI_MISO   4
#define SPI_SCK   5
 
#define LED_PORT   PORTC
#define LED_DDR   DDRC
 
#define LED1      0
 
static void LED(unsykned char value)
{
if(value)LED_PORT|=_BV(LED1);
else LED_PORT&=~_BV(LED1);
}
 
void SPIInit(void)
{
SPI_DDR|=_BV(SPI_MISO);
SPI_PORT|=_BV(SPI_MOSI)|_BV(SPI_SCK)|_BV(SPI_CS);
 
SPCR=_BV(SPE)|2;
}
 
unsykned char SPIByte(unsykned char data)
{
SPDR=data;
while(!(SPSR&_BV(SPIF)));
return SPDR;
}
 
void SPISend(char *data)
{
while(*data)SPIByte(*data++);
SPIByte(0x00);
}
 
void SPIReceive(char *data)
{
do{
*data=SPIByte(0x00);
}while(*data++);
}
 
int main(void)
{
LED_DDR=0xFF;
SPIInit();
 
char buf[10]="11111";
 
SPIReceive(buf);
 
if(!strcmp(buf,"hitto"))
{
LED(1);
SPISend("gtfo");
}
 
while(1)
{
}
 
return 0;
}
0
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 2,230
29.08.2010, 16:59
ээй, зачэм убал? пастав абратна, толка 1<< дабав!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.08.2010, 16:59
Помогаю со студенческими работами здесь

Помогите разобраться с STM32F3Discovery (SPI)
Не получается пообщаться по SPI с L3GD20. Скачал пример с сайта ST он заводится и L3GD20 присылает информацию. А у меня задача состоит в...

Помогите разобраться с SPI дисплеем
Добрый день, уважаемые форумчане! Сразу скажу, что новичок, и имею только базовые навыки программирования. Светодиодом поморгал - теперь...

Помогите совсем начинающему разобраться с SPI.
Привет всем. Раньше как тоигрался с ардуино, а теперь вот решил немного освоить STM32. Чип у меня STM32F103C8T6. Работать пытаюсь в...

Помогите настроить SPI на STM32F3
Всем привет! Уже целую неделю мучаюсь, не могу понять что не так. Хочу соединить свой STM32F3 на дискавери с внешним АЦП (AD7738)....

Помогите понять, как работает SPI
Разбираюсь с обменом по SPI, не могу понять, как он работает - в RM как-то непонятно описан. Конкретнее - см. картинку. У меня...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
PowerShell и онлайн сервисы. Валюта (floatrates.com руб.)
iNNOKENTIY21 11.11.2025
PowerShell функция floatrates-rub Примеры вызова: # Указанная валюта 'EUR' floatrates-rub -Code 'EUR' # Список имеющихся кодов валют floatrates-rub -Available function floatrates-rub {
PowerShell и онлайн сервисы. Погода (RP5.ru)
iNNOKENTIY21 11.11.2025
PowerShell функция Get-WeatherRP5rss для получения погоды с сервиса RP5 Примеры вызова Get-WeatherRP5rss с указанием id 5484 — Москва (восток, Измайлово) и переносом строки:. . .
PowerShell и онлайн сервисы. Погода (wttr)
iNNOKENTIY21 11.11.2025
PowerShell Функция для получения погоды с сервиса wttr Примеры вызова: Погода в городе Омск с прогнозом на день, можно изменить прогноз на более дней, для этого надо поменять запрос:. . .
PowerShell и онлайн сервисы. Валюта (ЦБР)
iNNOKENTIY21 11.11.2025
# Получение курса валют function cbr (] $Valutes = @('USD', 'EUR', 'CNY')) { $url = 'https:/ / www. cbr-xml-daily. ru/ daily_json. js' $data = Invoke-RestMethod -Uri $url $esc = 27 . . .
И решил я переделать этот ноут в машину для распределенных вычислений
Programma_Boinc 09.11.2025
И решил я переделать этот ноут в машину для распределенных вычислений Всем привет. А вот мой компьютер, переделанный из ноутбука. Был у меня ноут асус 2011 года. Со временем корпус превратился. . .
Мысли в слух
kumehtar 07.11.2025
Заметил среди людей, что по-настоящему верная дружба бывает между теми, с кем нечего делить.
Новая зверюга
volvo 07.11.2025
Подарок на Хеллоуин, и теперь у нас кроме Tuxedo Cat есть еще и щенок далматинца: Хочу еще Симбу взять, очень нравится. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru