STM32F3 и STM32F4 проблемы с SPI.
При переносе одного из проектов с сотой серии на трехсотую столкнулся с проблемой, посылки SPI всегда были длиной 16 бит, а мне нужно было 8. Что интересно у сотой серии для настройки длины пакета SPI выделен один бит DFF(Data frame format) , когда он сброшен длина посылки 8 бит, когда установлен 16. В трехсотой серии под это дело выделили битовое поле DS(Data Size) длиной 4 бита и длину посылки можно установить равной от 4 до 16 бит.
Но как бы я не изменял значение битового поля DS посылки все равно оставались 16 битными. Наверное стоит разъяснить, что в данном случае понимается под 16 битными посылками. Если подключиться к выводу SPI_SCK осциллографом, то при отправке/приеме данных на экране осциллографа будет 16 горбов, а по фронтам, которые формируют один горб, происходит передача данных.
В RM0316 информации по этому поводу нет, но ее удалось найти на одном из форумов. Разрядность посылок зависит от того как идет обращение к регистру DR.
Для того чтобы посылки стали 8 битными необходим обращаться к регистру DR как к 8 битному.
Кроме того, у МК трехсотой серии можно определить порог установки флага RXNE(Receive buffer not empty). Отвечает за это бит FRXTH(FIFO reception threshold), если он установлен флаг RXNE будет устанавливаться когда в FIFO будет находиться 8 бит и больше. Если он сброшен, то 16 бит и больше. В общем для 8 битного режима его надо установить.
Ну и напоследок инициализация SPI в 8 битном режиме для STM32F303VC.
Что касается серии F4, баг в этой серии заключается в следующем, что для того, чтобы SPI стартовал необходима задержка в 100ms. Иначе в регистре DR всегда ноль.
Но как бы я не изменял значение битового поля DS посылки все равно оставались 16 битными. Наверное стоит разъяснить, что в данном случае понимается под 16 битными посылками. Если подключиться к выводу SPI_SCK осциллографом, то при отправке/приеме данных на экране осциллографа будет 16 горбов, а по фронтам, которые формируют один горб, происходит передача данных.
В RM0316 информации по этому поводу нет, но ее удалось найти на одном из форумов. Разрядность посылок зависит от того как идет обращение к регистру DR.
Для того чтобы посылки стали 8 битными необходим обращаться к регистру DR как к 8 битному.
#define SPI2_DR_8bit *(__IO uint8_t*)&(SPI2->DR)
Кроме того, у МК трехсотой серии можно определить порог установки флага RXNE(Receive buffer not empty). Отвечает за это бит FRXTH(FIFO reception threshold), если он установлен флаг RXNE будет устанавливаться когда в FIFO будет находиться 8 бит и больше. Если он сброшен, то 16 бит и больше. В общем для 8 битного режима его надо установить.
Ну и напоследок инициализация SPI в 8 битном режиме для STM32F303VC.
#define SPI2_DR_8bit *(__IO uint8_t*)&(SPI2->DR)
void spi_init(void)
{
//Включаем тактирование порта B
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
//распиновка
//PB13 - SCL - Alternative func. push-pull - OUT
//PB14 - MISO - Alternative func. push-pull - OUT - IN
//PB15 - MOSI - Alternative func. push-pull - OUT
//PB12 - CS - GPIO - soft - OUT
//13, 14, 15 вывод - альтернативная функция,
GPIOB->MODER |= GPIO_MODER_MODER13_1 | GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1;
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR13 | GPIO_OSPEEDER_OSPEEDR15;
GPIOB->PUPDR &= ~(GPIO_PUPDR_PUPDR13 | GPIO_PUPDR_PUPDR15);
//назначаем выводам необходимые альтернативные ф-ции
GPIOB->AFR[1] |= (0x05<<5*4);
GPIOB->AFR[1] |= (0x05<<6*4);
GPIOB->AFR[1] |= (0x05<<7*4);
// 12 вывод - выход с подтяжкой к питанию
GPIOB->MODER |= GPIO_MODER_MODER12_0;
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR12_0;
//конфигурируем SPI2
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; //Enable oscil SPI2
SPI2->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256
SPI2->CR1 |= SPI_CR1_CPOL; //Polarity cls signal CPOL = 0;
SPI2->CR1 |= SPI_CR1_CPHA; //Phase cls signal CPHA = 0;
SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB will be first
SPI2->CR1 |= SPI_CR1_SSM; //Program mode NSS
SPI2->CR1 |= SPI_CR1_SSI; //анналогично состоянию, когда NSS 1
SPI2->CR1 |= SPI_CR1_MSTR; //Mode Master
SPI2->CR1 |= SPI_CR1_SPE; //Enable SPI2
SPI2->CR2 |= SPI_CR2_FRXTH; //RXNE 8 bit
SPI2->CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2; //Data_Size
}
uint8_t spi_txrx(uint8_t data)
{
SPI2_DR_8bit = data;
while ((SPI2->SR & SPI_SR_RXNE) == 0);
return SPI2_DR_8bit;
}
Что касается серии F4, баг в этой серии заключается в следующем, что для того, чтобы SPI стартовал необходима задержка в 100ms. Иначе в регистре DR всегда ноль.
Похожие статьи