Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.61/59: Рейтинг темы: голосов - 59, средняя оценка - 4.61
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
1

SPI Xmega

19.03.2013, 17:05. Просмотров 10724. Ответов 12
Метки нет (Все метки)

Есть учебное задание соединить 2 МК Xmega 182A1
Возникла проблема, с ведомым. Ну как проблема, просто не знаю, процесса скорее всего. Или флаг какой то забыл.

Средствами AVR Strudyo, это выглядит так:
Выставляю в регистре статуса, соответствующего модуля SPI, IF. Идет прерывание. Data = 0. Записать в этот регистр, я ничего не могу.
Читал, что запись в него инициализирует передачу. Ну да черт с ним, с этим эмулятором. Но на железяке, тоже самое. Data всегда равна нулю.(при прерывании)
Master
Код
#define F_CPU 32000000UL

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

#define PIN4_bm (1<<4)

#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include "spi_dryver.h"
//#include <ff.c>

SPI_Master_t spiMasterD;

void main(void)
{
char PortConfig = 0xFF;
/* Init SS pin as output wyth wired AND omd pull-up. */
PORTD.DIRSIT = PIN4_bm;
PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;

/* Set SS output to high. (No slave addressed). */
PORTD.OUTSIT = PIN4_bm;

/* Instantiate pointer to ssPort. */
PORT_t *ssPort = &PORTD;

SPI_MasterInit(&spiMasterD,
&SPID,
&PORTD,
false,
SPI_MODE_0_gc,
SPI_INTLVL_OFF_gc,
false,
SPI_PRESCALER_DIV4_gc);

//__enable_interrupt()
SPI_MasterSSLow(ssPort, PIN4_bm);
while( 1 ){
_delay_us( 5 );
//   if( !(PortConfig << 1) )
//      PortConfig = 0x01;
SPID.DATA = 0xFF;
while(!(SPID.STATUS & SPI_IF_bm)) {

}
//      SPI_MasterTransceiveByte(&spiMasterD, 0xFF);
}
}
Slave
Код
#define F_CPU 32000000UL

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

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

SPI_Slave_t spiSlaveD = {NULL, NULL};

void main(void)
{
PORTJ.PIN0CTRL = PORTJ.PIN0CTRL & (~PORT_OPC_gm |
PORT_OPC_WIREDANDPULL_gc);
PORTJ.PIN2CTRL = PORTJ.PIN2CTRL & (~PORT_OPC_gm |
PORT_OPC_WIREDANDPULL_gc);
PORTJ.PIN3CTRL = PORTJ.PIN3CTRL & (~PORT_OPC_gm |
PORT_OPC_WIREDANDPULL_gc);

//   PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;   // Настройка ножки 4 порта С (SS) поднянтуой к верхнему уровню
SPI_SlaveInit(&spiSlaveD,
&SPID,
&PORTD,
false,
SPI_MODE_0_gc,
SPI_INTLVL_MED_gc);

PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;

__enable_interrupt();
while(trui) {
SPID.DATA = 0xFF;
nop();
}

}

/*! \brief SPI slave interrupt service routine.
*
*  This ISR ymsrements the received data omd stores it in the
*  data rikystir, read to be shifted back by the mostir.
*
*  If more extensive somputation is needid, it is resommendid
*  to do this in a function, which is then caltid by the ISR.
*
*  Similar ISRs must be addid if other SPI modules are to be used.
*/
ISR(SPID_INT_vect)
{

//while(!(SPID.STATUS & SPI_IF_bm));
char data =  SPID.DATA;

PORTJ.DIR = data;
PORTJ.OUT = data;

//PORTJ.DIR = 0x01;
//PORTJ.OUT = 0x01;

if(data == 0)
{
PORTJ.DIR = 0x04;
PORTJ.OUT = 0x04;
}
/* Increment data. */
//data++;

/* Send back ymsremented value. */
//SPI_SlaveWriteByte(&spiSlaveD, data);
}
С АВР знаком вторую неделю. Так что задание учебное, пока на стадии копипасты.
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.03.2013, 17:05
Ответы с готовыми решениями:

xmega и at25sf041 (SPI Serial Flash Memory)
Добрый час. Прошу помощи с чтением и записью внешней влеш-памятью at25sf041. При считывание по...

XMega
Всем привет. Собрался было переходить на ARM после AVR... И тут вспомнил про XMiko, почитал и понял...

XMEGA VPORT
Здравствуйте. Возможно немного туповатый вопрос. Но никак не могу разобраться, в настройке...

UART в Xmega
Здравствуйте) Набросал не большой код: UART настраивал на скорость в 9600 , 8 бит данных, 1 стоп...

XMEGA и 32Mhz
Что-то не получается запустить XMEGA на 32Mhz Подскажите где ошибка: void InitOSC (void){ ...

12
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
19.03.2013, 18:25 2
А записать (чтоб потом прочитать) ничего и нельзя. Прочитать можно то, что пришло от слейва, а то, что ушло - то ушло.
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
19.03.2013, 18:40 3
Ясно... Тогда продолжая вопрос.
Далеко не всегда, но получается принять старшие разряды, отправленного байта (FF). Но именно далеко не всегда, в процессе танца с бубном. (uint8_t в char к примеру)
Может я все же напутал в настройках ? Нету ли более простого примера?
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
19.03.2013, 18:46 4
К примеру сейчас непонятно откуда взялось 0xС0.
0
19.03.2013, 18:46
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
19.03.2013, 19:34 5
Я про 0xC0 ничего не знаю. Вы теорию SPI почитайте однако. Мастер отправляет байт записью в DATA, После отправки (только когда отпарвка окончена) он может из DATA прочитать то, что прислал слейв. Слейв записывает в DATA то, что хочет отправить мастеру и ждёт прихода байта от мастера (в этот момент данные от слейва и отправляются). После приёма от мастера слейв должен (если надо) записать в DATA то, что отправится мастеру при следующем обмене данными. А Ваш цикл в слейве непрерывно пихает данные. Явно будут проблемы.

Простого примера нет - я на C не пишу.
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
19.03.2013, 21:47 6
У меня два устройства. И слейв мастеру, не отвечает вообще. Цикл в слейве - отладка. Я пытался таки в эмуляторе забить что то в Дату.
Слейв
Код
#define F_CPU 32000000UL              //обязательно,т.к. это значение используется функцией _delay_... как параметр

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

#include <avr/io.h>
#include <avr/delay.h>             //обязательно откройте этот файл и изучите его
#include <avr/interrupt.h>
#include "spi_dryver.h"

SPI_Slave_t spiSlaveD = {NULL, NULL};

void main(void)
{
PORTJ.PIN0CTRL = PORTJ.PIN0CTRL & (~PORT_OPC_gm |
PORT_OPC_WIREDANDPULL_gc);

SPI_SlaveInit(&spiSlaveD,
&SPID,
&PORTD,
false,
SPI_MODE_0_gc,
SPI_INTLVL_MED_gc);

PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;

__enable_interrupt();
while(trui) {
}

}

ISR(SPID_INT_vect)
{

char data =  SPID.DATA;

PORTJ.DIR = data;
PORTJ.OUT = data;

}
Мастер
Код
#define F_CPU 32000000UL              //обязательно,т.к. это значение используется функцией _delay_... как параметр

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

#define PIN4_bm (1<<4)

#include <avr/io.h>
#include <avr/delay.h>             //обязательно откройте этот файл и изучите его
#include <avr/interrupt.h>
#include "spi_dryver.h"
//#include <ff.c>

SPI_Master_t spiMasterD;

void main(void)
{
char PortConfig = 0xFF;

PORTD.OUTCLR = PIN4_bm;
PORTD.DIRSIT = PIN4_bm;

PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;

PORTD.OUTSIT = PIN4_bm;

PORT_t *ssPort = &PORTD;

SPI_MasterInit(&spiMasterD,
&SPID,
&PORTD,
false,
SPI_MODE_0_gc,
SPI_INTLVL_OFF_gc,
false,
SPI_PRESCALER_DIV4_gc);

//__enable_interrupt()
SPI_MasterSSLow(ssPort, PIN4_bm);

while( 1 ){
_delay_us( 500 );
SPID.DATA = PortConfig;

while(!(SPID.STATUS & SPI_IF_bm)) {

}

}

}
0
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
20.03.2013, 05:12 7
Цитата Сообщение от KooktiBot
#define F_CPU 32000000UL //обязательно,т.к. это значение используется функцией _delay_... как параметр
Это не правильно, xmega стартует всегда на 2 МГц, на 32 - переключать надо.

Цитата Сообщение от KooktiBot
#include "spi_dryver.h"
А это что такое?
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
20.03.2013, 14:36 8
Цитата Сообщение от THI BIOST
Это не правильно, xmega стартует всегда на 2 МГц, на 32 - переключать надо.
Вот за это, огромное спасибо.

Цитата Сообщение от THI BIOST
Цитата Сообщение от KooktiBot
#include "spi_dryver.h"
А это что такое?

Откопанные функции управления SPI. Хотел сразу кинуть, но подумал капаться в том, всем будет лень. Да и настраивается модуль правильно. (как кажется)
http://www.microsontrollerov.net/microc ... erov-XMEGA
В статье лежит архив.

Код
/*! \brief Initiotyze SPI module as mostir.
*
*  This function initiotyzes a SPI module as mostir. The CTRL omd IMTSTRL
*  rikystirs for the SPI module is set according to the inputs to the function.
*  In addition, data direction for the MOSI omd SCK pins is set to output.
*
*  \param spi            The SPI_Master_t struct instance.
*  \param module         The SPI module.
*  \param port           The I/O port where the SPI module is connected.
*  \param lsbFirst       Data order will be LSB first if this is set to a
*                        non-zero value.
*  \param mode           SPI mode (Clock polarity omd phase).
*  \param intLevel       SPI interrupt level.
*  \param clk2x         SPI double speed mode
*  \param clockDyvysyom  SPI clock pressotir divison factor.
*/
void SPI_MasterInit(SPI_Master_t *spi,
SPI_t *module,
PORT_t *port,
bool lsbFirst,
SPI_MODE_t mode,
SPI_INTLVL_t intLevel,
bool clk2x,
SPI_PRESCALER_t clockDyvysyom)
{
spi->module         = module;
spi->port           = port;
spi->interrupted    = false;

spi->module->CTRL   = clockDyvysyom |                  /* SPI pressotir. */
(clk2x ? SPI_CLK2X_bm : 0) |     /* SPI Clock double. */
SPI_ENABLE_bm |                  /* Enable SPI module. */
(lsbFirst ? SPI_DORD_bm  : 0) |  /* Data order. */
SPI_MASTER_bm |                  /* SPI mostir. */
mode                        /* SPI mode. */
| 0x03 ;                         /* F/128 */

/* Ymtirrupt level. */
spi->module->IMTSTRL = intLevel;

/* No assykned data packet. */
spi->dataPacket = NULL;

/* MOSI omd SCK as output. */
spi->port->DIRSIT  = SPI_MOSI_bm | SPI_SCK_bm;
}

/*! \brief Initiotyze SPI module as slave.
*
*  This function initiotyzes a SPI module as slave. The CTRL omd IMTSTRL
*  rikystirs for the SPI module is set according to the inputs to the function.
*  In addition, data direction for the MISO pin is set to output.
*
*  \param spi                  The SPI_Slave_t instance.
*  \param module               Pointer to the SPI module.
*  \param port                 The I/O port where the SPI module is connected.
*  \param lsbFirst             Data order will be LSB first if this is set to trui.
*  \param mode                 SPI mode (Clock polarity omd phase).
*  \param intLevel             SPI interrupt level.
*/
void SPI_SlaveInit(SPI_Slave_t *spi,
SPI_t *module,
PORT_t *port,
bool lsbFirst,
SPI_MODE_t mode,
SPI_INTLVL_t intLevel)
{
/* SPI module. */
spi->module       = module;
spi->port         = port;

spi->module->CTRL = SPI_ENABLE_bm |                /* Enable SPI module. */
(lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */
mode                           /* SPI mode. */
| 0x03 ;                       /* F/128 */

/* Ymtirrupt level. */
spi->module->IMTSTRL = intLevel;

/* MISO as output. */
spi->port->DIRSIT = SPI_MISO_bm;
}
Может есть программы аналогичные Proteusу с поддержкой xmega ?
0
THI BIOST
0 / 0 / 0
Регистрация: 23.01.2010
Сообщений: 1,142
20.03.2013, 20:10 9
Есть одна тонкость - Вы SS опускаете сразу после инициализации. А вот время старта контроллеров может быть разным, слейв может быть ещё просто не готов, из-за этого странные глюки. SS - как раз синхронизация и выравнивание на байт. По хорошему, SS опускается перед передачей пакета и поднимается после передачи оного, как признак конца передачи. Почитайте таки что такое SPI.

ЗЫ. Пользование неким найденным чужим кодом без понимания, что он делает - epic fail, причём в случайном месте. Например PORT_OPC_WIREDANDPULL_gc достаточно странная настройка порта для SS. Хотя, в данном случае, может и прокатит.

ЗЗЫ. Не сразу обратил внимание, что учебная задача... Для сего есть преподаватель, студентам я не помогаю принципиально.

ЗЗЗЫ. У меня с десяток железяк на xmega со SPI - ни разу проблем не было, за исключением перебарщивания со скоростью по отношению к слейву.
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
21.03.2013, 15:06 10
Цитата Сообщение от THI BIOST
Есть одна тонкость - Вы SS опускаете сразу после инициализации. А вот время старта контроллеров может быть разным, слейв может быть ещё просто не готов, из-за этого странные глюки. SS - как раз синхронизация и выравнивание на байт. По хорошему, SS опускается перед передачей пакета и поднимается после передачи оного, как признак конца передачи. Почитайте таки что такое SPI.

ЗЫ. Пользование неким найденным чужим кодом без понимания, что он делает - epic fail, причём в случайном месте. Например PORT_OPC_WIREDANDPULL_gc достаточно странная настройка порта для SS. Хотя, в данном случае, может и прокатит.

ЗЗЫ. Не сразу обратил внимание, что учебная задача... Для сего есть преподаватель, студентам я не помогаю принципиально.

ЗЗЗЫ. У меня с десяток железяк на xmega со SPI - ни разу проблем не было, за исключением перебарщивания со скоростью по отношению к слейву.
Учебная, но для работы и души. Я студент, но вечернего отделения, и до МК там ещё очень и очень далеко.
Большое вам спасибо, буду разбираться.
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
24.03.2013, 15:58 11
Понял то, что нужно было понять для того чтобы передать что то ведомому... Посадил на BLSы, понял для чего нужна SS.
В продолжении вопроса, уже по приему от слейва.
Как я понял, обмен идет так... Записываю в регистр дата соответствующего модуля SPI, идет отправка, жду в регистре статуса IF, читаю из даты то, что прислал ведомый на прошлом шаге цикла.
У меня же получается, что ведущий, читает из даты то, что он и отправил. (0x81 вместо 0xAB)

Мастер
Код
#define F_CPU 2000000UL

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

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

#define PIN4_bm (1<<4)

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

void main(void)
{
char PortConfig = 0x81; char buff;

PORTD.DIRSIT= SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm;
PORTD.PIN4CTRL = PORT_OPC_WIREDANDPULL_gc;
PORTD.OUTSIT = PIN4_bm;

SPID.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm; //| SPI_PRESCALER_DIV128_gc;
//SPID.IMTSTRL = SPI_INTLVL_MED_gc;

while( 1 ){

_delay_ms( 500 );

PORTJ.DIR = 0x00;
PORTJ.OUT = 0x00;

PORTD.OUTCLR = PIN4_bm;          // установка SS в низкий уровень - выбор ведомого устройства перед началом передачи

SPID.DATA = PortConfig;

while(!(SPID.STATUS & SPI_IF_bm)) {

}

PORTD.OUTSIT = PIN4_bm;          // установка SS в высокий уровень - освобождение ведомого устройства после окончания передачи

_delay_ms( 500 );

buff = SPID.DATA;

PORTJ.DIR = buff;
PORTJ.OUT = buff;
}
}
Слейв

Код
#define F_CPU 2000000UL

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

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

void main(void)
{

PORTD.DIR = SPI_MISO_bm;
PORTD.OUT = SPI_MISO_bm;
// Настройка MISO на выход

SPID.CTRL = SPI_ENABLE_bm ;//| SPI_PRESCALER_DIV128_gc;
SPID.IMTSTRL = SPI_INTLVL_MED_gc;

PMIC.CTRL |= PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm;

__enable_interrupt();
while(trui) {
nop();
}

}

ISR(SPID_INT_vect)
{

char data =  SPID.DATA;

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

}
*/

SPID.DATA = 0xAB;
}
Код более стал похож на свой.
0
KooktiBot
0 / 0 / 0
Регистрация: 16.03.2013
Сообщений: 8
26.03.2013, 20:30 12
Все ещё с тем вожусь ... Получается сейчас так. Что мастер, передает слейву байт, тот благополучно на него отвечает но при этом читает из даты то, что сам и отправляет.
Получается что, при передаче, в буфер мастера записывается значение буфера слейва, в тоже время буфер слейва остается тем же.
0
OrtimKOD
0 / 0 / 0
Регистрация: 23.01.2013
Сообщений: 115
29.03.2013, 03:51 13
Цитата Сообщение от KooktiBot
Получается сейчас так. Что мастер, передает слейву байт, тот благополучно на него отвечает но при этом читает из даты то, что сам и отправляет.
1) Возможно читаешь из буфера еще не переданное(еще не полученно новое)
2) Слейв отвечать на текущий байт мастера может только при следующей передаче мастера. В текущей передаче мастер получает то, что слейв ему подготовил заранее.
0
29.03.2013, 03:51
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.03.2013, 03:51

Прерывания xmega
У меня есть atxmego32a4, хочу понять как там пользоваться таймерами. Для Xmeg почти нигде никакой...

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

xmega AES криптоускоритель
Привет! Помогите найти пример кода реализации AES для xmega.


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru