Вс мар 24, 2024 14:12:38
Вс мар 24, 2024 20:40:52
Пн мар 25, 2024 08:45:37
Вт мар 26, 2024 08:29:27
Вт мар 26, 2024 15:29:34
Вт мар 26, 2024 19:57:01
Ср мар 27, 2024 18:09:42
.[/uquote]
Теперь схема выглядит так.
[url=https://img.radiokot.ru/files/154442/medium/3eoro7ny97.jpg]
Задумка такова, что в master есть переменная counter, которая поочередно в двух циклах for меняется от 0 до 4 и обратно. Значение этой переменной передается по SPI в slave. Причем в функции прерывания ISR(SPI_STC_vect) master один раз мигает светодиодом D9 при начале отправки по SPI, и 1 раз после отправки. Slave получает по SPI переменную counter и через stitch зажигает светодиоды D5-D8 (число горящих светодиодов равно переменной counter). В симуляции все мигает как надо, но в реале на макетке 1 раз мигнет светодиод D9 и больше ничего не происходит. Как будто в master прерывание по SPI с чем то конфликтует, хотя у меня других прерываний нет.
Код master:
[code]
#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_master_settings(void) //настройки SPI_Master
{
DDRB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
DDRB&=~(1<<MISO);
PORTB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR|=(1<<SPIE);[color=#800000]// разрешаем прерывания по SPI[/color]
SPCR|=(1<<SPE);// разрешаем работу SPI
SPCR|=(1<<MSTR); // МК работает как master
SPSR&=~(1<<SPI2X); //без удвоения частоты
SPCR&=~(1<<SPR1);
SPCR|=(1<<SPR0);
SPCR|=(1<<CPOL); // импульсы отрицательной полярности
SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты(MSB
}
ISR(SPI_STC_vect)
{
PORTC|=(1<<4); //первый раз мигаем светодиодом D9
_delay_ms(100);
PORTC&=~(1<<4);
_delay_ms(100);
while(~SPSR&(1<<SPIF)) //ждем окончания передачи
;
PORTB|=(1<<SS);
PORTC|=(1<<4); //второй раз мигаем светодиодом D9
_delay_ms(100);
PORTC&=~(1<<4);
_delay_ms(100);
}
int main(void)
{
SPI_master_settings();
sei();
DDRC|=(1<<4);//светодиод D9
PORTC&=~(1<<4);
while (1)
{
for (int i=0;i<5;i++)
{
counter++;
if(counter>4)
{counter=4;}
if(counter<0)
{counter=0;}
PORTB&=~(1<<SS);
SPDR=counter;
_delay_ms(100);
}
for (int i=0;i<4;i++)
{
counter--;
if(counter>4)
{counter=3;}
if(counter<0)
{counter=0;}
PORTB&=~(1<<SS);
SPDR=counter;
_delay_ms(100);
}
}
}
[/code]
Код slave:
[code]
#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);
PORTB|=(1<<MISO);
SPCR|=(1<<SPIE); //разрешаем прерывания по линии SPI
SPCR|=(1<<SPE);// разрешаем работу SPI
SPCR&=~(1<<MSTR); // МК работает как slave
SPCR|=(1<<CPOL); //мы используем импульсы отрицательной полярности SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты(MSB
DDRB&=~(1<<SS);
PORTB&=~(1<<SS);
}
ISR(SPI_STC_vect)
{
while(~SPSR&(1<<SPIF)) //ждем завершения обмена данными
;
counter=SPDR;//присваиваем переменной counter значение полученное по SPI
}
int main(void)
{
DDRC|=(1<<5)|(1<<4);//светодиоды D5, D6
PORTC&=~((1<<5)|(1<<4));
DDRB|=(1<<7)|(1<<6);//светодиоды D7, D8
PORTB&=~((1<<7)|(1<<6));
SPI_slave_settings();
sei();
while (1)
{
switch(counter) //мигаем светодиодами
{
case 0:PORTC&=~((1<<5)|(1<<4));PORTB&=~((1<<7)|(1<<6));break;
case 1:PORTC|=(1<<4);PORTC&=~(1<<5);PORTB&=~((1<<7)|(1<<6));break;
case 2:PORTC|=(1<<5)|(1<<4);PORTB&=~((1<<7)|(1<<6));;break;
case 3:PORTC|=(1<<5)|(1<<4);PORTB|=(1<<6);PORTB&=~(1<<7);break;
case 4:PORTC|=(1<<5)|(1<<4);PORTB|=(1<<6)|(1<<7);break;
}
}
}
Вт апр 09, 2024 19:23:34
#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
void SPI_master_settings(void) //настройки SPI_Master
{
DDRB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
PORTB|=(1<<SS);
DDRB&=~(1<<MISO);
PORTB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR=0;
SPSR=0;
SPDR=0;
SPCR|=(1<<SPIE);//разрешаем прерывания по линии SPI
SPCR|=(1<<SPE);//разрешаем работу SPI
SPCR|=(1<<MSTR); // МК работает как master
SPSR&=~(1<<SPI2X); //без удвоения частоты
SPCR&=~(1<<SPR1);//нам нужен предделитель частоты МК clk/16:
SPCR|=(1<<SPR0);
SPCR|=(1<<CPOL); //используем импульсы отрицательной полярности
SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты
}
int main(void)
{
SPI_master_settings();
for (int i=0;i<5;i++)
{
PORTB&=~(1<<SS);
SPDR=i;
while(!(SPSR&(1<<SPIF))) ; //Дождаться окончания передачи
PORTB |=(1<<SS);
_delay_ms(100);
}
}
#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
void SPI_slave_settings(void) //настройки SPI_SLAVE
{
DDRB&=~((1<<MOSI)|(1<<SCK));
DDRB|=(1<<MISO);
PORTB|=(1<<MISO);
SPCR=0;
SPSR=0;
SPDR=0;
SPCR|=(1<<SPIE);
SPCR|=(1<<SPE);
SPCR&=~(1<<MSTR); //МК работает как slave
SPCR|=(1<<CPOL);
SPCR|=(1<<CPHA);
SPCR&=~(1<<DORD);
DDRB&=~(1<<SS);
PORTB&=~(1<<SS);
}
int main(void)
{
DDRC|=(1<<5)|(1<<4);// 1й и 2йсветодиоды
PORTC&=~((1<<5)|(1<<4));
DDRB|=(1<<7)|(1<<6);// 3й и 4й светодиоды
PORTB&=~((1<<7)|(1<<6));
_delay_ms(50);
SPI_slave_settings();
while (1)
{
while(~SPSR&(1<<SPIF)) //ждем завершения обмена данными
;
counter=SPDR;//получили цифру от master
switch(counter)
{
case 0:PORTC&=~((1<<5)|(1<<4));PORTB&=~((1<<7)|(1<<6));break; //светодиоды погашены
case 1:PORTC|=(1<<4);PORTC&=~(1<<5);PORTB&=~((1<<7)|(1<<6));break; //зажигаем 1й светодиод
case 2:PORTC|=(1<<5);PORTC&=~(1<<4);PORTB&=~((1<<7)|(1<<6));;break; //зажигаем 2й светодиод
case 3:PORTB|=(1<<6);PORTB&=~(1<<7);PORTC&=~((1<<5)|(1<<4));break; //зажигаем 3й светодиод
case 4:PORTB|=(1<<7);PORTB&=~(1<<6);PORTC&=~((1<<5)|(1<<4));break; //зажигаем 4й светодиод
}
}
}
#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
void SPI_master_settings(void) //настройки SPI_Master
{
DDRB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
PORTB|=(1<<SS);
DDRB&=~(1<<MISO);
PORTB|=(1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR=0;
SPSR=0;
SPDR=0;
SPCR|=(1<<SPIE);//разрешаем прерывания по линии SPI
SPCR|=(1<<SPE);//разрешаем работу SPI
SPCR|=(1<<MSTR); // МК работает как master
SPSR&=~(1<<SPI2X); //без удвоения частоты
SPCR&=~(1<<SPR1);//нам нужен предделитель частоты МК clk/16:
SPCR|=(1<<SPR0);
SPCR|=(1<<CPOL); //используем импульсы отрицательной полярности
SPCR|=(1<<CPHA);//работаем по заднему фронту импульса
SPCR&=~(1<<DORD); //сперва передаются старшие биты
}
ISR(SPI_STC_vect)
{
while(~SPSR&(1<<SPIF)) //ждем когда данные передадутся и флаг SPIF станет =1 и мы выйдем из цикла
;
PORTB|=(1<<SS);
}
int main(void)
{
SPI_master_settings();
while (1)
{
for (int i=0;i<5;i++) //по очереди отправляем цифры 0,1,2,3,4 в slave
{
PORTB&=~(1<<SS);
SPDR=i;
_delay_ms(100);
}
}
}
#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);
PORTB|=(1<<MISO);
SPCR=0;
SPSR=0;
SPDR=0;
SPCR|=(1<<SPIE);
SPCR|=(1<<SPE);
SPCR&=~(1<<MSTR);
//мы не выбираем частоты работы SPI для slave, т.к. он подчиняется master
SPCR|=(1<<CPOL);
SPCR|=(1<<CPHA);
SPCR&=~(1<<DORD);
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);// 1й и 2йсветодиоды
PORTC&=~((1<<5)|(1<<4));
DDRB|=(1<<7)|(1<<6);// 3й и 4й светодиоды
PORTB&=~((1<<7)|(1<<6));
_delay_ms(50);
SPI_slave_settings();
sei();
while (1)
{
switch(counter)
{
case 0:PORTC&=~((1<<5)|(1<<4));PORTB&=~((1<<7)|(1<<6));break; //светодиоды погашены
case 1:PORTC|=(1<<4);PORTC&=~(1<<5);PORTB&=~((1<<7)|(1<<6));break; //зажигаем 1й светодиод
case 2:PORTC|=(1<<5);PORTC&=~(1<<4);PORTB&=~((1<<7)|(1<<6));;break; //зажигаем 2й светодиод
case 3:PORTB|=(1<<6);PORTB&=~(1<<7);PORTC&=~((1<<5)|(1<<4));break; //зажигаем 3й светодиод
case 4:PORTB|=(1<<7);PORTB&=~(1<<6);PORTC&=~((1<<5)|(1<<4));break; //зажигаем 4й светодиод
}
_delay_ms(100);
}
}