0 голосов
Получаю фиксированный массив данных по SPI ведомым (slave), по прерыванию SPI.interrupt. Я так понял, что пин SS или CS не участвует в этом. Происходит смещение начала массива, как мне обнулять счетчик массива при падении SS c высокого сигнала на низкий (c HIGH до LOW, начало передачи посылки)?
(22 баллов) 1 5 7

2 Ответы

+1 голос
 
Лучший ответ

Не понял вопроса, да и в вопросе отсутствуют примеры кода и тех. данные SPI, но объясню, как работает блок SPI в AVR серии ATMega.

В режиме MASTER блок SPI никак не управляет пином SS (Slave Select). Соответственно, им надо управлять программно. А раз так, то для этой цели можно выбрать, помимо SS, любой другой пин, предварительно сконфигурировав его на выход (например в случае, когда SLAVE устройств на шине несколько).

В режиме SLAVE (в режиме SLAVE блок SPI тактируется внешним устройством) блоком SPI можно управлять двумя путями:

1. Перевести программно с помощью флага в регистре управления

2. Перевести аппаратно с помощью пина SS.

И вот последний способ имеет одну особенность: при подаче на пин SS низкого уровня, блок SPI сразу же переходит в режим SLAVE. Поэтому, если блок SPI работает в режиме MASTER, то пин SS лучше сразу же переводить как выход.

Что такое счетчик массива - я не знаю (в блоке SPI нет такого счетчика).

Смещение начала массива может происходить по весьма простой причине - программный код в обработчике прерывания не успевает обработать получаемые данные.

ДОПОЛНЕНО:

Прерывание по пину SS возникает сразу же, как только внешнее устройство переводит пин SS в ноль. Поэтому индекс массива можно обнулить в самом начале прерывания от SPI. 

Но я  делаю по другому. Зачем индекс, если можно "скользить" по ячейкам массива указателем?

	//... Отправить и получить несколько байт по SPI. Принятые данные лежат в data
void SPI_ReadArray(uint8_t num, uint8_t *data)
{
	while(num--)
	{
		*data++ = SPI_WriteByte(*data);
	}
}

где:

 	//... Передать и принять байт данных
 inline uint8_t SPI_WriteByte(uint8_t data)
 {
	uint8_t temp;
	
	SPDR = data; 	
	
	while(!(SPSR & (1<<SPIF)));
 		
	temp = SPDR;

 	return temp;
 }

(2.7 тыс. баллов) 10 29 55
выбран
Извиняюсь, не так выразился "индекс, т.е. номер элемента в массиве". У меня мастер передает, а слейв принимает и записывает данные как массив.
Квалификатор volatile добавлен к переменным, которые изменяются в прерывании?
да,  и сам массив и индекс и еще флаг, что буфер заполнен.
дополнил ответ
+1 голос

Посмотрите ТУТ я сам писал эту статью - переносить все информацию сюда слишком заморочно.
Не совсем понятно что там еще происходит в Вашем коде кроме обмена данными. Самый простой способ проверять состояние SS в Loop и обнулять счетчик там (если временные интервалы позволяют). Если массив фиксированный обнулять - когда пришли все байты непосредственно в самой процедуре прерывания. Вообщем много есть вариантов решения - какой именно подойдет Вам не ясно. Насколько мне известно какое-либо событие при падении SS c высокого сигнала на низкий в МК отсутствует - так что  прямого решения "в лоб" не существует.

(1.2 тыс. баллов) 6 26 51
А можно ли сделать прерывание в прерывании, допустим прерывание по SS на D2  и внутри прерывание по SPI?
Так сделать можно, но не нужно, т.к. можно потерять контроль над прерываниями и получить срыв стека.
Добро пожаловать на Бредборд! Сайт вопросов и ответов на тему Arduino, Raspberry Pi и хоббийной электроники в целом. Цель Бредборда — быть максимально полезным. Поэтому мы строго следим за соблюдением правил, боремся с холиворами и оффтопиком.

    За этот месяц ещё никого.

    ...