Как должно работать:
При начале каждой передачи первый МК(далее-master) зажигает ненадолго свой светодиод (на PORTC.4). Потом передает по SPI переменную counter=2 во второй МК (далее-slave), который принимает переменную counter=2 и зажигает соответственно 2 светодиода.
В протеусе все работает нормально.
По итогу получается: собрал все на макетке и при включении master 1 раз включает светодиод, после чего он светится примерно на 50% от того уровня, какой был при включении, и не гаснет вообще (как будто цикл while не выполняется до конца либо выполняется 1 раз). А slave вообще не реагирует никак.
Пробовал убрать связь по SPI между master и slave (в коде закомментил все, что отвечает за SPI) и менял программу просто чтобы каждый МК отдельно помигал своими светодиодами, чтобы исключить неисправность светодиодов и портов МК и все нормально работало. Но как только я возвращал в код все, что связано с SPI, То опять ничего не работало (как было ранее).
Товарищи, не подскажете в чем может быть проблема? Вроде уже и master со slaave менял местами (и на схеме и прошивки) и результат все тот же
Код master:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define SS 2
#define MOSI 3
#define MISO 4
#define SCK 5
int counter=2;
void SPI_master_settings(void) //настройки SPI_Master
{
DDRB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
PORTB|=(1<<SS); //этот пин надо установить раньше настроек регистра контроля т.е. раньше команды SPCR|=(1<<MSTR); уже не помню почему
DDRB&=~(1<<MISO);
SPCR|=(1<<SPIE);//SPCR-регистр контроля SPI.
//Ставим SPIE=1 (разрешаем прерывания по линии SPI). Когда произошел обмен данными и мастер получил все 8 бит, то сработает прерывание и флаг SPIF становится=1
SPCR|=(1<<SPE);//SPI ENABLE. Ставим этот бит=1, чтобы разрешить работу SPI
SPCR|=(1<<MSTR); //если MSTR=1, МК работает как master
//нам нужен предделитель частоты МК F/16: SPI2X=0 SPR1=0 SPR0=1
SPSR&=~(1<<SPI2X); // мы не удваиваем частоту работы SPI
SPCR&=~(1<<SPR1);
SPCR|=(1<<SPR0);
SPCR|=(1<<CPOL); //мы используем импульсы отрицательной полярности согласно табл 48 (даташит atmega8 стр.126)
SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты(MSB), а потом младшие (LSB) . Если =0, то наоборот
}
ISR(SPI_STC_vect)
{
while(~SPSR&(1<<SPIF)) //ждем когда данные передадутся и флаг SPIF станет =1 и мы выйдем из цикла
;
PORTB|=(1<<SS);
}
int main(void)
{
SPI_master_settings();
sei();
DDRC|=(1<<4);//светодиод
PORTC&=~(1<<4);
while (1)
{
PORTC|=(1<<4);//мигаем светодиодом
_delay_ms(300);
PORTC&=~(1<<4);
_delay_ms(300);
PORTB&=~(1<<SS);
SPDR=counter;
_delay_ms(300);
}
}
Код slave:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define SS 2
#define MOSI 3
#define MISO 4
#define SCK 5
int counter=0;
void SPI_slave_settings(void) //настройки SPI_SLAVE
{
DDRB&=~((1<<MOSI)|(1<<SCK));
DDRB|=(1<<MISO);
SPCR|=(1<<SPIE);//SPCR-регистр контроля SPI.
SPCR|=(1<<SPE);//SPI ENABLE. Ставим этот бит=1, чтобы разрешить работу SPI
SPCR&=~(1<<MSTR); //ставим MSTR=0, чтобы МК работал как slave (если =1 то как master)
SPCR|=(1<<CPOL); //мы используем импульсы отрицательной полярности согласно табл 48 (даташит atmega8 стр.126)
SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты(MSB), а потом младшие (LSB) . Если =0, то наоборот
DDRB&=~(1<<SS);
PORTB|=(1<<SS); //подтягиваем к единице
}
ISR(SPI_STC_vect)
{
while(~SPSR&(1<<SPIF)) //ждем завершения обмена данными
;
counter=SPDR;//присваиваем переменной counter значение полученное по SPI и сохраненное в регистре данных SPI (SPDR)
}
int main(void)
{
DDRC|=(1<<5)|(1<<4);//светодиоды
PORTC&=~((1<<5)|(1<<4));
DDRB|=(1<<7)|(1<<6);//светодиоды
PORTB&=~((1<<7)|(1<<6));
SPI_slave_settings();
sei();
while (1)
{
if(counter>4)
{
PORTC|=(1<<5);
PORTC&=~(1<<4);
PORTB|=(1<<6);
PORTB&=~(1<<7);
}
if(counter==0)
{
PORTC&=~((1<<5)|(1<<4));
PORTB&=~((1<<7)|(1<<6));
}
if(counter==1)
{
PORTC|=(1<<4);
PORTC&=~(1<<5);
PORTB&=~((1<<7)|(1<<6));
}
if(counter==2) //при передаче COUNTER=2 должно работать вот это
{
PORTC|=(1<<5)|(1<<4);
PORTB&=~((1<<7)|(1<<6));
}
if(counter==3)
{
PORTC|=(1<<5)|(1<<4);
PORTB|=(1<<6);
PORTB&=~(1<<7);
}
if(counter==4)
{
PORTC|=(1<<5)|(1<<4);
PORTB|=(1<<7)|(1<<6);
}
}
}


