SPI Xmega

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 3
Зарегистрирован: Вт мар 26, 2013 11:19:59

Сообщение Google__Bot »

Есть учебная (в смысле рабочая, но в общем то учебная) связать 2 МК XMEGA128A1
И вот стоят у меня на столе 2 отладочные платы, Ready For Xmega
Долго над этим парюсь. Одна мысль о BLS'ах, доходила ...... Ну в общем может кто нибудь и прослезился, к сути.

Мастер успешно отправляет байт слейву, который успешно его принимает, если при этом не отвечает.
Т.e. Вопрос заключается в том, как правильно реализовать ответ мастеру от слейва?

Код. *Из которого выкинута вся шелуха, связанная с самой задачей.
*На ногах 0x01/0x02 портов J, соответственно зеленый и красный светодиоды.



Мастер
Спойлер

Код: Выделить всё

#define F_CPU 2000000UL              

#define PIN4_bm (1<<4) 

#include <avr/io.h>
#include <avr/delay.h>           
#include <avr/interrupt.h> 

#define SPI_SS_bm             0x10 
#define SPI_MOSI_bm           0x20 
#define SPI_MISO_bm           0x40 
#define SPI_SCK_bm            0x80 

int main(void)
{	
unsigned char buff;

 	PORTD.DIRSET= SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm;        
	PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;   
	PORTD.OUTSET = PIN4_bm;
	
	SPID.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_PRESCALER_DIV128_gc; 
	//SPID.INTCTRL = SPI_INTLVL_MED_gc;
	
	PORTD.OUTCLR = PIN4_bm;  
	SPID.DATA = 0x01;
        while(!(SPID.STATUS & (1<<SPI_IF_bp)));
	PORTD.OUTSET = PIN4_bm; 
	
	while( 1 ){
		
		
		_delay_ms( 500 );
		PORTD.OUTCLR = PIN4_bm;  // установка SS в низкий уровень - выбор ведомого устройства перед началом передачи  
		buff = SPID.DATA;
		
		if(buff == 0x10)
			{
			PORTJ.DIR = 0x01;
			PORTJ.OUT = 0x01;
			}
		else
			{
			PORTJ.DIR = 0x02;
			PORTJ.OUT = 0x02;
			}

		SPID.DATA = 0x01;	

		while(!(SPID.STATUS & (1<<SPI_IF_bp)));
		
		
		PORTD.OUTSET = PIN4_bm;          // установка SS в высокий уровень - освобождение ведомого устройства после окончания передачи
		
		_delay_ms( 500 );
	}
return(0);
}
Слейв.
Спойлер

Код: Выделить всё

#define F_CPU 2000000UL
          

#define __enable_interrupt()  sei();
#define __disable_interrupt() cli();


#include <avr/io.h>
#include <avr/delay.h>             
#include <avr/interrupt.h>

#define SPI_SS_bm             0x10 
#define SPI_MOSI_bm           0x20 
#define SPI_MISO_bm           0x40 
#define SPI_SCK_bm            0x80 


void main(void)
{


   PORTD.DIRSET = SPI_MISO_bm; 
            // Настройка MISO на выход
   
   SPID.CTRL = SPI_ENABLE_bm; //| SPI_PRESCALER_DIV128_gc; 
   SPID.INTCTRL = SPI_INTLVL_MED_gc;

   PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;

   __enable_interrupt();
      while( 1 ) {
      }

}

ISR(SPID_INT_vect)
{

   char data =  SPID.DATA;
 

	if(data == 0x01)
		{
		PORTJ.DIR = 0x01;
		PORTJ.OUT = 0x01;
		SPID.DATA = 0x10;
		}
		else 
		{
		
		PORTJ.DIR = 0x02;
		PORTJ.OUT = 0x02;
		}
		
}


*Вожусь с этим 2-ю неделю, в общем то столько же знаком с МК. Так что вопрос скорее по основам.
**То что там происходит по моему мнению:

Мастер отправляет первый байт. Слейв его принимает, интерпретирует и отправляет ответ. Мастер в начале основного цикла, принимает ответ на первый байт, выставляет статус и понеслась .....

И соответственно. Мастер не принимает правильный байт от слейва, а слейв принимает правильный байт от мастера, раз этак в 10 циклов.

Долгое время наблюдал то, что мастер читает из буфера то, что сам посылает.

*С контактами уж точно проблем быть не может. Намаявшись я припаял и bls'ы.
Реклама
Родился
Сообщения: 3
Зарегистрирован: Вт мар 26, 2013 11:19:59

Сообщение Google__Bot »

Народ, тема очень актуальна. :shock:
Реклама
Родился
Сообщения: 3
Зарегистрирован: Вт мар 26, 2013 11:19:59

Сообщение Google__Bot »

Получается что, при передаче, в буфер мастера записывается значение буфера слейва, в тоже время буфер слейва остается тем же.
Родился
Сообщения: 10
Зарегистрирован: Ср ноя 24, 2010 12:44:54
Откуда: Одесса

Сообщение ur5fia »

У каждого имеются по 2 буфера - буфер приема и буфер передачи.
В вашем варианте тактирует ведущий всегда., но при тактировании, данные "переливаются из буфера передачи ведущего в буфер приема ведомого и обратно ОДНОВРЕМЕННО!!!". Для приема ответа ведущий должен сделать холостую передачу, либо вести прием одновременно с передачей. Но если ведомый не успеет положить свои данные в свой буфер для передачи - ведущий приймет ерунду. Нужно либо выждать время для приема, либо ждать сигнала готовности передачи.
т.е Вы должны через время, или по дрыгу ногой (что хочет передать) ведомого, сделать холостую передачу ведущим. при этом в буфере приема ведущего окажется принятый байт. переданный байт может быть игнорирован( если не нужен).
Более красиво организовывается при помощи ноги SS., но здесь есть свои камни. Вывод SS конфигурируется как вход. Тогда низкий уровень переводит микроконтроллер в качестве ведомого, после передачи устанавливаем 1. Таким образом, когда хочет чего передать - ведущий, иначе - ведомый.
Камни будут когда оба захотят передать, тогда передавать будет тот кто раньше начал, а данные другого будут потеряны. Нужно проверить , не установлен ли вход SS в 0,
и только если нет отсылать в буфер передачи.
Реклама
Эиком - электронные компоненты и радиодетали
Ответить

Вернуться в «AVR»