Форум myROBOT.ru » Лаборатория » Электронная мастерская » SPI протокол

Страниц (2): [1] 2 »
 

1. mctim - 02 Января, 2010 - 22:21:34 - перейти к сообщению
Привет!

Хочу соединить чип памяти с МК через SPI.
Поскольку опыта работы с МК мало, с SPI вообще нет и немного умею в Proteus - решил сначала разобраться с протоколом SPI с помошью AVRStudio(C) и ISIS Proteus.
Взял ATmega8 и SPI Debugger. Пытаюсь передать и считать байт.
Вот написал функции:
CODE:

#define TRYES 16 // количество попыток
void SPI_init()
{
SPCR = 0b11010000;
// включить SPI
// режим MASTER
// разрешить прерывания от модуля SPI
// делитель скорости - 4
// полярность +
// фаза - по наростающему фронту
}
unsigned char SPI_WriteByte(unsigned char byte)
{
unsigned char ntry = 0;
while(1)
{
if(ntry >= TRYES)
return 0; // ошибка
if((SPSR & 0b10000000) == 0b00000000) // если модуль SPI свободен
SPDR = byte;
else
{
ntry++;
continue;
}
if((SPSR & 0b01000000) == 0b00000000) // если небыло конфликта записи
while((SPSR & 0b10000000) == 0b10000000) // пока не кончится передача
{}
else
{
ntry++;
continue;
}
break;
}
return 1;
}
unsigned char SPI_ReadByte(unsigned char *byte)
{
unsigned char ntry = 0;
while(1)
{
if(ntry >= TRYES)
return 0; // ошибка
if((SPSR & 0b10000000) == 0b00000000) // если модуль SPI занят(предполагается что он ожидает чтения байта)
*byte = SPDR;
else
{
ntry++;
continue;
}
if((SPSR & 0b01000000) == 0b00000000) // если небыло конфликта записи
break;
else
{
ntry++;
continue;
}
}
return 1;
}

Собрал схему:

пытаюсь чтот там писать читать, а вылазит такой сигнал

Подозрительные значения напряжения получаются.
И не разберу как настроить SPI Debugger чтоб он показывал что принимает и передавал что укажу.

Помогите пожалуйста, знатоки.
2. nest - 02 Января, 2010 - 22:33:46 - перейти к сообщению
всегда. всё. нужно. делать . в. железе.
3. mctim - 03 Января, 2010 - 13:49:30 - перейти к сообщению
Если сделаю в железе получится слишком много неизвестных.
Я не уверен в том что команды по SPI передаются правильно и не уверен что вообще правильные команды пытаюсь передать( у AT25F сложная для меня система команд).
Поэтому хочу сначала освоить SPI.

Да и в железе оно есть. Не работает конечно Подмигивающий , и нечем заглянуть внутрь. А вот в Proteus-е есть возможность разгуляться: смотреть память устройств, подключать осциллоскоп и пр.

Самое главное забыл: я только начал подыматься с уровня плинтуса поэтому опыта и знаний мало. От и прошу помощи Подмигивающий
4. nest - 03 Января, 2010 - 14:39:42 - перейти к сообщению
так SPI можно проверить тремя светодиодами, только скорость будет маленькая.
а так - убивать время на отлов глюков протеуса никто не мешает : )
5. mctim - 03 Января, 2010 - 15:24:15 - перейти к сообщению
Замешательство метода такого не знаю я ...
Посвятите пожалуйста.

Там наверно светодиоды мигать будут.
Как раз новогодний метод.
6. nest - 03 Января, 2010 - 16:12:58 - перейти к сообщению
если делать всё "руками" то можно отдельные ноги дёргать и смотреть на светодиоды, как байт в(ы)двигается.

посмотрите как сделано на дискретных микросхемах регистров последовательной загрузки:



грубо приблизительно так:
CODE:
$количество_битов=8;
while ($количество_битов>0){
- выставили бит на MOSI
- подали фронт на SCK (я не помню, какой там нужен, то ли передний то ли задний)
- (при этом бит с MOSI записался внутрь регистра и регистр сдвинул его на один)
$количество_битов=$количество_битов-1;
}


тут можно вставить задержку хоть длиной в минуты, и следить за битиками по светодиодам.
Правда я не знаю, как там скорость в аппаратном SPI можно помедленнее загнать (а копать - лень).


Если делать нечего - так можно весь микроконтроллер только лишь тремя кнопками запрограммировать без другой электроники : ) (хотя один RS-триггер лучше всё таки поставить)
7. mctim - 03 Января, 2010 - 18:45:18 - перейти к сообщению
В настройках SPI можно задать делитель частоты 4, 16, 64, 128. Получается минимальная частота, которую я могу поставить, 1МГц/128=7812,5Гц. Великовато чтоб заметить мигание светодиода на выходах SPI МК...
Если использовать регистры - это еще 1 неизвестная. Увеличивают только шансы на мою ошибку.
А вобщем при включении SPI и постоянной передаче любых данных меняется напряжение на выходе МК Chip Select, а на других(отвечающих за SPI) - ничего не меняется.
В документации не конкретно так написано как пользоваться модулем SPI. Похоже я неверно функции написал. Пример бы...

__
Описал результаты опытов на железе.
8. nest - 03 Января, 2010 - 19:16:41 - перейти к сообщению
mctim пишет:
В настройках SPI можно задать делитель частоты 4, 16, 64, 128. Получается минимальная частота, которую я могу поставить, 1МГц/128=7812,5Гц

а вы тактирование всего МК заведите от 10 Гц внешнего генератора.
Немного нетрадиционно, зато интересно.

Примеры посмотрите на сайте Atmel .
AVR107: Interfacing AVR serial memories (22 pages, revision A, updated 03/05)
This application note describes the functionality and the architecture of SPI serial memories drivers as well as the motivation of the selected solution.

AVR151: Setup and use of the SPI (15 pages, revision C, updated 7/08)
This application note describes how to setup and use the on-chip Serial Peripheral Interface (SPI) of the AVR microcontrollers.

AVR319: Using the USI module for SPI communication (8 pages, revision A, updated 09/04)
This application note describes a SPI interface implementation, in form of a fullfeatured driver and an example of usage for this driver.

AVR320: Software SPI Master
9. mctim - 05 Января, 2010 - 18:59:39 - перейти к сообщению
Улыбка примеры - то что надо. Написал функцию отправки байта. В ней странный баг выходит.
вот функция:
CODE:

unsigned char SPI_WriteByte(unsigned char byte)
{
unsigned char ntry = 0;
while(1)
{
SPI_Enable;
if(ntry >= TRYES)
{
SPI_Disable;
return 0; // ошибка
}
if((SPSR & 0b10000000) == 0b00000000) // если модуль SPI свободен
SPDR = byte;
else
{
SPI_Disable;
ntry++;
continue;
}
if((SPSR & 0b01000000) == 0b00000000) // если небыло конфликта записи
{
while(1) // пока не кончится передача
{
cli();
if(SPI_Interrapt == 0x01)
{
break;
}
sei();
_delay_us(16);
}
}
else
{
SPI_Disable;
ntry++;
continue;
}
SPI_Interrapt = 0;
break;
}
SPI_Disable;
return 1;
}

SPI_Interrapt выставляю в 1 в обработчике прерываний от SPI.
Так вот, в чем баг: программа не двигается дальше цикла "while(1) // пока не кончится передача". Хотя в симуляторе тикал пошагово и SPI_Interrapt выставляется в 1, а дальше симулятор зависает(при выходе из обработчика прерываний получается).

Мудрил ужа по-всякому. Замешательство
(Добавление)
SPI_Enable(Dissable) - команды включения(выключения) модуля SPI(как в аппнотах делаю Подмигивающий )
10. mctim - 08 Января, 2010 - 15:38:38 - перейти к сообщению
Думаю это грех компилятора!
С нулевой оптимизацией функция работает.
Мне нужно оптимизировать по размеру поэтому написал некоторые части кода на ассемблере.
Обработчик прерывания от SPI:
CODE:

ISR(SIG_SPI)
{
asm("sbr r20,1"); // выставляем r20 в 1
}

Проверка получения прерывания в функции:
CODE:

asm("Wait_Transmit:");
// Ожидание завершения передачи данных
asm("sbrc r20,0");
asm("rjmp Go_Further"); // идем дальше
asm("rjmp Wait_Transmit"); // ждем установки r20 в 1
asm("Go_Further:");

Буду рад справедливой критике.
11. nest - 08 Января, 2010 - 15:49:48 - перейти к сообщению
mctim, а компилятор потом где нибудь этот R20 не "запорет" ?
В этом голом коде то оно, может, и работает, а когда что то ещё добавить - кто его знает, что там компилятор с R20 натворит.
Наверняка как то можно в СИ запретить или ограничить использование R20.

А! то есть код тупо ждёт, пока не окончится передача ?
а там разве нету прерывания "передача закончена" ?
mctim пишет:
Мне нужно оптимизировать по размеру
нужно сразу полностью на асм переходить :)
Пару раз заглядывал в откомпилённую прошивку после СИ - тихий ужас, как с точки зрения объёма, так с точки зрения и скорости выполнения
12. mctim - 08 Января, 2010 - 22:50:33 - перейти к сообщению
nest пишет:
а компилятор потом где нибудь этот R20 не "запорет" ?

вполне возможно, не знаю как иначе сделать.
nest пишет:
то есть код тупо ждёт, пока не окончится передача ?

да
nest пишет:
а там разве нету прерывания "передача закончена" ?

есть конечно, вот даже есть код
CODE:

Wait_Transmit:
; Ожидание завершения передачи данных
sbis SPSR,SPIF
rjmp Wait_Transmit

компилятор только материться на SPSR, SPIF.
Пытался их определить с помошью .def SPSR = r0x2E но компилятор материться на команду .def Грустный
nest пишет:
нужно сразу полностью на асм переходить Улыбка

Cи знал поэтому начал программить на нем. Согласен что ассемблер знать нужно. Вот осваиваюсь в нем потихоньку.
13. nest - 09 Января, 2010 - 01:34:32 - перейти к сообщению
а там разве нету прерывания "передача закончена" ?
я имел ввиду это прерывание : "SPI, STC - Serial Transfer Complete". сюда вываливается, когда всё отправили.
14. mctim - 09 Января, 2010 - 16:12:36 - перейти к сообщению
Судя по всему это оно и есть. По окончанию передачи бит SPIF в регистре SPSR устанавливается в 1 или выполняется обработчик прерывания и бит устанавливается в 1.
15. mctim - 10 Января, 2010 - 13:20:00 - перейти к сообщению
Хм. Зациклил МК на постоянную передачу байта и чтение.
На входе SI микросхемы напряжение 1,5 В(и меняется пропорционально количеству единиц в передаваемом байте), на SO - 0 В, на CS - 2,5.
Похоже что МК передает всетаки информацию.
У меня в связи с этим вопрос: как проверить рабочая или нет моя микросхемка AT25F1024?
Я её вообще из сгоревшей видеокарты выпоял :)

_____
В ISIS Proteus мой код читает ID микросхемы, а в железе не хочет. (правда не разобрался почему больше ничего считать не удается)