batson 0 4 сентября, 2012 Опубликовано 4 сентября, 2012 · Жалоба Почему такая хрень, например: посылаю команду 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SII 0 4 сентября, 2012 Опубликовано 4 сентября, 2012 · Жалоба Анализировать код лениво (да и не работаю я с STM32 в настоящее время, а посему подробностей в голове не держу), но одно соображение выскажу. Принимаете ли Вы во внимание, что по SPI всегда выполняется операция чтения-записи (не существует отдельных операций чтения и записи)? Вполне возможно, что по крайней мере один FF Вы принимаете, выдавая команду чтения идентификатора устройства: контроллер SPI же не только отправляет байт, но и одновременно ведёт приём. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 4 сентября, 2012 Опубликовано 4 сентября, 2012 · Жалоба Вполне возможно, что по крайней мере один FF Вы принимаете, выдавая команду чтения идентификатора устройства: контроллер SPI же не только отправляет байт, но и одновременно ведёт приём. Один байт обязательно придёт - FF или нет, но будет. А вот откуда второй? Может в буфере что-то непрочитанное осталось? Можно его сбросить(проверить нет ли в нём данных) перед началом обмена? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
batson 0 10 сентября, 2012 Опубликовано 10 сентября, 2012 (изменено) · Жалоба Может в буфере что-то непрочитанное осталось? Можно его сбросить(проверить нет ли в нём данных) перед началом обмена? Пробовал читать после посылки каждого байта, не помогает. Самое главное теряются несколько первых байт при записи в память, тут чтение вобще не причем. Что-то с настроками STM32... написал софтовый spi - все работает отлично. Изменено 10 сентября, 2012 пользователем batson Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 11 сентября, 2012 Опубликовано 11 сентября, 2012 (изменено) · Жалоба Пробовал читать после посылки каждого байта, не помогает. Самое главное теряются несколько первых байт при записи в память, тут чтение вобще не причем. Что-то с настроками STM32... написал софтовый spi - все работает отлично. Может чем поможет, моя инициализация SPI STM32F101 для работы с памятью // Метод конфигурирует аппаратный модуль 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); } Изменено 11 сентября, 2012 пользователем IgorKossak [codebox] для длинного кода!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nx6310 0 19 октября, 2012 Опубликовано 19 октября, 2012 (изменено) · Жалоба У меня при чтении по 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; //принимаем корректный первый байт при приёме следующих байт сбрасывание не требуется Тут в какой то ветке про это уже писали, не помню кто и где Изменено 19 октября, 2012 пользователем nx6310 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
batson 0 15 декабря, 2012 Опубликовано 15 декабря, 2012 · Жалоба Дошли наконец руки разобраться с данной неприятностью. Проблема была в функции чтения данных, - при посылке байта нужно обязательно производить чтение данных, иначе устанавливается флаг 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(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться