Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC1756+AT45DB081D
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Croman13n3c
Имеем связку из LPC1756 и AT45DB081D через блок SSP в режиме SPI.
Пытаюсь считать Manufacturer ID (opcode - 0x9f)
По приему в буфеер оказывается значение 0x1E 0x00 0x00 0x00 (должно быть 0x1F 0x25 0x00 0x00).
Посмотрев осцилом на линии на первый взгляд всё порядке : cs опущен, тактирование идет, опкод заносится и от at45 приходит 0x1E( вместо ожидаемого).
Может кто с таким уже сталкивался , в чём может быть причина такого поведения ?

Инициализация SSP в SPI Mode 0 (P0.15,16,17,18 -- CLK,!CS,MISO,MOSI )
CODE

DataFlashSSP_CFG.CPHA=SSP_CPHA_FIRST;
DataFlashSSP_CFG.CPOL=SSP_CPOL_LO;
DataFlashSSP_CFG.ClockRate=1000000;
DataFlashSSP_CFG.Mode=SSP_MASTER_MODE;
DataFlashSSP_CFG.FrameFormat=SSP_FRAME_SPI;
DataFlashSSP_CFG.Databit = SSP_DATABIT_8;
SSP_ConfigStructInit(&DataFlashSSP_CFG);
SSP_Init(LPC_SSP0, &DataFlashSSP_CFG);

CLKPWR_SetPCLKDiv(CLKPWR_PCLKSEL_SSP0, CLKPWR_PCLKSEL_CCLK_DIV_2);

SSP_Cmd(LPC_SSP0, ENABLE);

/* ждем пока освободится*/
while( LPC_SSP0->SR & SSP_SR_BSY ) { ; }

/* очистка FIFO */
while( LPC_SSP0->SR & SSP_SR_RNE ) {
volatile uint32_t dummy = LPC_SSP0->DR;
(void)dummy;


Чтение Manufacturer ID

CODE

CS(LOW):
delay_us(10);
LPC_SSP0->DR = 0x9f;
while (LPC_SSP0->SR & SSP_SR_BSY ) { ; }
rx_data=LPC_SSP0->DR;

for (i=0;i<4;i++)
{
LPC_SSP0->DR = 0xFF;
while (LPC_SSP0->SR & SSP_SR_BSY ) { ; }
buf[i] = LPC_SSP0->DR;
}
CS(HI);
delay_ms(1);

esaulenka
Вы бы написали, что эта чудо-библиотека делает в SSP_ConfigStructInit и SSP_Init.

И это... у меня всё работает :-) LPC1768, AT45DB161D.
Croman13n3c
SSP_ConfigStructInit и SSP_Init стандартные функции из nxp lpx17xx cmsis library.

SSP_ConfigStructInit - инициализирует поля структуры настроек SSP значениями по умолчанию.
SSP_Init - установка скорости, параметров из DataFlashSSP_CFG, подача питания и тактирования на модуль.

P.S 1 ошибка в моем коде - SSP_ConfigStructInit должна находится в начале первого блока с кодом.
P.P.S настройка в режим SPI Mode 3 ничего не дала (
esaulenka
Ну вот честное слово, лениво продираться через высосанные из пальца дефайны. Имхо, периферия на NXP документирована достаточно хорошо, чтобы не использовать ещё какие-то дополнительные библиотеки.

Например, неочевидно мне, что тут пишут в CR1. Надо прочитать Ваш исходник, заголовок драйвера и сам драйвер, и только потом смотреть в даташит.
Код
    tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
    // Write back to CR1
    SSPx->CR1 = tmp;


Рабочий код обмена с SPI:

Код
#define        SPI_REG(reg)    SSP1->reg

#define        SPI_WAIT_READY()                while (SPI_REG(SR) & SPI_SR_BUSY)


//    Процедура инициализации (возвращает код ошибки)
dword    SPI_Init(void)
{
    // устанавливается в стартапе: SSP1 on, PCLK = CCLK
    //PCONP |= BIT(10);
    //CLKSEL (PCLKSEL0, 1, 20);

    SPI_DISABLE_ALL_CHIP();

    SPI_REG(CPSR)    =    6;
    SPI_REG(CR0)    =    0x0007;
    SPI_REG(IMSC)    =    0x0;
    SPI_REG(DMACR)    =    0x0;
    SPI_REG(CR1)    =    0x2;

    while    (SPI_REG(SR) & SPI_SR_RNE)
        SPI_REG(DR);
    return 0;
}

//    Процедура запуска одного цикла работы
dword    SPI_Run    (dword    aSendByte)
{
    SPI_REG(DR)    =    aSendByte;
    SPI_WAIT_READY();
    return    SPI_REG(DR);
}


ChipSelect сконфигурирован как GPIO, остальные ноги - как SSP (в другом модуле, здесь не видно).
После перехода CS low->high рекомендую добавить несколько (я сделал десяток) nop'ов - у контроллера ноги весьма быстрые, память может не "почуствовать" деактивации. Хотя, как я вижу, уже есть delay_ms(1) - это слегка избыточно, но для проверки сойдёт.
Croman13n3c
Функция обмена по SPI была рабочая, проверил на другой плате ( подпаявшись на прямую, достал из загашника ).
Чувствую дело в инициализации работы самой памяти.

При старте делаю :

Код
delay_us(70); //power-up Vcc
CS(LOW);
delay_ms(20); //delay before write allowed
CS(HI);


CS как GPIO, остальные как SSP. Используется внутренняя подтяжка.
esaulenka
Ну работает же у меня! :-) Проверил ещё раз:
на 0xD7 возвращается 0xAC
на 0x9F возвращается 0x1F,0x26 (у меня объем памяти другой)

Единственное, что Вы не указали - реализация CS(HI) / CS(LOW). Может, тут ошибка?

Также, в теории, возможна дохлая микросхема. Проверяли на другой?
Croman13n3c
Проверял, тоже самое.
Различие в уровнях может вызывать такое поведение ( на отладочной плате пины с 3,3 В , а питание платки с dataflash 3 В) ?
Код
#define LOW 0
#define HI  1

void CS (uint8_t type)
{
   if (type)
     {
        GPIO_SetValue(0, (1 << 16)); // Set Value on PIN  - port num , pin  
     }
   else
     {
        GPIO_ClearValue(0, (1 << 16));
     }
}
esaulenka
Нет, ну не нравятся мне эти супер-библиотеки!
Вся эта супер-портабельная фигня заменяется ОДНОЙ строкой.
CODE

void GPIO_SetValue(uint8_t portNum, uint32_t bitValue)
{
LPC_GPIO_TypeDef *pGPIO = GPIO_GetPointer(portNum);

if (pGPIO != NULL) {
pGPIO->FIOSET = bitValue;
}
}

static LPC_GPIO_TypeDef *GPIO_GetPointer(uint8_t portNum)
{
LPC_GPIO_TypeDef *pGPIO = NULL;

switch (portNum) {
case 0:
pGPIO = LPC_GPIO0;
break;
case 1:
pGPIO = LPC_GPIO1;
break;
case 2:
pGPIO = LPC_GPIO2;
break;
case 3:
pGPIO = LPC_GPIO3;
break;
case 4:
pGPIO = LPC_GPIO4;
break;
default:
break;
}

return pGPIO;
}

Код
LPC_GPIO0->FIOSET = (1UL<<16);


По делу:
Описание того, что флеш и контроллер находятся на разных платах, я упустил...
Осталось только проверить, что земли одинаковые, и хорошо связанные.

О! И что ещё вспомнил!! Я ведь тоже м/с на "соплях" подвешивал! В даташите на эту флеш указано макс. время фронтов клока. Оно там не просто так указано, при превышении этого значения начинаются разные странные вещи.
Croman13n3c
Спаяв новую плату , всё магическим образом заработало
uriy
У меня точно такая же проблема, но контроллер STM32 а флешку пробовал at45db161 и at45db642. Спаяно 4 платы, одна работает без проблем. На трех на команду 9F читается 0x1E 0x00 0x00 0x00 именно такое значение выдает и флешка, видно осциллом.
На плате имеются длинные дорожки к другой SPI микросхеме, та микросхема читается без каких либо проблем.
SyncLair
Простите, а разве нельзя просто частоту уменьшить если у вас паразитные емкости из-за плохого монтажа ?
uriy
Частоту итак понижал до 250 КГц. Проблема похоже решена. Воткнул последовательно сигнальным линиям резисторы 100 Ом.
esaulenka
Цитата(SyncLair @ Dec 7 2012, 01:09) *
Простите, а разве нельзя просто частоту уменьшить если у вас паразитные емкости из-за плохого монтажа ?

Повторюсь. У этих микросхем есть параметр SCR rise (fall) time, равный 0.1 V/ns min. Для 3 вольт питания это означает максимальное время фронта 30 наносекунд.

По опыту, при превышении этих параметров будет работать именно так, как описано - читается всякая фигня, вне зависимости от самой частоты клока. При этом форма сигнала довольно хорошая...
uriy
Поясню тоже на будущее для других. Возможно кому-то поможет.
У меня тоже устройство состоит из двух лпат.
На первой стоит STM32 и в паре сантиметров от нее AT45DB642. На другой плате ADE7878. Обе микросхемы висят на одной шине SPI.
Суммарное расстояние до ADE порядка 30см. Межплатный разъем примерно по середине.
У разъема стоят резисторы 100 Ом последовательно и кондеры 1000пф на землю. С емкостью я похоже переборщил.
ADE отлично работает на длинной линии с таким резистором и емкостью.
Попробовал снять кондеры, ADE по-прежнему работает. с SPI флеш ничего не изменилось.
Запаял последовательно SPI флеш резисторы 100 Ом, кондеры по прежнему сняты. Все заработало.
Но ведь эти резисторы опять же увеличили длительность фронта.
Кондеры я ставил с целью избавится от отражений которые могли вызывать появление ложных фронтов.
Сергей Борщ
QUOTE (uriy @ Dec 11 2012, 07:08) *
Кондеры я ставил с целью избавится от отражений которые могли вызывать появление ложных фронтов.
Резисторы тоже. Завалили фронт, уменьшили спектр.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.