|
Проблема с SPI., STM32F303VC |
|
|
|
Mar 27 2018, 06:53
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Камень STM32F303VC Настроил SPI Код /*!< SPI Config */ 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_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //APB1=36Mhz => ~1Mhz //APB2=72Mhz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPIx, &SPI_InitStructure); Размер задан - байт - SPI_DataSize_8b На скопе на клоке вижу 16 бит - после передачи 8 бит посылает еще 8. Я что то недонастроил? Передача байта такая Код uint32_t SPI_TransferByte(SPI_TypeDef *SPIx, uint8_t data) { uint32_t timeout;
// All data transmitted/received but SPI may be busy so wait until done. timeout = SPI_DELAY; while (SPIx->SR & SPI_I2S_FLAG_BSY) { if(!timeout--) return SPI_ERR; }
// Setting the Data Register (DR) transmits the byte of data on MOSI. SPIx->DR = data;
// Wait for any data on MISO pin to be received. timeout = SPI_DELAY; while (!(SPIx->SR & SPI_I2S_FLAG_RXNE)) { if(!timeout--) return SPI_ERR; }
// Return the data received on MISO pin. return (uint8_t)(SPIx->DR); }
Сообщение отредактировал Jenya7 - Mar 27 2018, 06:56
|
|
|
|
|
Mar 27 2018, 07:36
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Jenya7 @ Mar 27 2018, 09:53)  Размер задан - байт - SPI_DataSize_8b На скопе на клоке вижу 16 бит - после передачи 8 бит посылает еще 8. Я что то недонастроил? Есть такая тема в F3. Перепишите структуру так Код typedef struct { __IO uint16_t CR1; /*!< SPI Control register 1 (not used in I2S mode), Address offset: 0x00 */ uint16_t RESERVED0; /*!< Reserved, 0x02 */ __IO uint16_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ uint16_t RESERVED1; /*!< Reserved, 0x06 */ __IO uint16_t SR; /*!< SPI Status register, Address offset: 0x08 */ uint16_t RESERVED2; /*!< Reserved, 0x0A */ union { __IO uint16_t DR16; /*!< SPI data register, Address offset: 0x0C */ __IO uint8_t DR8; /*!< SPI data register, Address offset: 0x0C */ }; uint16_t RESERVED3; /*!< Reserved, 0x0E */ __IO uint16_t CRCPR; /*!< SPI CRC polynomial register (not used in I2S mode), Address offset: 0x10 */ uint16_t RESERVED4; /*!< Reserved, 0x12 */ __IO uint16_t RXCRCR; /*!< SPI Rx CRC register (not used in I2S mode), Address offset: 0x14 */ uint16_t RESERVED5; /*!< Reserved, 0x16 */ __IO uint16_t TXCRCR; /*!< SPI Tx CRC register (not used in I2S mode), Address offset: 0x18 */ uint16_t RESERVED6; /*!< Reserved, 0x1A */ __IO uint16_t I2SCFGR; /*!< SPI_I2S configuration register, Address offset: 0x1C */ uint16_t RESERVED7; /*!< Reserved, 0x1E */ __IO uint16_t I2SPR; /*!< SPI_I2S prescaler register, Address offset: 0x20 */ uint16_t RESERVED8; /*!< Reserved, 0x22 */ } SPI_TypeDef; и для 8 и менее -битных посылках используйте SPIx->DR8, а для более 8-битных SPIx->DR16. Добавлю, что это как раз тот случай, когда ответ можно найти в StdLib. Код void SPI_SendData8(SPI_TypeDef* SPIx, uint8_t Data) { uint32_t spixbase = 0x00;
/* Check the parameters */ assert_param(IS_SPI_ALL_PERIPH(SPIx));
spixbase = (uint32_t)SPIx; spixbase += 0x0C; *(__IO uint8_t *) spixbase = Data; } В RM это явление описано не очевидно. Код When the SPIx_DR register is accessed, data frames are always right-aligned into either a byte (if the data fits into a byte) or a half-word (see Figure 388). During communication, only bits within the data frame are clocked and transferred.
|
|
|
|
|
Mar 27 2018, 09:24
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Сергей Борщ @ Mar 27 2018, 12:00)  Глядя на этот код хочется долго и настойчиво бить его автора головой об стену. Я для себя ничего лучшего, чем подправить структуру не придумал. Да, вмешался в исходник StdLib, что не допустимо. Да, не все компиляторы поддерживают анонимные структуры/объединения. Да, ST мальца накосячили. Есть еще варианты кроме прямого приведения типов?
|
|
|
|
|
Mar 27 2018, 10:31
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Jenya7 @ Mar 27 2018, 11:23)  а что в нем не так? на будущее. чтобы знать. Поехали по буквам: CODE uint32_t spixbase = 0x00; 1)Придуманный специально для этого uintptr_t? Не, не слышали. CODE spixbase = (uint32_t)SPIx; spixbase += 0x0C; 2)Магические числа. Ну хоть стандартный макрос offsetof() можно было использовать вместо магичесого числа? Не, не слышали. 3)Почему не смогли взять сразу адрес SPIx->DR? Адресная арифметика, которую компилятор делает лучше криворукого программиста, тут делается вручную. 4)Переменная называется spix base, хотя хранит совсем не base. CODE *(__IO uint8_t *) spixbase = Data; Ну наконец-то! Полэкрана кода ради одного-единственного явного приведения типа. А что мешало вместо всего этого "шедевра" написать один макрос CODE #define SPI_SendData8(SPIx, data) *(__IO uint8_t *)&SPIx->DR = data
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 27 2018, 11:13
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Сергей Борщ @ Mar 27 2018, 13:31)  А что мешало вместо всего этого "шедевра" написать один макрос Код #define SPI_SendData8(SPIx, data) *(__IO uint8_t *)&SPIx->DR = data Полностью поддерживаю! Та функция - ну просто вырви-глаз какой-то! Ещё лучше регистр DR описать как union 16-битного и 8-битного. Тогда будет выглядеть ещё лучше. Я обычно так делаю. Честно говоря - мне всегда противно смотреть на портянки типа: Код SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; ... всегда пролистываю такие сообщения не глядя. И это вместо, того чтобы задать блоки периферийных регистров в виде структур, а формировать битовые поля в них макросами (ну или просто номерами битов), что было бы красиво и эффективно.
|
|
|
|
|
Mar 28 2018, 10:43
|
Частый гость
 
Группа: Участник
Сообщений: 146
Регистрация: 19-07-16
Пользователь №: 92 603

|
Цитата(adnega @ Mar 28 2018, 11:38)  Научитесь читать на техническом английском, и перед вами откроются многообещающие перспективы. Еще освоить сам язык Си.
|
|
|
|
|
Mar 30 2018, 06:26
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Чтобы не плодить тем, добавлю здесь. Вчера у меня был фестиваль HardFault ( Зато вынес ценный опыт. Ничто не предвещало..
Тадамм!!
В другом месте присвоение поля uint16_t в структуре падало так же, а копирование через memcpy проходило успешно. Чтобы не мучать ребусами, обращаю внимание на адрес буфера данных. HAL хорошая штука, но есть нюансы.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Mar 30 2018, 06:49
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(MrYuran @ Mar 30 2018, 09:26)  Чтобы не мучать ребусами, обращаю внимание на адрес буфера данных. Типа данные не выровненные? А ядро какое? На Cortex-M3 не выровненные данные не приводят к HF, а просто добавляют лишний такт (хотя можно заставить генерить исключение). Вчера с аналогичной бедой боролся на Cortex-M0 Код typedef struct s_param { int v_int; } __attribute__((packed)) s_param; ... ((s_param *)&out[p_out])->v_int += (in[p_in] - '0');
|
|
|
|
|
Mar 30 2018, 07:26
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(adnega @ Mar 30 2018, 09:49)  Вчера с аналогичной бедой боролся на Cortex-M0 Вот оно же и есть. Там вкладочка с халом отсвечивает Кстати, если бы не криворукий пейсатель драйвера AD7799 c сайта analog.com, я бы никогда туда не залетел. Они там в первый байт буфера кидают какой-то служебный байт, пришлось сдвинуть на один и здрасте.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|