Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SPI SLAVE в C8051F310
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > MCS51
evg123
Помогите плз.

Никак не могу настроить режим SLAVE в ентом контроллере.
Непонятен следующие моменты при работе с прерыванием:
- как определить первый байт в пакете
- или (вытекает из первог), как определить момент выбора ведомого (т.е. момент перепада с 1 в 0 входа SS) и его отключения (момент перепада с 0 в 1 входа SS).

Заранее благодарю help.gif
mihask
Цитата(evg123 @ Jan 23 2007, 21:55) *
Помогите плз.

Никак не могу настроить режим SLAVE в ентом контроллере.
Непонятен следующие моменты при работе с прерыванием:
- как определить первый байт в пакете
- или (вытекает из первог), как определить момент выбора ведомого (т.е. момент перепада с 1 в 0 входа SS) и его отключения (момент перепада с 0 в 1 входа SS).

Заранее благодарю help.gif


У меня был проект, в котором необходимо было связать два проц-а по SPI (ведущий С8051F040, ведомый С8051F023).
Вот часть кода ведомого (С8051F023), отвечающая за настройку модуля SPI и передачу данных ведущему (C8051F040).
Думаю, что модуль SPI один и тот же во всей линейке 51-ых у Cygnal.

Каждый принятый байт по SPI генерирует прерывание SPI_isr.

/*----------------------------------------------------------------
* SPI Configuration
*----------------------------------------------------------------
*/
SPI0CN = 0x00; // Выключаем модуль SPI, сбрасываем все флаги.
SPI0CFG = 0x07; // Задаём конфигурацию модуля.
SPI0CKR = 0x0C; // Задаём тактовую частоту модуля SPI (должна совпадать с ведущим).
SPI0CN |= 0x01; // Включаем модуль SPI.

EIE1 |= (1 << 0); // Разрешаем прерывания модулю SPI



/*------------------------------------------------------------------------------
* Обработка прерывания модуля SPI.
* Данные (tbufSPI []) передаются от slave-а к master-у.
*------------------------------------------------------------------------------
*/
void SPI_isr (void) interrupt 6 using 2
{
EA = 0;
if (SPIF)
{
SPIF = 0;

if (tSPI_in != tSPI_out)
{
CheckSum = CheckSum ^ tbufSPI [tSPI_out];
SPI0DAT = tbufSPI [tSPI_out++];
}
else
{
SPI0DAT = CheckSum;
tSPI_in = 0;
tSPI_out = 0;
}
}
else
{
WCOL = 0;
MODF = 0;
RXOVRN = 0;
}
EA = 1;
}
evg123
Спасибо за помощь.


Вот как я реализовал Slave (если интересно):

// Формат запроса от Master - |Команда|Данные1|...|ДанныеN|

void Init_SPI0(byte speed)
{
IE |= 0x40;//SPI0 interrupt enable
IP |= 0x40;//SPI0 priority enable
XBR0 |= 0x02;//routed SPI to crossbar
SPI0CKR=speed; //max speed=0 ; min = 0xFF
SPI0CFG=_0b00010000;
SPI0CN= _0b00000101;
}

void SPI0_ISR (void) interrupt 6 using 2
{
static data char *p_buf;
static data char Rsv_N=0;
static data char N=0;

EA=0;
if(SPIF){
SPIF = 0;
if (N != Rsv_N){
//tmp=p_buf[Rsv_N]; //передача данных +
p_buf[N++]=SPI0DAT; //прием данных |
//SPI0DAT=tmp; // <-----+
}else{
//Прием первого байта и определение операции
switch(SPI0DAT)//Команды от мастера
{
case GET_KEY: //p_buf=&key;
SPI0DAT=key; //передача key
Rsv_N=0;
break;
case SET_HD: p_buf=Dis_Buf; //Загружаю адрес приемника
Rsv_N=SIZE_HD; //и его длину
break;
case SET_LED: p_buf=LED;
Rsv_N=SIZE_LED;
break;
case SET_BEEP: p_buf=bp.buf;
Rsv_N=SIZE_BEEP;
break;
default: p_buf=0;
Rsv_N=0;
break;
}
N=0;
//SPI0DAT=p_buf[N]; //передача данных
}

}else{
WCOL = 0;
MODF = 0;
RXOVRN = 0;
}
EA=1;
}

Все работает, только почемуто при ответе на запрос GET_KEY:

case GET_KEY: //p_buf=&key;
SPI0DAT=key; //передача key
Rsv_N=0;
break;

Master получает всегда 0x00, хотя значение key изменяется.

Не врубаюсь в чем дело. angry.gif
mihask
Может быть ошибка в том что мастер ожидает получения key после того как
мастер выдал запрос GET_KEY, а ведь на самом деле мастеру необходимо
выдать еще один запрос, чтобы значение key записанное слэйвом в SPIDAT
было переписано в регистр SPIDAT мастера (это принцип работы spi).
evg123
"ведь на самом деле мастеру необходимо выдать еще один запрос"

У меня так.

В принципе я добился работоспособности. Только перед передачей второго
байта (после GET_KEY) приходится выдерживать 24 такта. Только так и работает.
Такое ощущение что slave не успевает обработать запрос. Но с бругой стороны при
записи данных (например SET_HD) все работает без задердек. Глюки blink.gif
mihask
Цитата(evg123 @ Jan 26 2007, 19:49) *
"ведь на самом деле мастеру необходимо выдать еще один запрос"

У меня так.

В принципе я добился работоспособности. Только перед передачей второго
байта (после GET_KEY) приходится выдерживать 24 такта. Только так и работает.
Такое ощущение что slave не успевает обработать запрос. Но с бругой стороны при
записи данных (например SET_HD) все работает без задердек. Глюки blink.gif


Да у меня такое было когда я ADSP21992(master) скрещивал с Cygnal(slave), то же задержку
делал. Правда там у меня Cygnal как раз по записи (в него) и не успевал. smile.gif

Единственное что еще приходит на ум - я знаю что в Cygnal для того чтобы данные
записались необходимо, минимум на 4 такта помоему, убрать чип-селект микросхемы, с которой
общаешься по SPI, т.е если мастер записал в SPIDAT то в слэйве этот байт появится только
после того как мастер убрал чип-селект слэйва. Хотя конечно у тебя так и происходит иначе бы
запись не работала. smile.gif

А erratу на свой проц смотрел ?
mihask
И еще вдогонку smile.gif - После того как master записал байт в SPIDAT он должен дождаться SPIF
перед тем как пихать в SPIDAT следующий байт и еще перед записью в SPIDAT следующего
байта master должен прочитать байт из SPIDAT даже если он ему не нужен. То есть
в случае GET_KEY мастер должен после первого запроса прочитать байт из SPIDAT так же
как и после второго.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.