С Новым годом! Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/40: Рейтинг темы: голосов - 40, средняя оценка - 4.65
23 / 23 / 7
Регистрация: 04.11.2011
Сообщений: 566
Записей в блоге: 1
1

Обмен данными по SPI между двумя Atemga

02.03.2016, 10:39. Показов 7951. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пытаюсь реализовать обмен 5 байт данными между двумя Atmeg(1-Atmega165 ведущий, 2-Atmega16 ведомый),
обмен начинается при прерывания которое срабатывает при нажатие кнопки, начинается отправка первого байта 0xaAA после его отправки, срабатывает прерывание SPI и из регистра SPDR я должен этот бай снять и записать другой байт чтобы вернуть его обратно, но происходит сбои в обмене, реализую всё в ATMEL STUDIO и Proteus 8, можете помочь может я не до конца понял как происходит обмен SPI.

Код ведущего (Atmega165)
C
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#define F_CPU 8000000
 
#define SS_BIT 0
#define SCK_BIT 1
#define MOSI_BIT 2
#define MISO_BIT 3
 
#include <avr/io.h>
#include <avr/interrupt.h>
char switcher;
 
unsigned char temp;
unsigned char counter;
 
unsigned char BufOut[5]={0xAA,0x02,0x03,0x04,0x05};
unsigned char BufIn[5]={};
 
 
 ISR(SPI_STC_vect) {
    
        counter++;
        
            BufIn[counter-1]=SPDR;
        
        if(counter==5)
            {
            
                PORTB |=(1<<SS_BIT); //Выключить SS
                return;
            }
        else
            {
                SPDR=BufOut[counter];
            }
        
    
        
        
        
 }
 
 
void InitInterruptSynk(){
    
    ////Настройка прерывания
    SREG |=(1<<7); //ВКЛЮЧИТЬ ГЛОБАЛЬНОЕ ПРЕРЫВАНИЕ 
    EIMSK |=(1<<0); //Включить прерывание на ножке INT0
    PCMSK0 |=(1<<0);/// включаем прерывание на нажке INT0
    // Событие при изменение лог значения
    EICRA |=(1<<1);
    EICRA &=~(1<<0);
        
}
 
 
void InitSPi(){
    
///////Настройка портов SPI
    DDRB |=(1<<SS_BIT);
    DDRB |=(1<<SCK_BIT);
    DDRB |=(1<<MOSI_BIT);
    DDRB &=~(1<<MISO_BIT);
    PORTB |=(1<<SS_BIT);
        
///////Настройка SPI
    SPCR|=(1<<4);/// ведущий 
    //настройка частоты 8MhZ/8MhZ =1 MhZ
    SPCR |=(1<<0);
    SPCR &=~(1<<1);
    SPSR |=(1<<0);
    /// Передача со старшего бита в байте
    SPCR &=~(1<<5);
    //// Режим SPI 
    SPCR &=~(1<<3);///такты положительной полярности
    SPCR &=~(1<<2);///Считывание по переднему фронту
    ///Включаем SPI 
    SPCR |=(1<<6);
    ///Включаем флаг прерывания
    SPCR |=(1<<7);
}
 
 
void SpiTransfer(char a){
    
    //asm("cli");
    PORTB &=~(1<<SS_BIT); //Выбор SS   
    SPDR=a;
    counter=0;
    
    //while(!(SPSR & (1<<SPIF)));///Ожидание завершения передачи данных
//  asm("sei");
}
 
ISR (INT0_vect){
 
    if(switcher){PORTA|=(1<<0);switcher=0;}else{PORTA&=~(1<<0);switcher=1;}
    SpiTransfer(BufOut[0]);
    
    
}
 
 
 
int main(void)
{
    
    switcher=0;
    ///Настройка порта ЛЕД
    DDRA |=(1<<0);
    PORTA &=~(1<<0);
    
    DDRA |=(1<<1);
    PORTA &=~(1<<1);
    
    InitSPi();
    InitInterruptSynk();
    
    
    
    asm("sei");
    while (1) 
    {
        
        asm("nop");
        
        
    }
}

Код ведомого (Atmega16)

C
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
87
88
89
90
91
92
93
94
95
96
97
98
#define F_CPU 1000000 
 
#define SS_BIT 4
#define MOSI_BIT 5
#define MISO_BIT 6
#define SCK_BIT 7
 
#include <avr/io.h>
#include <avr/interrupt.h>
 
unsigned char temp;
unsigned char counter;
 
unsigned char BufOut[5]={0x01,0x02,0x03,0x04,0x05};
unsigned char BufIn[5]={};
    
unsigned char FlagTransfer;
 
 
void InitSPI(){
    
    DDRB &=~(1<<SS_BIT);
    DDRB &=~(1<<SCK_BIT);
    DDRB &=~(1<<MOSI_BIT);
    DDRB |= (1<<MISO_BIT);
    
    SPCR &=~(1<<4);/// ведомый 
    
    //Включаем SPI
    SPCR |=(1<<6);
    ///Включаем флаг прерывания
    SPCR |=(1<<7);
    
    //SPDR=0;
    
}
 
 
 ISR(SPI_STC_vect) {
    
    temp=SPDR;
    
    if(temp==0xAA)
    {       
        FlagTransfer=1;
        
    }
        ///////////////????????????????????????????????
        
        if(FlagTransfer)
        {
        
                counter++;
                
                BufIn[counter-1]=SPDR;
                
                if(counter==5)
                {
                    counter=0;
                    FlagTransfer=0;
                //  PORTC|=(1<<0);
                    return;
                }
                
                
                SPDR=BufOut[counter];
    
        }
    
    //  PORTC|=(1<<0); //Включить лед
 
 
 }
 
int main(void)
{
 DDRA|=(1<<0);
 DDRC|=(1<<0);
 
 
 InitSPI();
 counter=0;
//  SPDR=0xAA;
 char TMP;
 asm("sei");
    while (1) 
    {
        
        asm("nop");
        
        //  PORTC|=(1<<0); //Включить лед
        TMP=BufIn[0];
    if(TMP==0xAA)
        {PORTC|=(1<<0);}
    
        
    }
}
В приложение оба проекта Atmel Studio и проект в Proteus
Миниатюры
Обмен данными по SPI между двумя Atemga   Обмен данными по SPI между двумя Atemga  
Вложения
Тип файла: rar YSV.rar (19.1 Кб, 16 просмотров)
Тип файла: rar YDK_YOD.rar (22.1 Кб, 13 просмотров)
Тип файла: rar MyProject.rar (21.7 Кб, 13 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
02.03.2016, 10:39
Ответы с готовыми решениями:

Как организовать обмен данными между двумя контроллерами
Заранее извиняюсь за нубский вопрос. Есть два микроконтроллера, шина данных (порты A, B), линия...

Нужно слушать обмен данными между двумя устройствами по rs-232
Нужно слушать обмен данными между двумя устройствами по rs-232(уровень сигнала ±12В) Какую...

Обмен данными с датчиком давления mprls0015pa0000sa по SPI
Добрый день. Отправляю команды согласно даташиту но при команде 0xAA0000 присылает 0xFFFFFF а при...

Обмен данными между двумя приложениями
Здравствуйте! Задача такая: существует два приложения: одно содержит кнопки вверх, вниз, влево,...

5
23 / 23 / 7
Регистрация: 04.11.2011
Сообщений: 566
Записей в блоге: 1
02.03.2016, 11:02  [ТС] 2
Ёщё тут же вопрос может проблема в подключение, в некоторых источниках пишут что нужно подключить MISO-MISO MOSI-MOSI, в других MOSI-MISO MISO-MOSI, как правильно
Миниатюры
Обмен данными по SPI между двумя Atemga  
0
23 / 23 / 7
Регистрация: 04.11.2011
Сообщений: 566
Записей в блоге: 1
02.03.2016, 11:12  [ТС] 3
Изменил подключение данные теряются, не понимаю в чём дело
Миниатюры
Обмен данными по SPI между двумя Atemga  
0
1978 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
02.03.2016, 21:46 4
Цитата Сообщение от generation472 Посмотреть сообщение
начинается отправка первого байта 0xaAA после его отправки, срабатывает прерывание SPI и из регистра SPDR я должен этот бай снять
неверно мыслите. Слейв передаст вам первый принятый байт уже при приеме второго байта. Он же не может передавать вам то, чего еще не знает?
вот пример (M - master, S - slave):
1) Мастер шлет первый байт слейву. В момент передачи он принимает что-то там от слейва. Часто это последний отправленный байт слейва.
2) Слейв принимает байт и шлет его себе в буфер, ожидая следующего байта от мастера.
3) Мастер шлет второй байт и принимает одновременно от слейва, что у него висит в буфер, то есть свой собственный первый байт.
4) Слейв принимает второй байт от мастера и снова ложит его в свой буфер.
....
N) Мастер отправляет последний байт из своейго буфера, при этом принимая от слева предпоследний байт. В итоге слейв ложит его себе в буфер, но мастер уже ничего не шлет, соответственно, он не принимает последний собственный байт. Чтобы его принять, мастером просто надо отправить что-нибудь слейву, чтобы он переслал (в конце) обратно оставшийся байт...
2
Модератор
Эксперт по электронике
8951 / 6717 / 921
Регистрация: 14.02.2011
Сообщений: 23,712
03.03.2016, 21:08 5
Цитата Сообщение от Voland_ Посмотреть сообщение
Мастер шлет второй байт и принимает одновременно от слейва, что у него висит в буфер, то есть свой собственный первый байт.
насколько знаю, буфера у АВрок физически разделены,правда имеют один и тот же адрес, так что програмисту кажется что он работает с одним и тем же буфером
2
23 / 23 / 7
Регистрация: 04.11.2011
Сообщений: 566
Записей в блоге: 1
04.03.2016, 16:12  [ТС] 6
Voland_, Хорошо допустим я это понял тогда вопрос когда срабатывает прерывание, после одной отправки?

Добавлено через 1 час 27 минут
Переделал код, пытаюсь отправить один байт и вернуть один, получается что при первой отправке я отправляю байт на слэйве я его принимаю, записываю в регистр данные, и при второй отправке мастер опять отправляет и считывает, но когда считывает то теряются данные как будто происходит один лишний сдвиг, то есть я должен принять 0b10010110 а на самом деле протеус показывает что принимаю 0b11001011
Мастер
C
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * AvrYDK_YOD.c
 *
 * Created: 29.02.2016 20:12:39
 * Author : Ваня
 *
 * Проект под YDK
 */ 
 
#define F_CPU 8000000
 
#define   BitIsClear(reg, bit)    ((reg & (1<<bit)) == 0)
#define   BitIsSet(reg, bit)       ((reg & (1<<bit)) != 0)
 
#define SS_BIT 0
#define SCK_BIT 1
#define MOSI_BIT 2
#define MISO_BIT 3
 
#include <avr/io.h>
#include <avr/interrupt.h>
char switcher;
 
unsigned char temp;
unsigned char counter;
 
unsigned char BufOut[5]={0xAA,0x02,0x03,0x04,0x05};
unsigned char BufIn[5]={};
    
unsigned char SYNK1=0;
unsigned char SYNK2=0;  
 
void SpiTransfer(unsigned char a);
 
 
 ISR(SPI_STC_vect) {
        
            
    
 }
 
ISR (INT0_vect){
    if(switcher){PORTA|=(1<<0);switcher=0;}else{PORTA&=~(1<<0);switcher=1;}
    //  SpiTransfer(BufOut[0]);
}
 
ISR (PCINT0_vect){
    
 
    if(BitIsSet(PINE,7)){
    if(SYNK1==0){PORTA&=~(1<<0);SYNK1=1;}else{PORTA|=(1<<0);SYNK1=0;}
        SpiTransfer(120);
    }
    
    
}
    
ISR (PCINT1_vect){  
 
    
        if(BitIsSet(PINB,6)){
    if(SYNK2==0){PORTA&=~(1<<1);SYNK2=1;}else{PORTA|=(1<<1);SYNK2=0;}
        SpiTransfer(120);   
    }
    
}
 
 
void InitInterruptSynk(){
    
    ////Настройка прерывания
    SREG |=(1<<7); //ВКЛЮЧИТЬ ГЛОБАЛЬНОЕ ПРЕРЫВАНИЕ 
    
    EIMSK=0b11000000;///включить прерывания на группах PCIE1 и PCIE0
    
    PCMSK0|=(1<<7);///Включить прерывание на контакте PE7
    PCMSK1|=(1<<6);///Включить прерывние на контакте PB6 
    
        
    DDRE&=~(1<<7);/// PE7 настроен на вход сигнала     
    DDRB&=~(1<<6);/// PB6 настроен на вход сигнала
        
}
 
 
void InitSPi(){
    
///////Настройка портов SPI
    DDRB |=(1<<SS_BIT);
    DDRB |=(1<<SCK_BIT);
    DDRB |=(1<<MOSI_BIT);
    DDRB &=~(1<<MISO_BIT);
    PORTB |=(1<<SS_BIT);
        
///////Настройка SPI
    SPCR|=(1<<4);/// ведущий 
    //настройка частоты 8MhZ/8MhZ =1 MhZ
    SPCR |=(1<<0);
    SPCR &=~(1<<1);
    SPSR |=(1<<0);
    /// Передача со старшего бита в байте
    SPCR &=~(1<<5);
    //// Режим SPI 
    SPCR &=~(1<<3);///такты положительной полярности
    SPCR &=~(1<<2);///Считывание по переднему фронту
    ///Включаем SPI 
    SPCR |=(1<<6);
    ///Включаем флаг прерывания
    SPCR |=(1<<7);
}
 
 
void SpiTransfer(unsigned char a){
    
    
    PORTB &=~(1<<SS_BIT);///
    SPDR=a; 
    while (!(SPSR & (1 << SPIF))); // Ждем конца ПЕРЕДАЧИ
    PORTB |=(1<<SS_BIT);///
    temp=SPDR;
    if(temp==150){PORTA|=(1<<6);}
    
}
 
 
 
 
 
int main(void)
{
    
    switcher=0;
    ///Настройка порта ЛЕД
    DDRA |=(1<<0);
    PORTA &=~(1<<0);
    
    DDRA |=(1<<1);
    PORTA &=~(1<<1);
    
    InitSPi();
    InitInterruptSynk();
    
    
    
    asm("sei");
    while (1) 
    {
        
        asm("nop");
        
        
    }
}
Слэйв
C
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
/*
 * AtmegaYSV.c
 *
 * Created: 29.02.2016 20:03:12
 * Author : Ваня
 *
 * Проект под YSV
 */ 
#define F_CPU 1000000 
 
#define SS_BIT 4
#define MOSI_BIT 5
#define MISO_BIT 6
#define SCK_BIT 7
 
#include <avr/io.h>
#include <avr/interrupt.h>
 
unsigned char temp;
unsigned char counter;
 
unsigned char BufOut[5]={0x01,0x02,0x03,0x04,0x05};
unsigned char BufIn[5]={};
    
unsigned char FlagTransfer;
 
 
void InitSPI(){
    
    DDRB &=~(1<<SS_BIT);
    DDRB &=~(1<<SCK_BIT);
    DDRB &=~(1<<MOSI_BIT);
    DDRB |= (1<<MISO_BIT);
    
    SPCR &=~(1<<4);/// ведомый 
    
    //Включаем SPI
    SPCR |=(1<<6);
    ///Включаем флаг прерывания
    SPCR |=(1<<7);
    
    //SPDR=0;
    
}
 
 
 ISR(SPI_STC_vect) {
    
 
    temp=SPDR;
    if(temp==120){PORTC|=(1<<0);}
    SPDR=150;
    
        
 }
 
int main(void)
{
 DDRA|=(1<<0);
 DDRC|=(1<<0);
 
 
 InitSPI();
 counter=0;
//  SPDR=0xAA;
 
 asm("sei");
    while (1) 
    {
        
        asm("nop");
    
        
    }
}
0
04.03.2016, 16:12
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.03.2016, 16:12
Помогаю со студенческими работами здесь

Обмен данными между двумя файлами
Разработать программу обмена данными между двумя файлами. Имена файлов вводятся с клавиатуры.

Обмен данными между двумя программами
Доброго времени суток! Подскажите, есть ли возможность передавать из одной запущенной копии...

Обмен данными между двумя удаленными БД
Есть две БД. Обе находяться на разных серверах. Не могу реализовать обмен данными между ними в...

Обмен данными между двумя приложениями
есть 2 приложения. Приложение 1 - Создает Приложение 2 с помощью CreateProcess(); следовательно...

Обмен данными между двумя устройствами
Доброго времени суток, У меня возник следующий вопрос. У нас в студенческом общежитии, где я...

Обмен данными между двумя формами
У меня есть две формы и нужно передать данные от одной формы к другой. Вот код: /* Форма 1 */...

Обмен данными между двумя файлами
написать программу обмена данными между двумя файлами задача по теме работа с файлами в,билдер с++...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Книги и учебные ресурсы по C#
InfoMaster 08.01.2025
Базовые учебники и руководства Одной из лучших книг для начинающих является "C# 10 и . NET 6 для начинающих" Эндрю Троелсена и Филиппа Джепикса . Книга последовательно раскрывает основные концепции. . .
Что такое NullReferenceEx­­­ception и как исправить?
InfoMaster 08.01.2025
NullReferenceException - одно из самых распространенных исключений, с которым сталкиваются разработчики на C#. Это исключение возникает при попытке обратиться к членам объекта (методам, свойствам или. . .
Что такое Null Pointer Exception (NPE) и как это исправить?
InfoMaster 08.01.2025
Null Pointer Exception (NPE) - это одно из самых распространенных исключений в Java, которое возникает при попытке использовать ссылку на объект, значение которой равно null. Это исключение относится. . .
Русский язык в консоли C++
InfoMaster 08.01.2025
При разработке программ на C++ одной из частых проблем, с которой сталкиваются русскоязычные программисты, является корректное отображение кириллицы в консольных приложениях. Эта проблема особенно. . .
Telegram бот на C#
InfoMaster 08.01.2025
Разработка ботов для Telegram стала неотъемлемой частью современной экосистемы мессенджеров. C# предоставляет мощный и удобный инструментарий для создания разнообразных ботов, от простых. . .
Использование GraphQL в Go (Golang)
InfoMaster 08.01.2025
Go (Golang) является одним из наиболее популярных языков программирования, используемых для создания высокопроизводительных серверных приложений. Его архитектурные особенности и встроенные. . .
Что лучше использовать при создании класса в Java: сеттеры или конструктор?
Alexander-7 08.01.2025
Вопрос подробнее: На вопрос: «Когда одновременно создаются конструктор и сеттеры в классе – это нормально?» куратор уточнил: «Ваш класс может вообще не иметь сеттеров, а только конструктор и геттеры. . .
Как работать с GraphQL на TypeScript
InfoMaster 08.01.2025
Введение в GraphQL и TypeScript В современной разработке веб-приложений GraphQL стал мощным инструментом для создания гибких и эффективных API. В сочетании с TypeScript, эта технология. . .
Счётчик на базе сумматоров + регистров и генератора сигналов согласования.
Hrethgir 07.01.2025
Создан с целью проверки скорости асинхронной логики: ранее описанного сумматора и предополагаемых fast регистров. Регистры созданы на базе ранее описанного, предполагаемого fast триггера. То-есть. . .
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru