реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F100RB + AT45DB081D, странное поведение
batson
сообщение Sep 4 2012, 19:59
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 26-02-11
Пользователь №: 63 256



Почему такая хрень, например: посылаю команду Manufacturer and Device ID Information (0x9F) а в ответ приходит FF FF 1F 25 00 00. Откуда берутся при любом чтении SPI эти два лишних байта FF FF.
Еще при записи памяти теряются несколько первых байт, остальные записываются нормально.

Настройки порта
Код
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //SPI1 clock
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //включить тактирование альтернативных функций        /
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //включить тактирование порта А
    //вывод SCK: выход двухтактный, альтернативная функция, 50MHz
    GPIOA->CRL   |=  GPIO_CRL_MODE5;    //
    GPIOA->CRL   &= ~GPIO_CRL_CNF5;     //
    GPIOA->CRL   |=  GPIO_CRL_CNF5_1;   //
    //вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
    GPIOA->CRL   &= ~GPIO_CRL_MODE6;    //
    GPIOA->CRL   &= ~GPIO_CRL_CNF6;     //
    GPIOA->CRL   |=  GPIO_CRL_CNF6_1;   //
    GPIOA->BSRR   =  GPIO_BSRR_BS6;     //
    //вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
    GPIOA->CRL   |=  GPIO_CRL_MODE7;    //
    GPIOA->CRL   &= ~GPIO_CRL_CNF7;     //
    GPIOA->CRL   |=  GPIO_CRL_CNF7_1;   //
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //подать тактирование                                      /
    SPI1->CR1     = 0x0000;             //очистить первый управляющий регистр
    SPI1->CR2     = 0x0000;             //очистить второй управляющий регистр
    SPI1->CR1    |= SPI_CR1_MSTR;       //контроллер должен быть мастером
    SPI1->CR1    |= SPI_CR1_BR;         //задаем скорость        
    //SPI1->CR1    |= SPI_CR1_BR_0;         //задаем скорость    
    //SPI1->CR1    |= SPI_CR1_BR_1;         //задаем скорость
    //SPI1->CR1    |= SPI_CR1_BR_2;         //задаем скорость
    SPI1->CR1    |= SPI_CR1_CPOL;
    SPI1->CR1    |= SPI_CR1_CPHA;
    SPI1->CR1    |= SPI_CR1_SSI;        //обеспечить высокий уровень программного NSS
    SPI1->CR1    |= SPI_CR1_SSM;        //разрешить программное формирование NSS
    SPI1->CR1    |= SPI_CR1_SPE;        //разрешить работу модуля SPI

Скорость самая маленькая. С битами SPI_CR1_CPOL и SPI_CR1_CPHA баловался, результат тотже.

Процедуры чтения и записи
Код
void send_spi1_byte(unsigned char byte)
{  
    while ((SPI1->SR & SPI_SR_TXE) == 0);
    SPI1->DR = byte;
}

unsigned char read_spi1_byte(void)
{    
    unsigned char byte;
    
    send_spi1_byte(0xFF);
    
    while ((SPI1->SR & SPI_SR_RXNE) == 0);
    byte = SPI1->DR;
    
    return byte;
}


Сама функция Manufacturer and Device ID Information
Код
void at45_devid(void)
{  
    volatile unsigned int i;
    
    cs_spi1_low();

    send_spi1_byte(0x9F);

    for(i = 0;i < 6;i++)
    {
        at45_read_buf[i] = read_spi1_byte();
    }
    
    cs_spi1_high();
}
Go to the top of the page
 
+Quote Post
SII
сообщение Sep 4 2012, 20:30
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414



Анализировать код лениво (да и не работаю я с STM32 в настоящее время, а посему подробностей в голове не держу), но одно соображение выскажу. Принимаете ли Вы во внимание, что по SPI всегда выполняется операция чтения-записи (не существует отдельных операций чтения и записи)? Вполне возможно, что по крайней мере один FF Вы принимаете, выдавая команду чтения идентификатора устройства: контроллер SPI же не только отправляет байт, но и одновременно ведёт приём.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 4 2012, 20:46
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(SII @ Sep 4 2012, 23:30) *
Вполне возможно, что по крайней мере один FF Вы принимаете, выдавая команду чтения идентификатора устройства: контроллер SPI же не только отправляет байт, но и одновременно ведёт приём.

Один байт обязательно придёт - FF или нет, но будет.
А вот откуда второй?
Может в буфере что-то непрочитанное осталось?
Можно его сбросить(проверить нет ли в нём данных) перед началом обмена?
Go to the top of the page
 
+Quote Post
batson
сообщение Sep 10 2012, 21:06
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 26-02-11
Пользователь №: 63 256



Цитата(_Артём_ @ Sep 5 2012, 00:46) *
Может в буфере что-то непрочитанное осталось?
Можно его сбросить(проверить нет ли в нём данных) перед началом обмена?

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

Что-то с настроками STM32... написал софтовый spi - все работает отлично.

Сообщение отредактировал batson - Sep 10 2012, 21:07
Go to the top of the page
 
+Quote Post
Danis
сообщение Sep 11 2012, 17:46
Сообщение #5


Twilight Zone
***

Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990



Цитата(batson @ Sep 11 2012, 00:06) *
Пробовал читать после посылки каждого байта, не помогает. Самое главное теряются несколько первых байт при записи в память, тут чтение вобще не причем.

Что-то с настроками STM32... написал софтовый spi - все работает отлично.


Может чем поможет, моя инициализация SPI STM32F101 для работы с памятью
CODE
// Метод конфигурирует аппаратный модуль SPI1 микроконтроллера и его пины для
// работы с внешней памятью SPI -> EN25F16
void SPI_Flash::Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

// Configure SPI1 pin: SCK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Configure SPI1 pin: MISO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//Configure SPI1 pin: MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Configure SPI1 CS pin : PA4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);


SPI_InitTypeDef SPI_InitStructure;

// SPI configuration
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;


SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; // 12MHz


SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);

// Enable the sFLASH_SPI
SPI_Cmd(SPI1, ENABLE);
}


Сообщение отредактировал IgorKossak - Sep 11 2012, 20:01
Причина редактирования: [codebox] для длинного кода!!!


--------------------
Magic Friend
Go to the top of the page
 
+Quote Post
nx6310
сообщение Oct 19 2012, 10:05
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



У меня при чтении по spi перввый байт всегда был FF. перед чтением надо регистр DR считать.
Код
while (!(spi->SR&SPI_I2S_FLAG_TXE));  //проверяем флаг занятости spi
spi->DR = read_reg|acc_x_l;// посылаем байт
while (!(spi->SR&SPI_I2S_FLAG_RXNE)); // проверяем флаг приёма байта
b=spi->DR;                  // сбрасываем регистр приёма
while (!(spi->SR&SPI_I2S_FLAG_TXE));//проверяем флаг занятости spi
spi->DR = 0xff;   //инициализация приёма байта(попросту передаем байт)
while (!(spi->SR&SPI_I2S_FLAG_RXNE));// проверяем флаг приёма байта
b=spi->DR; //принимаем корректный первый байт

при приёме следующих байт сбрасывание не требуется
Тут в какой то ветке про это уже писали, не помню кто и где

Сообщение отредактировал nx6310 - Oct 19 2012, 10:05
Go to the top of the page
 
+Quote Post
batson
сообщение Dec 15 2012, 13:48
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 28
Регистрация: 26-02-11
Пользователь №: 63 256



Дошли наконец руки разобраться с данной неприятностью. Проблема была в функции чтения данных, - при посылке байта нужно обязательно производить чтение данных, иначе устанавливается флаг OVR: Overrun flag, отсюда и эти FF... С правильно написанной функцией записи-чтения все передается и принимается идеально, без каких-либо лишних байт.
Функция записи-чтения:
Код
unsigned char send_spi1_byte(unsigned char byte)
{  
    unsigned char rxbyte;
    
    while (!(SPI1->SR & SPI_SR_TXE));
    SPI1->DR = byte;
    while (!(SPI1->SR & SPI_SR_RXNE));
    rxbyte = SPI1->DR;
    
    return rxbyte;
}


Пользоваться ей нужно так:
Код
void at45_devid(void)
{  
    unsigned int i;
    
    cs_spi1_low();

    send_spi1_byte(0x9F); //посылка команды

    for(i = 0;i < 6;i++)
    {
        at45_read_buf[i] = send_spi1_byte(0xFF); //прием данных
    }
    
    cs_spi1_high();
}
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 10:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01409 секунд с 7
ELECTRONIX ©2004-2016