Jump to content

STM32F103 SPI!!! CMSIS + прерывание - 8bit - 16bit


john2103
 Share

Recommended Posts

Доброго времени суток, товарищи, пытаюсь создать функции передачи по spi с использованием cmsis и прерываний. Раньше пользовался HAL на "полу- интуитивном" уровне. Все работало. Сейчас пытаюсь все писать только на cmsis и вот возникла проблема... Я попытался сделать две функции ( Отправка по SPI - 8-битного  массива и передача 8 битная DFF = 0 и отправка 16 битного массива и передача 16 бит DFF =1 и все это через прерывания)Результат смотрю анализатором и вот в чем проблема... если сначала идет функция передачи 8 битная а потом 16 битная то мелькает лишняя передача, 8 бит 0x00 и потом идет правильная передача, 16 битная. Не могу понять откуда берется эта передача??? (0xAA 0xBB 0xCC 0x00 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF) ,  если поставить передачи 8 бит 16 бит 8 бит 16 бит то получается вот это (0xAA 0xBB 0xCC 0x00 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xAA 0xBB 0xCC 0xFE 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF), если между функциями вставить задержку 1 мс то все ок иначе тот результат о котором писал ..."головной убор Михаила Боярского"

void SPI1_STM32F1_init(void)
{

	// --- Инициализация порта для работы spi ---
		
	// ------ Настраиваем порт А --------------------------------------------------------------------------
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //--- Включаем тактирование порта А
	RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; //--- Включаем тактирование альтернативных функции
	RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; //--- Включаем тактированние SPI1 
	// ----------------------------------------------------------------------------------------------------
	GPIOA->CRL &= ~(GPIO_CRL_CNF5|GPIO_CRL_CNF7|GPIO_CRL_MODE5|GPIO_CRL_MODE7); //--- Обнуление первоначальных параметров порта
	GPIOA->CRL |= (
								 GPIO_CRL_MODE5			// --- |Настройка вывода SCL, на работу в режиме альтернативной функции   
								|GPIO_CRL_CNF5_1		// --- |режим output mode 11b - max 50 Мгц, CNF = 10b Альтернативная функция output push-pull  )
								|GPIO_CRL_MODE7			// --- |Настройка вывода MOSI
								|GPIO_CRL_CNF7_1		// --- |
								);
	// ----------------------------------------------------------------------------------------------------
	GPIOA->CRL &= ~(GPIO_CRL_CNF6|GPIO_CRL_CNF6); 
	GPIOA->CRL |= GPIO_CRL_MODE6;
	

	SPI1->CR1 |= SPI_CR1_BIDIMODE; // --- BIDIMODE режим работы (1 - одна линия, 0 - две линии связи)
	
	SPI1->CR1 |= SPI_CR1_BIDIOE;	 // --- BIDIOE Этот бит в сочетании с битом BIDImode выбирает направление передачи в двунаправленном режиме 
																 // --- 0: Output disabled (receive-only mode) 
																 // --- 1: Output enabled (transmit-only mode) 
	
	SPI1->CR1 &=~SPI_CR1_CRCEN;		 // --- Аппаратный расчет CRC включить
																 // --- 0: расчет CRC отключен 
																 // --- 1: Расчет CRC включен
	
	SPI1->CR1 &= ~SPI_CR1_CRCNEXT; // --- Следующая передача данных будет завершаться CRC-кодом.
																 // --- 0: Этап передачи данных
																 // --- 1: Следующая передача завершится передачей RCR
	
	SPI1->CR1 &= ~SPI_CR1_DFF;			 // --- Формат кадра данных
																 // --- 0: Размер кадра передачи 8 бит
																 // --- 1: Размер кадра передачи 16 бит
	
	SPI1->CR1 &= ~SPI_CR1_RXONLY;  // --- Этот бит совместно с BIDIMODE выбирает направление передачи в 2-х проводном (MISO и MISO) режиме.
																 // --- 0: Full duplex — передача и прием
																 // --- 1: Output disabled — только прием
	
 	SPI1->CR1 |= SPI_CR1_SSM; 		 // --- Программное управление ведомым устройством. Когда бит SSM установлен, сигнал NSS заменяется значением бита SSI.
																 // --- 0: Программное управление ведомым отключено
																 // --- 1: Программное управление ведомым включено
	
	SPI1->CR1 |= SPI_CR1_SSI;			 // --- Внутренний выбор ведомого. Этот бит работает только когда бит SSM установлен. Значение этого бита принудительно подается на NSS, а значение IO вывода NSS игнорируется.
																 // --- 1: (Master) Заменяет значение на выводе NSS
																 // --- 0; (Slave)
																 
	SPI1->CR1 &= ~SPI_CR1_LSBFIRST;// ---  Формат кадра
																 // --- 0: MSB передается первым
																 // --- 1: LSB передается первым
																 
	SPI1->CR1 |= SPI_CR1_BR;	 		 // --- BR[2:0]: Выбор скорости передачи
  																//	000: fPCLK/2 
																	//	001: fPCLK/4
																	//	010: fPCLK/8
																	//	011: fPCLK/16
																	//	100: fPCLK/32
																	//	101: fPCLK/64
																	//	110: fPCLK/128
																	//	111: fPCLK/256
																	//#define SPI_CR1_BR_Pos                      (3U)                               
																	//#define SPI_CR1_BR_Msk                      (0x7U << SPI_CR1_BR_Pos)           /*!< 0x00000038 */
																	//#define SPI_CR1_BR                          SPI_CR1_BR_Msk                     /*!< BR[2:0] bits (Baud Rate Control) */
																	//#define SPI_CR1_BR_0                        (0x1U << SPI_CR1_BR_Pos)           /*!< 0x00000008 */
																	//#define SPI_CR1_BR_1                        (0x2U << SPI_CR1_BR_Pos)           /*!< 0x00000010 */
																	//#define SPI_CR1_BR_2                        (0x4U << SPI_CR1_BR_Pos)           /*!< 0x00000020 */

	SPI1->CR1 |= SPI_CR1_MSTR;		 // --- Выбор режима работы SPI: Master/Slave
																 // --- 0: Режим Slave (ведомый)
																 // --- 1: Режим Master (ведущий)
																 
  SPI1->CR1 &= ~SPI_CR1_CPOL;		 // --- Полярность тактового сигнала
																 // --- 0: CK в 0 при простое
																 // --- 1: CK в 1 при простое
	
	SPI1->CR1 &= ~SPI_CR1_CPHA;		 // --- Фаза тактового сигнала
																 // --- 0: Первый переход тактового сигнала является краем захвата данных
																 // --- 1: Второй переход тактового сигнала является краем захвата данных


	SPI1->CR2 &= ~SPI_CR2_TXEIE;	 // --- Прерывание опустошения буфера передачи данных Tx
																 // --- 0: Прерывание TXE запрещено
																 // --- 1: Прерывание TXE разрешено. Используется для генерации прерывания когда устанавливается флаг TXE

	SPI1->CR2 &= ~SPI_CR2_RXNEIE;	 // --- Прерывание не пустого буфера приема Rx
																 // --- 0: Прерывание RXNE запрещено
																 // --- 1: Прерывание RXNE разрешено. Используется для генерации прерывания когда устанавливается флаг RXNE.

	SPI1->CR2 &= ~SPI_CR2_ERRIE;	 // --- Прерывание при возникновении ошибок передачи. Этот бит контролирует генерацию прерывания при возникновении одной из ошибок интерфейса SPI (CRCERR, OVR, MODF).
																 // --- 0: Прерывание при возникновении ошибок запрещено
																 // --- 1: Прерывание при возникновении ошибок разрешено

	SPI1->CR2 |= SPI_CR2_SSOE;		 // --- Разрешить выход SS
																 // --- 0: Выход SS отключен в режиме master (ведущий) и есть возможность работать в multimaster режиме
																 // --- 1: Выход SS включен в режиме master (ведущий), при этом нет возможности работать в multimaster режиме
																 
	SPI1->CR2 &= ~SPI_CR2_TXDMAEN;	 // --- Когда этот бит установлен, запрос DMA возникает при установке флага TXE
																 // --- 0: Tx buffer DMA disabled 
																 // --- 1: Tx buffer DMA enabled 

	SPI1->CR2 &= ~SPI_CR2_RXDMAEN;	 // --- Когда этот бит установлен, запрос DMA возникает при установке флага RXNE
																 // --- 0: Rx buffer DMA disabled 
																 // --- 1: Rx buffer DMA enabled


	SPI1_Enable;

	NVIC_EnableIRQ(SPI1_IRQn);

}

void SPI1_STM32F1_write_8bit_irq(uint8_t *data, int32_t len_8bit)
{
	 if(len_8bit<=0)
    return;
  
		//Ждем, пока SPI освободится от предыдущей передачи
		while(SPI1->SR & SPI_SR_BSY))
			;
		SPI1->CR1 &= ~SPI_CR1_SPE;			
		SPI1->CR1 &= ~SPI_CR1_DFF;
		SPI1->CR1 |= SPI_CR1_SPE;			
		
		//Настройка переменных, которые будут
		//использоваться в обработчике прерывания SPI
		tx_index_8_bit = 0;
		tx_len_8_bit = len_8bit;
		tx_data_8_bit = data;
		
		//Разрешаем прерывание TXEIE И запускаем обмен
		SPI1->CR2 |= SPI_CR2_TXEIE; 
		
}

void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit)
{
	 if(len_16bit<=0)
    return;
  
		//Ждем, пока SPI освободится от предыдущей передачи
		while(SPI1->SR & SPI_SR_BSY)
			;
		SPI1->CR1 &= ~SPI_CR1_SPE;	
		SPI1->CR1 |= SPI_CR1_DFF;
		SPI1->CR1 |= SPI_CR1_SPE;
		//Настройка переменных, которые будут
		//использоваться в обработчике прерывания SPI
		tx_index_16_bit = 0;
		tx_len_16_bit = len_16bit;
		tx_data_16_bit = data;
		
		//Разрешаем прерывание TXEIE И запускаем обмен
		SPI1->CR2 |= SPI_CR2_TXEIE; 
		
}


void SPI1_IRQHandler(void)
{
  if ((SPI1->CR1&SPI_CR1_DFF) == 0)
	{
	SPI1->DR = tx_data_8_bit[tx_index_8_bit]; //Записываем новое значение в DR
  tx_index_8_bit++; //увеличиваем счетчик переданных байт на единицу
  
  //если все передали, то отключаем прерывание,
  //тем самым завершаем передачу данных
  if(tx_index_8_bit >= tx_len_8_bit)
    SPI1->CR2 &= ~(SPI_CR2_TXEIE); 
	}
		else
	{
	SPI1->DR = tx_data_16_bit[tx_index_16_bit]; //Записываем новое значение в DR
  tx_index_16_bit++; //увеличиваем счетчик переданных байт на единицу
  
  //если все передали, то отключаем прерывание,
  //тем самым завершаем передачу данных
  if(tx_index_16_bit >= tx_len_16_bit)
    SPI1->CR2 &= ~(SPI_CR2_TXEIE); 
	}
}

.............
uint8_t data_8bit[3] = 
{ 0xAA, 0xBB, 0xCC};

uint16_t data_16bit[3] = 
{ 0xDDDD, 0xEEEE, 0xFFFF};

                                                                      
                                                                      
int main(void)
{
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
//LL_mDelay(1);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
//LL_mDelay(1);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
//LL_mDelay(1);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
}
                                                                      
                                                                      
                                                                      

 

Edited by john2103
Link to comment
Share on other sites

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

8 часов назад, john2103 сказал:

отправка по SPI - 8-битного  массива и передача 8 битная DFF = 0 и отправка 16 битного массива и передача 16 бит DFF =1 и все это через прерывания

А зачем вам нужен такой геморой , такой экстравагантный режим работы СПиАя??? Если вы считаете для себя возможным на лету менять режим работы периферии да еще и с прерываниями вы должны быть экспертом по этой периферии.

На мой взгляд вы что то перемудрили с прерываниями (как минимум) - при таком режиме работы их использование вряд ли оправдано!

Вы попробуйте изложить идею использования там прерываний и, я думаю, вам все станет намного понятнее!

Я так понимаю код который работал - работал без прерываний, правильно?

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

11 минуту назад, ruhi сказал:

А зачем вам нужен такой геморой , такой экстравагантный режим работы СПиАя??? Если вы считаете для себя возможным на лету менять режим работы периферии да еще и с прерываниями вы должны быть экспертом по этой периферии.

На мой взгляд вы что то перемудрили с прерываниями (как минимум) - при таком режиме работы их использование вряд ли оправдано!

Вы попробуйте изложить идею использования там прерываний и, я думаю, вам все станет намного понятнее!

Я так понимаю код который работал - работал без прерываний, правильно?

Это все чисто в образовательных целях! Пытаюсь повысить свой уровень знаний. Просто использование HAL не дает понимания как это все работает. Вот и захотелось все ручками. У меня есть функции без прерываний, которые прекрасно работают, через while(...txe). Просто много статей читал и смотрел, где делали это с прерываниями.Я не могу понять почему проходит эта передача. Я ведь дожидаюсь флага bay, потом выключаю модуль и включаю, не заношу больше ничего в DR, почему она возникает? в какой момент? Анализатором ничего путевого не могу поймать

Link to comment
Share on other sites

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Во-первых, что за задача, что надо щелкать туда-сюда битность? Во-вторых, ждут окончание передачи примерно так:

void SPI3_Send(uint8_t dat){
	while (!(SPI3->SR & SPI_SR_TXE));
	
	SPI3->DR = dat;

	while (!(SPI3->SR & SPI_SR_TXE));
	while ((SPI3->SR & SPI_SR_BSY));
}

В-третьих, выключать SPI перед сменой битности не требуется и делается как-то так:

void SPI3_Send16(uint16_t dat){
	SPI3->CR1 |= SPI_CR1_DFF;
	
	while (!(SPI3->SR & SPI_SR_TXE));
	
	SPI3->DR = dat;

	while (!(SPI3->SR & SPI_SR_TXE));
	while ((SPI3->SR & SPI_SR_BSY));
	
	SPI3->CR1 &= ~SPI_CR1_DFF;
}

В-четвертых, прерывание по передаче нафиг не нужно, ибо скорость передачи высокая и все очень быстро отправляется без прерываний. Прерывание удобно использовать на прием. А если надо слать большие массивы данных, то есть DMA. Ну и прежде чем отключать SPI :

In master or slave full-duplex mode (BIDIMODE=0, RXONLY=0)
1. Wait until RXNE=1 to receive the last data
2. Wait until TXE=1
3. Then wait until BSY=0
4. Disable the SPI (SPE=0) and, eventually, enter the Halt mode (or disable the peripheral
clock)

Link to comment
Share on other sites

Как измерить внутреннее сопротивление литиевого аккумулятора. Измеряем правильно

Внутреннее сопротивление – один из наиболее значимых параметров, от которого напрямую зависят другие характеристики литиевого аккумулятора. От этого параметра зависят такие характеристики источника питания, как напряжение на выходе под нагрузкой, максимальный выходной ток и коэффициент полезного действия (КПД). Рассмотрим как измерить действительное значение внутреннего сопротивления АКБ, используя определенные методики. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

44 минуты назад, BARS_ сказал:

Во-первых, что за задача, что надо щелкать туда-сюда битность?

Задача, сделать функции с использованием прерываний для передачи 8 битного и 16 битного массивов. Что бы была беспрерывная передача. (Использование для этого именно прерываний- это чистый интерес, поэтому этот пункт обязателен)

void SPI3_Send(uint8_t dat){
	while (!(SPI3->SR & SPI_SR_TXE));
	
	SPI3->DR = dat;

	while (!(SPI3->SR & SPI_SR_TXE)); // -- ЗАЧЕМ ЭТИ ПРОВЕРКИ ?
	while ((SPI3->SR & SPI_SR_BSY)); // ---Это трата времени 
}

 

49 минут назад, BARS_ сказал:

В-третьих, выключать SPI перед сменой битности не требуется

Из материалов, которые я читал, в разных местах пишут по разному, кто то говорит что надо, кто говорит- нет. Я четкого ответа не нашел и перестраховался.

 

57 минут назад, BARS_ сказал:

В-четвертых, прерывание по передаче нафиг не нужно, ибо скорость передачи высокая и все очень быстро отправляется без прерываний. Прерывание удобно использовать на прием. А если надо слать большие массивы данных, то есть DMA. Ну и прежде чем отключать SPI :

In master or slave full-duplex mode (BIDIMODE=0, RXONLY=0)
1. Wait until RXNE=1 to receive the last data
2. Wait until TXE=1
3. Then wait until BSY=0
4. Disable the SPI (SPE=0) and, eventually, enter the Halt mode (or disable the peripheral
clock)

Разобраться с DMA - это следующая задача. За механизм остановки спасибо. Только опять вопрос, зачем ждать остальные флаги, если BSY =0  свидетельствует о том что SPI и передачу и прием закончило ??? Или я ошибаюсь ?

Link to comment
Share on other sites

1 час назад, john2103 сказал:

Просто много статей читал и смотрел, где делали это с прерываниями

что то я сомневаюсь что существует хоть одна статья про использовании прерываний СПИАя когда переключается режим из 16-битного в 8-ми битный.

Если вы хотите изучать работу с прерываниями - уберите переключение режимов, если хотите изучать переключения режимов - уберите прерывания,

когда по отдельности разберетесь, может у вас получится сотворить какое нибудь чудо, а пока рано о чудесах грезить :) .

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

25 минут назад, ruhi сказал:

что то я сомневаюсь что существует хоть одна статья про использовании прерываний СПИАя когда переключается режим из 16-битного в 8-ми битный.

В том то и дело! Много статей, где идет передача 8бит и ожиданием флагов или 16 бит и флаги. Я сам по экспериментировал и сделал переключение с 8 га 16 и обратно. Так же примеры с прерыванием и 8бит или прерывание и 16 бит. А потом я попытался сделать переключение с прерыванием, но чет есть проблемы. Видимо,чет я не совсем понимаю в логике работы модуля. Хотя в циклах все ок.(И я думал, что я разобрался)

Причем просто функция передачи по прерываниям работает отлично, если без смены битности. Но битность то я меняю когда модуль не работает ? не могу понять..(

Edited by john2103
Link to comment
Share on other sites

11 час назад, john2103 сказал:

если между функциями вставить задержку 1 мс

так это... ты говоришь модуль спи отключается при изменении битности - 

может он у тебя отключается ДО того как байт выплюнулся хотя это странно конечно - в общем надо проверить наложение момента отключения юнита на текущюю передачу,

и вот так :

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

если передавать, что будет?

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

4 минуты назад, ruhi сказал:

может он у тебя отключается ДО того как байт выплюнулся хотя это странно конечно

В том то и дело. По логике... Как я думаю spi не будет отключатся раньше чем выплюнет крайний бит и не примет если есть что, т.к. я отслеживаю флаг BSY. Но ощущение, что не смотря на то, что я проверил бит BSY и вроде как модуль закончил все дела,я его остановил и изменил количество бит на передачу, он почему то считает что в DR занесено значение 0x00 и выплевывает его, хотя этого нигде нет. Может конечно и моя функция на передачу с прерыванием вообще как то не так построена.

Если передать 

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

То все норм 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0xAA 0xBB 0xCC

 Проверил если 

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);

То после 8 битных передач опять появляется одна передача 0x00, а потом все норм по 16 бит как положено, ничего лишнего

Link to comment
Share on other sites

12 минуты назад, john2103 сказал:

Что бы была беспрерывная передача.

Беспрерывная передача не имеет отношения к прерываниям. 

image.thumb.png.da4269ea00445cfaf017f9441b136e07.png

 

2 минуты назад, john2103 сказал:

То после 8 битных передач опять появляется одна передача 0x00, а потом все норм по 16 бит как положено, ничего лишнего

А если убрать отключение и включение SPI?

Link to comment
Share on other sites

12 часа назад, john2103 сказал:

//если все передали, то отключаем прерывание, //тем самым завершаем передачу данных if(tx_index_16_bit >= tx_len_16_bit) SPI1->CR2 &= ~(SPI_CR2_TXEIE); }

я насколько помню-знаю отключение (это же просто запрет?) прерываний НЕ отключает СПИ!

И, соответственно, я не вижу что у тебя СПИ воЩе отключается! то есть получается ты ему битность меняешь наживую - это вполне может приводить к генерации лишней посылки на шину!

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

29 минут назад, ruhi сказал:

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

если передавать, что будет?

Попробовал еще 

При такой конструкции 

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);

SPI1_STM32F1_write_8bit_irq( data_8bit, 3);
SPI1_STM32F1_write_8bit_irq( data_8bit, 3);

SPI1_STM32F1_write_16bit_irq( data_16bit, 3);
SPI1_STM32F1_write_16bit_irq( data_16bit, 3);

получается 

0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0x00 

0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF

0xAA 0xBB 0xCC 0xAA 0xBB 0xCC 0xFE

0xDD 0xDD 0xEE 0xEE 0xFF 0xFF 0xDD 0xDD 0xEE 0xEE 0xFF 0xFF

Link to comment
Share on other sites

12 часа назад, john2103 сказал:

while(SPI1->SR & SPI_SR_BSY) ; SPI1->CR1 &= ~SPI_CR1_SPE;

вообще то отключать надо после каждого из этих while -ов , конфигурировать и включать.

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

15 минут назад, BARS_ сказал:

Беспрерывная передача не имеет отношения к прерываниям. 

Я знаю. И картинку смотрел. Я неправильно выразился. Если передавать большой объем данных с опросом флага, то программа "фактически" встанет, пока все не передаст все (DMA - пока в принципе не рассматриваю). С прерыванием она может выполнять какие то фоновые задачи в это время. Ну это так... для меня же пока основная задача, понять насколько хорошо я понял принципы. 

20 минут назад, BARS_ сказал:

А если убрать отключение и включение SPI?

Только что убрал, все так же не правильные передачки проскакивают. В принципе строки отключения и включения spi, появились когда я искал причину появления этих лишних передач. 

Link to comment
Share on other sites

12 часа назад, john2103 сказал:

SPI1_Enable;

вот это вот что такое? и где дизэйбл???

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

12 минуты назад, ruhi сказал:

я насколько помню-знаю отключение (это же просто запрет?) прерываний НЕ отключает СПИ!

И, соответственно, я не вижу что у тебя СПИ воЩе отключается! то есть получается ты ему битность меняешь наживую - это вполне может приводить к генерации лишней посылки на шину!

Прерывание нет.

void SPI1_STM32F1_write_16bit_irq(uint16_t *data, int32_t len_16bit)
{
	.....
		SPI1->CR1 &= ~SPI_CR1_SPE;	
		SPI1->CR1 |= SPI_CR1_DFF;
		SPI1->CR1 |= SPI_CR1_SPE;
	....
}

В самой функции передачи происходит отключение модуля и переключение разрядности. И как писали выше, битность вроде можно менять на живую

 

3 часа назад, BARS_ сказал:

В-третьих, выключать SPI перед сменой битности не требуется 

 

15 минут назад, ruhi сказал:

вот это вот что такое? и где дизэйбл???

Забыл вставить это в шапке проги 

#define SPI1_Enable  SPI1->CR1 |= SPI_CR1_SPE

А дизэйбл не прописывал, дальше я и включал и выключал в функции передачи напрямую битами.

Link to comment
Share on other sites

46 минут назад, john2103 сказал:

То после 8 битных передач опять появляется одна передача 0x00, а потом все норм по 16 бит как положено, ничего лишнего

вот исходя из этого, например, как и по другим данным, у меня только одна гипотеза (кажется мне правдоподобной):

переключение с 8бит на 16 - приводит к тому что СПИ-ай воспринимает это расширение как то что у него появился один НЕ переданный байт который он и отправляет,

поэтому, я бы предложил, в качестве эксперимента, этот СПИ-ай выключить как то более кардинально,

что бы не было сомнений что его настройки ни как не связаны с его предыдущими настройками.

потому что если вы его просто задизейблили он все равно может запомнить что у него появился непереданный байт. который он сначала выплюнет при разрешении передачи!

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

28 минут назад, ruhi сказал:

вот исходя из этого, например, как и по другим данным, у меня только одна гипотеза (кажется мне правдоподобной):

переключение с 8бит на 16 - приводит к тому что СПИ-ай воспринимает это расширение как то что у него появился один НЕ переданный байт который он и отправляет,

поэтому, я бы предложил, в качестве эксперимента, этот СПИ-ай выключить как то более кардинально,

что бы не было сомнений что его настройки ни как не связаны с его предыдущими настройками.

потому что если вы его просто задизейблили он все равно может запомнить что у него появился непереданный байт. который он сначала выплюнет при разрешении передачи!

Я вот сейчас сижу и смотрю на схему выше

 

1 час назад, BARS_ сказал:

image.thumb.png.da4269ea00445cfaf017f9441b136e07.png

И у меня тоже гипотеза почти как ваша .... Только вот думаю, а не может ли SPI "думать", что у него есть еще один, не принятый байт? и поэтому даже после флага BSY он шлет SCK, но вот почему он передает то 0x00 то 0xFE я не могу понять. (Или я немного не так понимаю смысл подписи к самой нижней картинке RX buffer)

Хотя такая версия как у вас у меня тоже была. Просто не знаю как бы ее проверить ... Рубить тактирование модуля ?

Edited by john2103
Link to comment
Share on other sites

9 минут назад, BARS_ сказал:

Зайти под отладчиком и пройтись по флагами

Пытаюсь, уже дня три, но постоянно в отладчике проскакиваю. Сейчас буду пытаться 

Link to comment
Share on other sites

17 минут назад, john2103 сказал:

что у него есть еще один, не принятый байт?

почему не принятый - не переданный? он же у вас мастер? Или ты имеешь ввиду попробовать прочитать его?

все надо пробовать - все что в голову приходит, в таких ситуациях.

Все таки, если правильно что 1мс задержки решает проблему лишнего байта, значит что задержка до переключения битности решает проблему!

АГА - вот! попробуй после бизи флага подождать еще флаг завершения передачи (есть такой? не опустошения буфера для записи следующего сампла, а именно что все выплюнули в шину!)

Точно! если ты его дизейблишь а он еще не закончил посылать последний байт и до завершения посылки не дизейблится - тут ты и попадаешь в undefined behavior.

Там может еще бит-флаг есть о том что СПИ-ай задизейблился, тогда его надо ждать после дизейбла!

23 минуты назад, john2103 сказал:

Рубить тактирование модуля ?

вряд ли - тогда наверно не получится сконфигурировать, если только выключить-включить сразу попробовать.

вот такой флаг еще посмотри:

Там может еще бит-флаг есть о том что СПИ-ай задизейблился, тогда его надо ждать после дизейбла!

Edited by ruhi

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

Сейчас увеличил скорость работы spi до 

6 минут назад, ruhi сказал:

АГА - вот! попробуй после бизи флага подождать еще флаг завершения передачи (есть такой? не опустошения буфера для записи следующего сампла, а именно что все выплюнули в шину!)

Так если я правильно все понимаю, то это и есть BSY  флаг? Нет?

Сейчас увеличил скорость работы SPI, левые посылки пропали. 

первый скрин скоросьть /256, второй /32

Где то в прерываниях я косячу, что то где то не так проверяю

частота 111.jpg

частота 100.jpg

Link to comment
Share on other sites

Только что, john2103 сказал:

Так если я правильно все понимаю, то это и есть BSY  флаг? Нет?

значит он - я точные названия уже не помню.

1 минуту назад, john2103 сказал:

Сейчас увеличил скорость работы SPI, левые посылки пропали. 

Так это эквивалентно тому что ты маленькую задержку добавил! Задержка же решает проблему!

Попробуй вернуть медленную скорость и поставить 5 или 10 NOP инструкций после ожидания бизи!

Это может быть фича такая СТМ-мовского СПИ-ая что у него бизи срабатывает чуть раньше чем надо!?

8 минут назад, john2103 сказал:

Где то в прерываниях я косячу, что то где то не так проверяю

ты там читаешь регистр управления в прерывании, вот я бы так не стал делать, сделай флаг в памяти.

Можно сделать все! Но чем больше можно, тем больше нельзя!

Link to comment
Share on other sites

9 часов назад, john2103 сказал:

Из материалов, которые я читал, в разных местах пишут по разному, кто то говорит что надо, кто говорит- нет. Я четкого ответа не нашел и перестраховался.

Потому-то нужно читать RM, а не в разных местах...

Edited by MasterElectric
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...