Jump to content
john2103

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

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

Share this post


Link to post
Share on other sites
8 часов назад, john2103 сказал:

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

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

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

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

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


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

Share this post


Link to post
Share on other sites
11 минуту назад, ruhi сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites

Взаимодействие устройств IoT от Microchip с облаком Google

Благодаря облачным технологиям появилась возможность реализовать сложные проекты на базе микроконтроллера путем перераспределения вычислительной нагрузки между микроконтроллером и облаком. Простые в использовании отладочные платы, такие как AVR- и PIC-IoT WG, позволяют выполнять ресурсоемкие вычисления, передавая их в облако.

Подробнее

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

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)

Share this post


Link to post
Share on other sites

Пружинные клеммники Degson - высокое качество соединения по оптимальной цене!

Пружинные клеммные блоки Degson для монтажа на печатную плату – это простое и надежное соединение, которое позволяет легко решать задачи для различных приложений за счет обширного ассортимента. Клеммники Degson доступны в двух конструктивных исполнениях (торцевой контакт и зажимная клеть), имеют различные направления ввода проводника (45°, 90°, 180°) и обладают широким диапазоном поперечных сечений (0,2…2,5 мм2).

Подробнее

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 и передачу и прием закончило ??? Или я ошибаюсь ?

Share this post


Link to post
Share on other sites

Новое семейство ИП от MEAN WELL мощностью 150, 300, 600 Вт с повышенной перегрузочной способностью

Компания MEAN WELL разработала семейство источников питания номинальной мощностью 150, 300 и 600 Вт с возможностью кратковременной безопасной работы при мощности в 2,5 раза выше номинальной (до 5 секунд). Данное семейство источников питания востребовано в промышленных установках с использованием электродвигателей или с емкостной нагрузкой. Применяя новые источники питания HRP/N можно получить экономический выигрыш.

Подробнее

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

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

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

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

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


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

Share this post


Link to post
Share on other sites
25 минут назад, ruhi сказал:

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

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

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

Edited by john2103

Share this post


Link to post
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);

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


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

Share this post


Link to post
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 бит как положено, ничего лишнего

Share this post


Link to post
Share on other sites
12 минуты назад, john2103 сказал:

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

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

image.thumb.png.da4269ea00445cfaf017f9441b136e07.png

 

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

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

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

Share this post


Link to post
Share on other sites
12 часа назад, john2103 сказал:

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

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

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


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

Share this post


Link to post
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

Share this post


Link to post
Share on other sites
12 часа назад, john2103 сказал:

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

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


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

Share this post


Link to post
Share on other sites
15 минут назад, BARS_ сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
12 часа назад, john2103 сказал:

SPI1_Enable;

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


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

Share this post


Link to post
Share on other sites

На кой там нужен дизейбл?

Отправлено с моего Nexus 5 через Tapatalk

Share this post


Link to post
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

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

Share this post


Link to post
Share on other sites
46 минут назад, john2103 сказал:

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

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

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

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

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

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


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

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

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

Отправлено с моего Nexus 5 через Tapatalk

Share this post


Link to post
Share on other sites
9 минут назад, BARS_ сказал:

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

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

Share this post


Link to post
Share on other sites
17 минут назад, john2103 сказал:

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

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

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

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

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

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

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

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

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

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

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

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

Edited by ruhi

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

частота 111.jpg

частота 100.jpg

Share this post


Link to post
Share on other sites
Только что, john2103 сказал:

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

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

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

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

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

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

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

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

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

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


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

Share this post


Link to post
Share on other sites
9 часов назад, john2103 сказал:

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

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

Edited by MasterElectric

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. 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
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...

  • Сообщения

    • Они все пляшут по КУ, особенно 16-е.  Там встречались экземпляры до  +/-30..40%..Думаю, сейчас,  "ровных" ламп найти вероятность минимальная.
    • думать тебе противопоказано .... из гавна - не лепят конфетки .... при таких вопросах - тебе лампочку к батарейке подключать - в самій раз ..... а колонки - не ломай.
    • Подскажите, пожалуйста, какие металлоискатели смогут обнаружить металл на 1.5-2м. Нужно найти трубу под землей, она бетонная или керамическая, к трубе есть доступ за 70м до нужного места. Думаю привязать к протяжке что-то металлическое и запустить в трубу, а потом металоискателем её найти. Насколько это реально ?
    • Вобщем вопрос, как удалить старый компаунд, которым склеиваются советские ПЛ сердечники. Раньше всё удалял механическим способом. Но может есть какие другие варианты? Пробовал ацетоном - не берет. Вопрос номер 2 - достаточно склеить их эпоксидкой или нужен какой то хитрый состав? И вопрос номер 3 - один товарищ утверждал, что если в пл сердечнике от трансформатора ТСА270 сделать немагнитный зазор в виде прокладки из бумаги то ток холостого хода уменьшится. Это правда или он по ушам ездит?
    • ну так и спиши на гавно АКБ .... китаезы давно порхатые стали .... гарантия - до дверей. в сейфе узкоглазого .... наврняка спинздили .... и перелатали под себя ... а такие ШИМ-ки-перевертыши зеркальные по пиновке на МОНИТОР сбрасывал .... дрочи судьбу так: https://www.google.com/search?client=firefox-b-d&q=sot23-6+marking+code+R9BGB и убирай по одной букве постепенно сначала - конца .... в режиме картинок .... может повезет ....
    • Советуют настоятельно такой, вторичка фрезерована в ее пазах первичка
  • Similar Content

    • By Обычный Человек
      Микроконтроллер ATmega328p, внешний кварц 16МГц. Компилятор avr-gcc с оптимизацией O1

      Написал код для управление шаговым двигателем. Работает так: требуемая скорость задается переменной STP1_ReqSpeed, дальше с частотой 100Гц срабатывает таймер TIM0, который высчитывает с какой частотой надо подавать сигналы на вход шагового драйвера. TIM1 работает в режиме частотно импульсной модуляции и по прерыванию меняет значение пина на противоположное.

      Управление работает, скорость регулируется, но по какой то причине случаются пропуски шагов. Чаще всего во время ускорения. Количество пропусков от 0 до 4, обычно 2-3, длятся 32мс.

      Из кода вырезал неиспользуемое. Заменить прерывания на аппаратный ШИМ возможности нет. Как убрать эти пропуски?
      Осциллограммы:
       
       
    • By Tuxford
      С помощью STM32CubeMX сгенерил самый примитывний проект чтобы что-то принять-передать по USB. Все бы ничего, но обмена не происходит, хотя в системе устройство видно.
      Шаг за шагом обнаружил что приходит прерывание SOF, и просто скидывается. На этом финиш. И так постоянно. Находил проекты по эти борды (Blue pill, STM32 Smart), где собственно все то же. Но нифига не рабтает.

      Что же такого особенного в этом MCU особенного чтобы USB работал?
      PS. Пробывал делать тоже на STM32L4-Discovery. Работает старта. В чем разница?
      IOC в атаче.
      TestBP.ioc
    • By В гостях у Slime
      Здравствуйте, мне нужна помощь с подключением дисплея WG12864 к STM32F103C8T6. А именно? Я не нашёл библиотек для него, лишь только ардуиновские. Может у кого есть своя? С STM32 опыта почти нет. Так мигал светодиодом и всё, но зато ардуину я уже знаю всё. Я перерос её и мне хочется освоить стм.
    • By defin
      Добрый день, имеется отладочная плата Nucleo-F411RE. Не получается настроить в CMSIS ногу PA8 для вывода частоты (MCO) с внутреннего генератора HSI. Через HAL все чётко работает. Из reference manual так и не понял как прописать источник тактирования для MCO. В инете полно примеров для F100 серии, для себя не могу их адаптировать.
      RCC->AHB1ENR|=RCC_AHB1ENR_GPIOAEN; // enable clock for port A GPIOA->MODER |= GPIO_MODER_MODER8_0; GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD8_0; GPIOA->PUPDR |= GPIO_PUPDR_PUPD8_1; GPIOA->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8_0 | GPIO_OSPEEDER_OSPEEDR8_1); RCC->CFGR |= RCC_CFGR_SW_HSI; //вот здесь не знаю что писать, написал наугад Тактирование по умолчанию от HSI
    • By COKPOWEHEU
      Решил разобраться с модулем компаса GY-271 - одним из немногих модулей, которые вообще сумел найти. Пол-интернета заполнены утверждениями что собран данный модуль на микросхеме HMC5883L, которая общается по I2C и отзывается на адрес 0x1E (соответственно, 0x3C/0x3D для записи и чтения). На практике же посылка этого адреса натыкалась на глухой таймаут, мол знать не знаем такого адреса, и вообще мы не оно. Целенаправленные, но больше случайные поиски по интернету дали наводку что данное чудо техники, возможно, отзовется на адрес 0x0D (0x1A/0x1B для записи и чтения) и действительно, по такому адресу удалось добиться ответа, правда не совсем того, что ожидалось. К примеру, без "шаманской" (опять же, советы из "Всезнающего") записи единицы по адресу 9, ответ был нулевым. Потом более-менее осмысленные данные появились, но не с адреса 0x03, как положено по даташиту, а вовсе даже с 0x00. Очередная случайная находка дала направление, что заботливые китайцы запаяли на плату не HMC5883L, а вовсе даже QMC5883L - совсем другую микросхему с другими регистрами. И вот она действительно похожа по настройкам и адресу.
      Стал бы я создавать тему, если бы все было так хорошо... Хотя ответ от микросхемы и есть, как-то он слабо похож на нормальные данные. Теоретически, в регистрах 1:0, 3:2, 5:4 должны быть проекции магнитного поля на оси X, Y, Z. То есть вдали от магнитов и массивных железяк, геометрическая сумма значений должны быть примерно 0.5 Гс, то есть ~32000 единиц модуля, причем пока модуль лежит на столе, сильно меняться значениям не с чего. Привожу лог снятых данных (во вложении исходный код прошивки: вся работа с периферией идет руками, без автоконфигураторов и тому подобного). За все время съема этого лога модель лежал на столе в одном положении, но данные по осям скачут достаточно произвольным образом.
      I2C test FB FF 0A 00 14 00 00 A8 F5 0D 00 01 01 00 Write 0F 00 05 00 F1 FF 04 99 F5 | 15 5 -15 2337 FB FF 00 00 05 00 00 9A F5 | -5 0 5 2338 0F 00 05 00 00 00 00 8F F5 | 15 5 0 2327 E2 FF 00 00 F6 FF 00 93 F5 | -30 0 -10 2331 28 00 F6 FF FB FF 00 90 F5 | 40 -10 -5 2328 05 00 FB FF FB FF 00 99 F5 | 5 -5 -5 2337 00 00 00 00 00 00 00 97 F5 | 0 0 0 2335 00 00 0F 00 D6 FF 00 99 F5 | 0 15 -42 2337 32 00 E2 FF 00 00 00 94 F5 | 50 -30 0 2332 E7 FF EC FF 00 00 00 97 F5 | -25 -20 0 2335 05 00 F6 FF 00 00 04 92 F5 | 5 -10 0 2330 Продублирую код чтения регистра (насколько я знаю, он довольно типичный, но мало ли...). Естественно, код писался в первую очередь под конкретную задачу - оптимизация будет потом, если оно вообще заработает.
      void I2C_Read(uint8_t device, uint8_t addr, uint8_t *buf, uint8_t count){ //start I2C2->CR1 |= I2C_CR1_START; while(!(I2C2->SR1 & I2C_SR1_SB)){} (void) I2C2->SR1; //device I2C2->DR = (device<<1) &~(1<<0); while(!(I2C2->SR1 & I2C_SR1_ADDR)){} (void) I2C2->SR1; (void) I2C2->SR2; //addr I2C2->DR = addr; while(!(I2C2->SR1 & I2C_SR1_TXE)){} I2C2->CR1 |= I2C_CR1_STOP; //restart I2C2->CR1 |= I2C_CR1_START; while(!(I2C2->SR1 & I2C_SR1_SB)){} //device I2C2->DR = (device<<1) | (1<<0); while(!(I2C2->SR1 & I2C_SR1_ADDR)){} (void) I2C2->SR1; (void) I2C2->SR2; //data for(uint8_t i=0; i<count-1; i++){ //I2C2->CR1 &=~ I2C_CR1_ACK; I2C2->CR1 |= I2C_CR1_ACK; while(!(I2C2->SR1 & I2C_SR1_RXNE)){} buf[i] = I2C2->DR; } I2C2->CR1 &=~I2C_CR1_ACK; while(!(I2C2->SR1 & I2C_SR1_RXNE)){} buf[count-1] = I2C2->DR; //stop I2C2->CR1 |= I2C_CR1_STOP; } #define QMC5883L 0x0D I2C_Read(QMC5883L, 0, data, 14); for(uint8_t i=0; i<14; i++){ UART_HEX(data[i]); UART_putc(USART, ' '); } data[0] = 0x80; I2C_Write(QMC5883L, 10, data, 1); data[0] = 0x01; I2C_Write(QMC5883L, 0x0B, data, 1); data[0] = (0b00<<6) | (0b00<<4) | (0b11<<2) | (0b01<<0); //oversampling = 512 //range = 2 G //ODR = 200 Hz //mode = continuous I2C_Write(QMC5883L, 9, data, 1); UART_puts(USART, "Write\x0d\n"); while(1){ I2C_Read(QMC5883L, 0, data, 9); for(uint8_t i=0; i<9; i++){ UART_HEX(data[i]); UART_putc(USART, ' '); } i16a x,y,z,t; x.u8val[0] = data[0]; x.u8val[1] = data[1]; y.u8val[0] = data[2]; y.u8val[1] = data[3]; z.u8val[0] = data[4]; z.u8val[1] = data[5]; t.u8val[0] = data[7]; t.u8val[1] = data[8]; t.ival += 3000+2000; sprintf(str,"| %i %i %i %i", x.ival, y.ival, z.ival, t.ival); UART_puts(USART, str); Собственно, вопрос: что я делаю не так и как сделать так, чтобы модуль отдавал правильные данные магнитного поля?
      compass.rar
×
×
  • Create New...