STM32F3 и STM32F4 проблемы с SPI.

STM32F3 и STM32F4 проблемы с SPI.

При переносе одного из проектов с сотой серии на трехсотую столкнулся с проблемой, посылки SPI всегда были длиной 16 бит, а мне нужно было 8. Что интересно у сотой серии для настройки длины пакета SPI выделен один бит DFF(Data frame format)  , когда он сброшен длина посылки 8 бит, когда установлен 16. В трехсотой серии под это дело выделили битовое поле DS(Data Size) длиной 4 бита и длину посылки можно установить равной от 4 до 16 бит.
STM32F3 и STM32F4 проблемы с SPI.

Но как бы я не изменял значение битового поля 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 всегда ноль.
комментарии
0