SPI

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

serg_vega
Сообщения: 96
Зарегистрирован: 20 июл 2020, 15:50
Предприятие: АО "ВНИИ "Вега"

Re: SPI

Сообщение serg_vega »

И у меня и у blessedit речь идет именно о коротких посылках. У меня вообще 24 бита.
blessedt
Сообщения: 34
Зарегистрирован: 25 фев 2019, 00:09
Предприятие: АОКБ Импульс

Re: SPI

Сообщение blessedt »

Ну да, DMA, конечно, не для этого придумали, но за время обмена, 240 тактов из 5000 можно делать рутинные операции.
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

Добрый день!
А возможна непрерывная работа SPI (без отпускания CS и пропусков тактирования)?
Вложения
SPI.png
SPI.png (8.64 КБ) 2706 просмотров
dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

Re: SPI

Сообщение dav »

Paul125 писал(а): 03 авг 2022, 11:56 Добрый день!
А возможна непрерывная работа SPI (без отпускания CS и пропусков тактирования)?
Доброго времени суток!
Да, непрерывная работа возможна в случае программного управления сигналом CS. Какая длина посылки должна быть?
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

Да, перешел на программное управление CS, но последняя посылка отправляется позже чем я отпускаю CS, видимо из за сдвигового регистра.
Необходимо городить временную задержку.
Но интересен SCLK, он прерывается после каждого байта отправленных данных.
Работаю с SD картой.
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

Доброго времени суток, товарищи!
А есть какая-то возможность заставить SPI выдавать прерывания при приеме/передаче каждого 16-битного слова?
Заполнять буфер четырьмя словами по 4 бита не предлагать ))
Да, возможно принимать необходимое количество слов от 1 до 1024х.
Сделать это можно настроив ДМА (на 1 -1024 слово), по завершению приема ДМА выдаст вам прерывание.
Еще можно настроить ДМА на передачу и прием (но вкл перерывание только на прием), тогда по завершению передачи в режиме мастера вы получите прерывание от принимающего буфера (не забудьте вычитать 8 раз буфер приема перед включением ДМА).
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

Столкнулся с проблемой, загадкой...
Есть 2 платы с МК1921 один в режиме мастера другой в слейве.
Когда отправляю значения 0, 1, 7 слейв все принимает сигнализируя на шине MISO значением (0xfe, так контролирую прием).
Когда отправляю 2, 4, 5... и т.д слейв может принять данные, а может и не принять, как ему захочется (закономерности не установил).
Работаю в режиме ДМА.
Привожу несколько рисунков обмена, прошу помощи весь мозг сломал.
Вложения
Значение 0х01
Значение 0х01
Screenshot_3.png (34.67 КБ) 1587 просмотров
Значение 0х41
Значение 0х41
Screenshot_2.png (36.99 КБ) 1587 просмотров
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

Почему-то в режиме слейва происходит потеря данных при включении запрета на передачу SOD.
Сделал циклический буфер, по прерыванию складываю туда принятые значения, одновременно хочу отвечать происходит потеря данных как на прием так и на передачу.
Так же в какой то момент SPI сам по себе начинает отсылать последнее значение записанное в буфер.
Просто в режиме приема все работает корректно.
Подскажите что может быть не так?
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: SPI

Сообщение Paul125 »

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

Код: Выделить всё

if(Cnt > 20){
			NT_SPI1->SPI_DR = 0x80;
			while(!SPI_GetITStatus(NT_SPI1, SPI_Flag_TFE));
			while(SPI_GetITStatus(NT_SPI1, SPI_Flag_BSY));
		}
Инициализация

Код: Выделить всё

#include "K1921VK01T.h"
#include "niietcm4.h"
#include "system_K1921VK01T.h"

void GPIO_Ph_Init() {

	GPIO_Init_TypeDef GPIOInit_SPI;
	// SPI1 MOSI
	GPIO_StructInit(&GPIOInit_SPI);
	GPIOInit_SPI.GPIO_Pin = GPIO_Pin_0;
	GPIOInit_SPI.GPIO_Mode = GPIO_Mode_AltFunc;
	GPIOInit_SPI.GPIO_AltFunc = GPIO_AltFunc_3;
	GPIOInit_SPI.GPIO_Out = GPIO_Out_En;
	GPIOInit_SPI.GPIO_PullUp = GPIO_PullUp_En;
	GPIO_Init(NT_GPIOF, &GPIOInit_SPI);

	// SPI1 MISO
	GPIO_StructInit(&GPIOInit_SPI);
	GPIOInit_SPI.GPIO_Pin = GPIO_Pin_2;
	GPIOInit_SPI.GPIO_Mode = GPIO_Mode_AltFunc;
	GPIOInit_SPI.GPIO_AltFunc = GPIO_AltFunc_3;
	GPIOInit_SPI.GPIO_Out = GPIO_Out_En;
	GPIOInit_SPI.GPIO_PullUp = GPIO_PullUp_En;
	GPIO_Init(NT_GPIOG, &GPIOInit_SPI);

	// SPI1 SCLK
	GPIO_StructInit(&GPIOInit_SPI);
	GPIOInit_SPI.GPIO_Pin = GPIO_Pin_9;
	GPIOInit_SPI.GPIO_Mode = GPIO_Mode_AltFunc;
	GPIOInit_SPI.GPIO_AltFunc = GPIO_AltFunc_3;
	GPIOInit_SPI.GPIO_Out = GPIO_Out_En;
	GPIOInit_SPI.GPIO_PullUp = GPIO_PullUp_En;
	GPIO_Init(NT_GPIOE, &GPIOInit_SPI);

	// SPI1 CS
	GPIO_StructInit(&GPIOInit_SPI);
	GPIOInit_SPI.GPIO_Pin = GPIO_Pin_8;
	GPIOInit_SPI.GPIO_Mode = GPIO_Mode_AltFunc;
	GPIOInit_SPI.GPIO_AltFunc = GPIO_AltFunc_3;
	GPIOInit_SPI.GPIO_Out = GPIO_Out_En;
	//GPIOInit_SPI.GPIO_PullUp = GPIO_PullUp_En;
	GPIO_Init(NT_GPIOE, &GPIOInit_SPI);
}

//! SPI_DIV_SPI OFF FQspi = Fsys/(CPSDVSR*(SCR+1))
//! SPI_DIV_SPI ON 	FQspi = Fsys/(CPSDVSR*(SCR+1)*2*(DIV_SPI+1))
void SPI_Ph_Init() {

	// настройка тактирования и сброса SPI
	RCC_PeriphRstCmd(RCC_PeriphRst_SPI1, ENABLE);

	SPI_ClkInit_TypeDef SPI_ClkInitStruct1;
	SPI_ClkInitStruct1.SPI_SelectClk = SPI_Select_SystemClock;
	SPI_ClkInitStruct1.SPI_ClkDiv = SPI_SysClkDiv_SysClk;
	SPI_ClkInitStruct1.SPI_SysClkStatus = SPI_Clk_Enable;
	SPI_ClkInitStruct1.SPI_DIV_SPI = 0;	// max 63
	SPI_ClkInit(NT_SPI1, &SPI_ClkInitStruct1);

	// настройка блока SPI
	SPI_Init_TypeDef SPI_InitStruct1;
	SPI_StructInit(&SPI_InitStruct1);
	SPI_InitStruct1.SPI_SCR = 0;
	SPI_InitStruct1.SPI_CPSDVSR = 2;
	SPI_InitStruct1.SPI_Mode = SPI_ModeSlave;
	SPI_InitStruct1.SPI_WordLength = SPI_WordLength8b;
	SPI_InitStruct1.SPI_SPH = SPI_SPH_1Edge;
	SPI_InitStruct1.SPI_SPO = SPI_SPO_Low;
	SPI_InitStruct1.SPI_FRF = SPI_FRF_SPI_Motorola;
	SPI_InitStruct1.SPI_TX_Slave = 0;
	SPI_Init(NT_SPI1, &SPI_InitStruct1);

	Энвик_EnableIRQ(SPI1_IRQn);
	SPI_ITConfig(NT_SPI1, SPI_IT_RX, ENABLE);
	SPI_Cmd(NT_SPI1, ENABLE);
}

#define SYSTEM_CLK 		72000000
#define DataLength		100
	uint16_t Cnt = 0;
	uint8_t SPI1_RXData[DataLength] = { 0 };
Основной код

Код: Выделить всё

void main() {
	RCC_PLLAutoConfig(RCC_PLLRef_XI_OSC, SYSTEM_CLK);
	GPIO_Ph_Init();
	SPI_Ph_Init();

	while (1) {
		if(Cnt > 20){
			NT_SPI1->SPI_DR = 0x80;
			while(!NT_SPI1->SPI_SR_bit.TFE);
			while(NT_SPI1->SPI_SR_bit.BSY);
		}
		if(Cnt > DataLength){
			Cnt = 0;
		}
	}
}

void SPI1_IRQHandler() {
	while(NT_SPI1->SPI_SR_bit.BSY);
	while(NT_SPI1->SPI_SR_bit.RNE){
		SPI1_RXData[Cnt++] = (uint8_t) (NT_SPI1->SPI_DR);
	}
	SPI_ClearITPendingBit(NT_SPI1, SPI_IT_MASK);
}
Вложения
Screenshot_1.png
Screenshot_1.png (47.16 КБ) 1198 просмотров
Ответить

Вернуться в «32-разрядные микроконтроллеры»