Cujo

Realtime SSI slave 18bit+ STM3L4

4 posts in this topic

Cujo    0

Собственно задача соорудить SSI slave Transmit only с асинхронным обновлением в реальном времени.
Контроллер сейчас STM32L433CC. 
Дано один вход SCLK до 2 МГц, один выход SOUT(он жеMISO). Формат посылки 18, 20,22 бит.
Обновление через ~15мкс после последнего такта SCLK, либо каждые 7,5 мкс.
Стандартный интерфейс для быстрых датчиков.
Как делал 
1: Без DMA и прерываний, по прерываниям от TIM_ETR на SCLK. Режим без NSS, с NSS по первому SCLK и сбросом.
Проблема нельзя узнать, записались ли данные в SPI->DR, соответственно первые байты могли быть не обновлены, а следующие обновлялись.
2: DMA с NSS по таймеру. Проблема: DMA не обновляет SPI в реальном времени, а только после отправки прошлой посылки, а нужно обновлять каждые 7,5 мкс вне зависимости есть ли запросы. 
Если пробовать сбрасывать SPI и обновлять DMA, случаются смещения на 1 такт, а потому как реакция ядра на запрос ~ 150-200 нс, + обновление ~ 150-200нс. В итоге облом.

Какие есть решения, может кто сталкивался?

 

Снимок.PNG

Edited by Cujo

Share this post


Link to post
Share on other sites
ruhi    39
В 10.11.2018 в 21:31, Cujo сказал:

нельзя узнать, записались ли данные в SPI->DR,

Это как это? Если инструкция записи выполнена - данные записались!

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

Вообще зачем нужен таймер? Используйте флаг опустошения буфера! Скорость SPI- настраивается, в том числе через задержки между байтами.

И для ДМА, кстати, тоже флаг опустошения буфера нужно использовать.

Edited by ruhi
дополнено

Share this post


Link to post
Share on other sites
Cujo    0

на самом деле проблема уже решилась с помощью трех таймеров, программного прерывания 3х внешних соединений и кучи костылей, подробнее описал на easyelectronics, если интересно

 

Проблема в том что SPI->DR обновлять можно. Те на SPI будут выдаваться последний записанных DR. Но когда приходит такт SCLK, регистр блокируется и запись в него не осуществляется. И узнать об этом никак нельзя. А обновлять данные нужно не дожидаясь прихода SCLK, он может не приходить сколь угодно долго, но данные должны быть все время актуальные.

Дело в том, что на этом контроллере есть еще 2 потока с периодом вызова 7 и 14 мкс. Останавливать их никак нельзя, и главные прежде всего они. SPI нужен чтобы вывести информацию о их вычислениях, те о угле либо положении.  Стандартный протокол выдачи в таких случаях - это SSI, есть еще BISS C - тот же проприетарный SSI с контрольной суммой. 

В общем, тему можно закрывать. Плодить костыли по интернету как-то не хочется. STM сказал: "он не рекомендует использовать их МК для реализации SSI и работоспособность такой системы не гарантирована".

Share this post


Link to post
Share on other sites

Старт складской программы по Wi-Fi/ Bluetooth-чипам от Espressif

На склад КОМПЭЛ поступили чипы, модули и отладочные платы от компании Espressif Systems на базе ESP8266 и ESP32. Стоимость всех изделий данной линейки – в 2-3 раза ниже ближайших аналогов, чипы занимают минимальное место на плате, энергоэффективны и универсальны в применении

Подробнее...

Guest Kost286   
Guest Kost286

Если ещё интересно. Недавно пришлось с датчиком линейного перемещения столкнуться. Протокол SSI.

Сделал 2 варианта: 1)с использованием таймера и внешнего прерывания ; 2) с использованием SPI. 

С SPI конечно получше, больше времени на выполнение других задач остаётся, так как вместо 48 прерываний по передаче и ещё 25 прерываний по приёму для получения одного значения это очень много.

При использовании SPI только 2 прерывания. Или вообще без них.

Вот пример с SPI:

Настройка SPI

void Init_SPI2(void){
	/* Configure SPI pins: SCK and MOSI with default alternate function (not re-mapped) push-pull */
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	/* Configure MISO as Input with internal pull-up */
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	// SPI configuration
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // 64000kHz/256=250kHz
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	//SPI_InitStructure.SPI_CRCPolynomial = 7;
	SPI_Init(SPI2, &SPI_InitStructure);
	SPI_CalculateCRC(SPI2, DISABLE);
	SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Set);
	SPI_Cmd(SPI2, ENABLE);
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) { ; }
}

Обработка

volatile uint32_t u32ssiResult;
 uint16_t u16singleTurn;
 uint16_t u16multiTurn;
 char cBuffer[32];
volatile uint32_t u32result = 0;

uint32_t spiReadSSI( void )
{
 uint8_t u8byteCount;

 for (u8byteCount=0; u8byteCount<2; u8byteCount++)
 {
	 // отправить что-нибудь для запуска тактирования
	 SPI_I2S_SendData(SPI2, 0xffff);
	 u32result <<= 16; 
	 while( !(SPI2->SR & SPI_SR_TXE) || SPI2->SR & SPI_SR_BSY);
	 u32result |= SPI_I2S_ReceiveData(SPI2);
 }

 u32result >>= 7; // убираю часть LSBs, можно не убирать, просто у меня мусор там
 return u32result;
}
int main(void)
{
	 Init_clock();
	 Init_pins();
	 Init_SPI2();
	 Init_UART2();
	 delay_ms(50);
	 Init_IWDG(2000);
	 printf("START\r");

while(1)
    {
		delay_ms(100);
		IWDG_ReloadCounter();

		if (inc_sec++ >= 5){
			inc_sec = 0;
			u32ssiResult = spiReadSSI();
			
			u16singleTurn = u32ssiResult & 0x0000FFFF; //здесь я млачшую часть взял 2 байта
			u16multiTurn = (u32ssiResult >> 16) & 0x0000000F; //старшый, только 1 байт беру, дальше цифры уже не меняются когда линейка до краёв доходит
			//Это я разделил, чтобы по 2 байта передать по юарту
             printf( "MSB = " );
             sprintf( cBuffer, "%u ", u16multiTurn);
             printf( cBuffer );
             printf( "LSB = " );
             sprintf( cBuffer, "%u ", u16singleTurn);
             printf( cBuffer );
             printf(" \r");
		}
    }
}

Вот и всё. Схема подключения - просто через модули на MAX485. Только нужно с передающего выпаять если есть резистор на 120 ом, который параллельно A-B впаян и питать его 5 вольтами. И не забыть подать питание на выбор режима работы - передача.

Из приёмного модуля можно ничего не выпаявать, питать 3.3 вольтами, выбор режима работы подсоединить к минусу питания.

Share this post


Link to post
Share on other sites

Your content will need to be approved by a moderator

Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoticons maximum 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...

  • Similar Content

    • By mr_smit
      Вынес то что не получается в упрощенной форме в отдельный проект. Среда разработки CooCox 1.7.8, микроконтроллер STM32F103C8T6.
      Нужно раз в ~100 мсек формировать на ножке МК, например,такую последовательность:

      Стартовую длительность формирует таймер, в первом же своем прерывании по совпадению активирует DMA и дальше уже DMA по запросу таймера загружает значение CCR из массива. Что то похожее на управление светодиодами WS2812B. То что я сочинил выдает на пин:

      Но только один раз при первом вызове. При последующих вызовах данные из массива выдаются без первоначальной длительности в 150 мкс.
      Не могу найти ошибку. 
       
      #include <stm32f10x.h> #include <stm32f10x_conf.h> #include <stm32f10x_gpio.h> #include <stm32f10x_rcc.h> #include <stm32f10x_tim.h> #include <stm32f10x_dma.h> GPIO_InitTypeDef PIN; TIM_TimeBaseInitTypeDef TIM_Config; TIM_OCInitTypeDef TIM_OCConfig; DMA_InitTypeDef DMA_Setting; uint8_t Test_Buf[] = {15,30,30,30,15}; void delay_ms(uint32_t ms) { volatile uint32_t nCount; RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq (&RCC_Clocks); nCount = (RCC_Clocks.HCLK_Frequency/10000)*ms; for (; nCount != 0; nCount--); } void Init_GPIO(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); PIN.GPIO_Pin = GPIO_Pin_11; // PA11 -> TIM1 Channel4 PIN.GPIO_Mode = GPIO_Mode_AF_PP; PIN.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &PIN); } void Init_TIM_Transmit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructInit(&TIM_Config); // настройки по дефолту TIM_Config.TIM_Prescaler = 72-1; // Запускаем таймер на тактовой частоте 1 MHz (72000000/(72-1)) TIM_Config.TIM_Period = 150-1; // Период - 150 мкс TIM_Config.TIM_ClockDivision = 0; // частоту дополнительно не делим TIM_Config.TIM_CounterMode = TIM_CounterMode_Up; // считаем вверх TIM_TimeBaseInit(TIM1, &TIM_Config); // Инициализируем TIM1 TIM_OCStructInit(&TIM_OCConfig); // настройки по дефолту TIM_OCConfig.TIM_OCMode = TIM_OCMode_PWM1; // Конфигурируем как ШИМ (выравнивание по границе) TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable; // Включаем выход TIM_OCConfig.TIM_Pulse = 0; // CCR до старта пока нулевой TIM_OCConfig.TIM_OCPolarity = TIM_OCPolarity_High; // Полярность TIM_OCConfig.TIM_OCIdleState = TIM_OCIdleState_Reset; // состояние выхода по совпадению CCR (сброс) TIM_OC4Init(TIM1, &TIM_OCConfig); // Инициализируем 4-й выход таймера, это PA11 TIM_ARRPreloadConfig(TIM1,ENABLE); // Предзагрузка периода (ARR) TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); // Предзагрузка длины импульса CCR 4-го канала // (даем досчитать до конца и только потом значение меняется на новое) TIM_DMACmd(TIM1,TIM_DMA_CC4,DISABLE); // выключаем пока запрос к DMA от таймера TIM1 по достижении CCR) TIM_CtrlPWMOutputs(TIM1, ENABLE); // включаем выходы (это только для TIM1) TIM_CCxCmd(TIM1,TIM_Channel_4,TIM_CCx_Enable); // разрешаем таймеру управлять выводом PA11 TIM_ITConfig(TIM1, TIM_IT_CC4, DISABLE); // запрещаем пока таймеру генерировать прерывание по совпадению NVIC_EnableIRQ(TIM1_CC_IRQn); // разрешаем прерывания TIM_Cmd(TIM1, DISABLE); // Выключаем таймер (пока ждем) } void TIM1_CC_IRQHandler(void) // прошло 130 мкс { if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) { // по совпадению TIM_ClearITPendingBit(TIM1,TIM_IT_CC4); // сбрасываем флаг прерывания TIM1 по совпадению } NVIC_EnableIRQ(TIM1_CC_IRQn); // выключаем прерывания от таймера TIM_ITConfig(TIM1, TIM_IT_CC4, DISABLE); // TIM1->ARR = 40-1; // устанавливаем период 40 мкс TIM1->CCR4 = Test_Buf[0]; // ширину из массива для следующего импульса DMA1_Channel4->CNDTR = 4; // длина данных для DMA на 1 меньше т.к. уже установили выше 1 элемент TIM_DMACmd(TIM1,TIM_DMA_CC4,ENABLE); // разрешаем таймеру делать запрос к DMA по совпадению CCR DMA_Cmd(DMA1_Channel4, ENABLE); // включаем DMA } void Init_DMA(void) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // включаем тактирование DMA1 DMA_Setting.DMA_PeripheralBaseAddr = (uint32_t) &TIM1->CCR4; // куда копировать DMA_Setting.DMA_MemoryBaseAddr = (uint32_t) &Test_Buf[1]; // что копировать DMA_Setting.DMA_DIR = DMA_DIR_PeripheralDST; // копируем в периферию (Peripheral Destination, точка назначения - периферия) DMA_Setting.DMA_BufferSize = 0; // количество передаваемых данных DMA_Setting.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // адрес периферии постоянный DMA_Setting.DMA_MemoryInc = DMA_MemoryInc_Enable; // адрес в памяти увеличиваем DMA_Setting.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // периферия 16 бит DMA_Setting.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // массив 8 бит DMA_Setting.DMA_Mode = DMA_Mode_Normal; // режим обычный DMA_Setting.DMA_Priority = DMA_Priority_Medium; // приоритет средний DMA_Setting.DMA_M2M = DMA_M2M_Disable; // MemoryToMemory откл. DMA_Init(DMA1_Channel4, &DMA_Setting); // TIM1_CH4 относится к 4-му каналу DMA1 DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); // настраиваем прерывание по окончанию передачи NVIC_EnableIRQ(DMA1_Channel4_IRQn); // включаем прерывания от 4-го канала DMA1 DMA_Cmd(DMA1_Channel4, DISABLE); // пока выключаем 4-ый канал DMA1 } void DMA1_Channel4_IRQHandler(void) // закончили передавать { if (DMA_GetITStatus(DMA1_IT_TC4) != RESET) { // по совпадению DMA_ClearITPendingBit(DMA1_IT_TC4); // сбрасываем флаг прерывания DMA1 Channel4 transfer complete } if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET) { // по совпадению TIM_ClearITPendingBit(TIM1,TIM_IT_CC4); // сбрасываем флаг прерывания TIM1 на всякий случай } TIM1->ARR = 150-1; // вновь настраиваем на период 150 мкс TIM1->CCR4 = 0; // и ждем следующею передачу TIM1->CNT = 0; // TIM_DMACmd(TIM1,TIM_DMA_CC4,DISABLE); // всё выключаем DMA_Cmd(DMA1_Channel4, DISABLE); // TIM_Cmd(TIM1, DISABLE); // TIM_ITConfig(TIM1, TIM_IT_CC4, DISABLE); // TIM_CCxCmd(TIM1,TIM_Channel_4,TIM_CCx_Disable); } int main(void) { Init_GPIO(); Init_TIM_Transmit(); Init_DMA(); delay_ms(1000); while(1) { TIM1->CCR4 = 130-1; // до включения линия удерживается в 0 (CCR=0) TIM_ITConfig(TIM1, TIM_IT_CC4, ENABLE); TIM_CCxCmd(TIM1,TIM_Channel_4,TIM_CCx_Enable); TIM_Cmd(TIM1, ENABLE); delay_ms(100); } }  
      TEST_TIM_DMA.zip
    • By Grampus
      Добрый день!
      ПОМОГИТЕ ПОЖАЛУЙСТА!
      в описании для одного дисплея нашел код для STM на СИ
      там есть строчка которая мне не понятна, точнее смысл ее понятен но нет объявления аргументов функции
      помогите пожалуйста. В общем ситуация такая 
       
      spi_write ( DTA, 0x00 )                                     spi_write ( CMD, 0x01) 
      вот эта функция
      DTA - выполняет установку пина в 1 ,    CMD -  выполняет установку пина в 0 
      0x00 , 0x01, .........0xFF     это либо данные либо команда. 
       и все бы ничего но все это нужно передать по HAL_SPI_Transmit 
      помогите написать эту функцию с описанием аргументов и всех действий.
    • By voltex
      Всем привет! Подскажите, пожалуйста, как правильно считать данные с внешней eeprom по шине spi, в данном случае 25LC256.
      Написал код ссылаясь на даташит. Собрал схему в протеусе, подключил spi отладчик и вот что получил в итоге. Так же не могу проверить получается записать данные в память или нет. Весь код прикрепил.
       

      main.c
    • By aske12345
      Здравствуйте! Прошу помощи ! Столкнулся со следующей проблемой пытаюсь подключить к контроллеру по spi память FRAM FM25CL64 ,компилятор keil , пытаюсь записать одно число и его же считать, а осциллографом вижу, что считывается не то, что записывал. Пытался в разные ячейки памяти разные числа - считываются разные числа, но не те. Пишу 0x2F считывается 0x1С,  пишу 0xFF считывается 0xFE, пишу 0x99 считывается 0x20 - ерунда какая то. 
      Куски кода привел ниже:

      int main(void) {          SystemCoreClockUpdate();     SysTick_Config(SystemCoreClock/1000);//1ms     LEDs_ini();     Button_ini();     SPI3_FRAM_ini();         delay_ms(50);     //проверим FRAM начало запись 1 байта        CS_FRAM_ON();//        while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};        SPI_I2S_SendData(SPI3, 0x06);//Set Write Enable Latch 6        while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};        while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется        CS_FRAM_OFF();        delay_us(3);    //на самом деле задержка выходит около 500нс                CS_FRAM_ON();         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};     SPI_I2S_SendData(SPI3, 0x02);// Write              while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется     SPI_I2S_SendData(SPI3, 0x10);// 13 битный адрес         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется         SPI_I2S_SendData(SPI3, 0x00);// 13 битный адрес         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется     SPI_I2S_SendData(SPI3, 0x2F);// данные          while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется              CS_FRAM_OFF();         delay_us(3);//на самом деле задержка выходит около 500нс         //проверим FRAM конец запись  1 байта         //проверим FRAM начало чтение 1 байта         CS_FRAM_ON();//         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};     SPI_I2S_SendData(SPI3, 0x03);// Read              while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется     SPI_I2S_SendData(SPI3, 0x10);// 13 битный адрес         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется         SPI_I2S_SendData(SPI3, 0x00);// 13 битный адрес         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется     SPI_I2S_SendData(SPI3, 0x00);// пишем 0 для считывания         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE)== RESET){};         while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_BSY)== SET){};//ждем пока запишется         CS_FRAM_OFF(); //проверим FRAM конец чтение 1 байта              //LED1_OFF;          while(1)     {
      настройки spi:

      SPI_Init_user3.SPI_Direction = SPI_Direction_2Lines_FullDuplex;     SPI_Init_user3.SPI_Mode = SPI_Mode_Master;     SPI_Init_user3.SPI_DataSize = SPI_DataSize_8b;     SPI_Init_user3.SPI_CPOL = SPI_CPOL_High;//SPI_CPOL_Low     SPI_Init_user3.SPI_CPHA = SPI_CPHA_2Edge;     SPI_Init_user3.SPI_NSS = SPI_NSS_Soft;     SPI_Init_user3.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//4     SPI_Init_user3.SPI_FirstBit = SPI_FirstBit_MSB;         SPI_Init_user3.SPI_CRCPolynomial = 7;          SPI_Init(SPI3, &SPI_Init_user3);
      контакты вроде все пересмотрел, думал провода может длинноваты,  клок spi настраивал на разную частоту уменьшал до 1МГц - не влияет,  пробовал делать паузу между командой WREN и командой записи 15мс, а записью и считыванием 20мс, всё то же самое не помогло..
      приложил осциллограммы:
      Осциллограмма всех посылок  WREN, WITE, READ  (тактовый сигнал ch1 и miso FRAM ch2) (синий луч отношения к делу не имеет)
      Осциллограмма  команды WREN (тактовый сигнал ch1 и miso FRAM ch2)(синий луч отношения к делу не имеет)
      Осциллограмма  команды WITE (тактовый сигнал ch1 и miso FRAM ch2)
      Осциллограмма  считанного значения записывал 0x2F, считал 0x1C (тактовый сигнал ch1 и mosi FRAM ch2)
       




    • By User_1
      Доброго времени суток!
      Вкратце: нужно после того, как я записал байт данных в SPI1->DR, отменить передачу этого байта и вместо него отправить 0х00
      Подробно: Смысл вот в чём: некий контроллер, с которым я пытаюсь наладить общение по SPI, запрашивает произвольный участок массива байт и считывает их сплошным потоком. Ну примерно как считывается микросхема EEPROM: задаёшь начальный адрес, а потом просто шлёшь сплошные 0xFF, а она сама инкрементирует адрес и прямо непрерывным потоком байт выдаёт содержимое памяти. Только тут в роли этой микросхемы мой stm32f030 и мне нужно следующий байт отправлять в SPI1->DR сразу после отправки предыдущего. Но когда поток заканчивается (а он каждый раз разной длины и длина эта заранее неизвестна), один байт остаётся не переданным и отправится первым при следующем запросе. А мне нужно, чтобы первым байтом всегда отправлялся 0х00
      Пином (ну то есть битом) NSS управляю программно, его выставление в единичку и снова в ноль, очевидно, не помогает вообще никак. Пока решил проблему так: деинициализирую модуль SPI и выключаю его тактирование, затем включаю тактирование и снова инициализирую. Работает, скорости хватает. Но должно же быть менее костыльное решение?)
      Может кто сталкивался с такой проблемой?
      Курение даташита, reference manual и результатов поиска в гугле, не особо помогло.
  • Сообщения

    • Ссылки в теме и другие погрешности возникли после изменения сайта. Защита от обрыва на одном транзисторе это просто, думаю не лишняя будет на всякий случай. Потребление тока от 12 В первой версией с генератором тока ( схема ниже) примерно до 50 мА. С изменением схемы ток тоже может измениться. Защита входа U3 в архиве "первая версия", ссылка выше,  есть текст там написано. "В режиме КЗ при установленном высоком напряжение на выходе БП , напряжение на управляющем электроде U1 приближается к +12В, Напряжение на резисторе R5 тоже увеличивается ( на 2,5 В меньше чем на управляющем) Ток через R5 и U1 увеличивается, U1 и R5 начинают нагреваться.  
      Допустим на БП выставлен 1 В, а вы подключили аккумулятор для подзарядки на 12 В или больше. VT1 ограничивает падение напряжения на управляющем U1 до -0,6 В от напряжения на управляющем U2.
      Транзисторы VT1 и VT2 ограничивают изменение напряжения на управляющем U1 +- 0,6 В от напряжения на управляющем U2. В  режиме стабилизации напряжения на работу схемы они не влияют." Резистор до шунта. Там же есть картинки с минуса выхода БП на эмиттер силового. Но  это не решает всех проблем. Токи через шунт все равно остаются и для амперметра на этом шунте показания прибора на малых токах будут не верными. Есть замена этому резистору это генератор тока. Но тоже ток генератора будет идти через шунт транзистора. Схема не есть окончательный вариант. Каждый может адаптировать ее для себя по своим запросам, и возможностям.  Результат желательно показать в теме, возможно получится удачная схема и кому то пригодится.   V1 ген. тока.spl7  
    • Пробовал я менять, да и катушку другую ставил, снайперку дд 5,5, с ней тоже балаболит, а она по частоте на килогерц меньше(7кгц) При чем если прибор отстроится от феррита не правильно эти сектора смещаются по шкале в другое место. А вот без катушки прибор ведёт себя совсем тихо. Может какие нибудь стабилизаторы так шумят? ( очень много писали про шум стабилизаторов особенно в квазар авр, там TL шумела, но я не знаю как шум стабилизатора выглядит, может это он и есть?)
    • Вот и хорошо, не надо упираться доказывать. Всем не угодишь. Главное делаешь сам, а опыт только так и бывает. Хочу представить пробную лампочку такого типа: Схема хорошо работает до 30 ма и только с большим кол-вом светодиодов, т.к. "лишнее" V рассеивается на транзисторе а у него есть максимальная мощность, рассеиваемая коллектором. Резистор 47 ком необходим на случай обрыва цепи 2К 4Watt. Лампа плавно зажигается и абсолютно не мерцает. Транзистор приклеен к алюм. пластинке суперклеем и взят от старого компьютерного БП. Собрано несколько светильников по подобной схеме, работают в гаражах. Где постоянно варят сваркой и простые газонаполненные лампы мерцают аж невозможно. Здесь схема хорошо работает до 100 ма, т.к. корпус является радиатором. Мощный резистор собирается из нескольких МЛТ 2Wt.   4 светильника сделал, людям понравилось - ещё 6 шт. на подходе. Схемы с электронным балластом в условиях сильных скачков V просто сгорают. Далее хотел показать как можно сделать лампочку из прожекторного диода, правда об экономичности тут понятно лучше умолчать. Важен сам процесс. :-)   Радиатором для мощного LED диода является неисправный мощный прожекторный диод, конденсаторы из старых компьютерных БП, СМД диоды из старой платы ну и конечно скотч, куда же без него. :-)
    • мне она не нужна, это Вы пытались доказывать опираясь на её. я такого не писал, а лишь указал на то, что так уменьшается ресурс работы компонентов. теория она же из практики следует... и не Вы один конденсаторные источники применяете... хотите я Вам xls-ку составлю, для расчёта балластного конденсатора? - чтоб Вы так не расстраивались от общения со мной...
    • еще я забыл сказать, что я там под шкалой провел горизонтальную черту. этим я ограничил рабочее поле при масштабировании. а то с увеличением масштаба бесполезно масштабировалось и всё пустое поле под шкалой.
    • Всё верно. Я своё решение применяю как раз к "халявным" шуруповёртам. В ситуации когда покупается новый "шурик", а старый приносят мне. Чего добру пропадать. И другу можно подарить. Внутри батарею разрываю и вывожу провода. На снимке как раз подаренный мне шуруповёрт.
    •   Лу́нный за́говор» — теория заговора, центральную идею которой представляет собой утверждение, что во времена «лунной гонки» в ходе американскойкосмической программы «Аполлон» (1969—1972) высадка людей на Луну не производилась, а фотографии, киносъёмки и другие документальные материалы лунных экспедиций были сфальсифицированы правительством США. Теория лунного заговора неоднократно была объектом критики со стороны комиссии РАН по борьбе с лженаукой,  где её сторонники ставятся в один ряд с последователями новой хронологии Фоменко.