Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 16:23:09

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

Что с этой схемой не так? По-моему полностью независимое от ядра поведение. Ну, кроме однократной настройки, конечно. Слишком много разбираться и читать придётся? Ну тут уж извините, судьба такая, жизнь - боль, чему быть, того не миновать, б-г терпел и нам велел и прочие мотивирующие цитаты великих людей.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 16:24:34

DmitryR, нафиг эти навороченные дорогущие МК, если есть одноплатники дешевые? И там - нормальный линукс, а не убогий lwip поверх убогой же ртоси.
Кстати, lwip можно и без ртоси запускать, если что.
Но все равно я считаю, что ethernet на МК - это маразм.
Я вот сделал себе нашлепку на orange pi zero2, чтобы туда SPI/I2C/UART и еще кое-чего подключать (все с защитой от ESD, а то "из коробки" там даже USB не защищены!). Заодно там и DC-DC сделал, понижающий с 12В до 5В, чтобы питать эту штуку (а то 5В тащить на улицу - наверняка просядет на длинных проводах, а с 12В все ОК: пусть хоть до 7В просаживается, DC-DC этого хватит). Еще хочу другую нашлепку сделать: с микроконтроллером, чтобы можно было дополнить функционал одноплатника тем, чего он делать уж точно не умеет (АЦП/ЦАП, таймеры, CAN и т.д., и т.п.).

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 17:45:11

Одна только проблема с этим: как только отрабатывают все 3 тайминга (50, 50 и 500 мксек), выставляем низкий уровень и при следующем EXTI у нас первые 50 мк сек опять должны быть HIGH, но они будут LOW, и из-за этого все уровни поменяются местами и так будет происходить циклично
Ничего подобного. Вы плохо понимаете работу режима PWM. В этом режиме если значение счётчика меньше содержимого регистра сравнения CR - на выходе одно значение (0 или 1), если больше CR - другое. Так что - как только новый период PWM запустится, на выходе будет тот же уровень, который был в начале прошлого периода. А для состояния остановленного таймера есть регистр, задающий пассивное состояние выхода: запишете туда 0 и будет на выходе 0, пока ожидается следующий сигнал запуска (такой регистр есть в XMC, насчёт STM32 - не уверен).
Последний раз редактировалось jcxz Ср окт 12, 2022 18:01:26, всего редактировалось 1 раз.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 17:56:03

разве связка TIM DMA в режиме burst не решает эту задачу? вроде должно получится, и никаких прерываний. Собственно, я думал, что Eddy_Em это в начале и предлагал.
а по SPI - я по неопытности опасаюсь там джиттер начала пачки будет. хотя если от TIM и тактировать ... и да мертвый хвост ((16-12)х50) остается. а еще надо, чтоб SPI умел константу автоотправлять. ;)
Последний раз редактировалось a797945 Ср окт 12, 2022 18:27:49, всего редактировалось 4 раз(а).

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 17:56:36

Ну и еще раз напомню о DMA. А также, видимо, мимо пролетело: было же предложение SPI или I2C использовать, чтобы данную последовательность импульсов воспроизвести.
DMA здесь - как мёртвому припарка, потому как за 100мкс можно успеть записать все необходимые теневые регистры даже если МК работает на 1МГц тактовой.
Касательно SPI: разве SPI STM32 умеет работать с 12-битными словами? И как запускать процесс предлагаете? Каковы будут задержки от момента запуска до первого фронта и от момента последнего спада до возможности нового запуска? SPI - имхо, бесперспективная затея, по крайней мере на STM32.
А I2C - вам следует сперва изучить что это такое, прежде чем нести чушь.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 18:10:00

А I2C - вам следует сперва изучить что это такое, прежде чем нести чушь.

Да, там же требуется от слейва ACK. Еще и старт-стоп... Не взлетит.

Re: Аппаратное управление таймером состоянием вывода

Ср окт 12, 2022 19:51:18

Касательно SPI: разве SPI STM32 умеет работать с 12-битными словами? И как запускать процесс предлагаете? Каковы будут задержки от момента запуска до первого фронта и от момента последнего спада до возможности нового запуска?

SPI 12 бит умеет. Задержки конечно будут.
На сколько допустимы ошибки по времени DmitryR не озвучил.
Самое быстрое, полностью аппаратное решение - два таймера и объединённые выходные пины "открытый сток" + резистор + буфер по вкусу. Если нет требований по малому времени нарастания, то можно обойтись и без буфера. Резистор можно заменить пулл-апами.

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 06:50:01

Andrey_B,
Самое быстрое, полностью аппаратное решение - два таймера и объединённые выходные пины "открытый сток" + резистор + буфер по вкусу

Или поставить микросхему 2ИЛИ

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 10:10:17

Почти сделал на двух таймерах (правда, на F1, но какая разница), но столкнулся с проблемой: в режиме PWM2 до достижения CCR уровень низкий, а надо наоборот. Если же перевести в режим PWM1, то в неактивном состоянии уровень высокий, что тоже не подходит. Как сделать так, чтобы в состоянии "покоя" выход был низкий, при старте таймера как бы работал в режиме PWM2 (то есть высокий уровень ДО достижения CCR), а после сброса CEN снова выход переходил в низкий уровень?
Последний раз редактировалось azhel12 Чт окт 13, 2022 10:34:00, всего редактировалось 1 раз.

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 10:29:46

нашел очень интересный момент:
Режим объединения входов по XOR

Для таймеров TIM2 — TIM5 существует возможность подавать на вход фильтра первого входного канала комбинированный по XOR сигнал от входов TIMx_CH1, TIMx_CH2, TIMx_CH3. Эта фишка используется при подключении интерфейсов датчиков Холла (подробности в RM0008, глава 14.3.18, стр.327).

Для выбора этой опции нужно установить в 1 бит TI1S.


Насколько я понял на данный момент, можно на 2 канала таймера завести 2 сигнала и получить 3й сигнал, соответствующий логической таблице для элемента XOR

Если это так, то по сути это:
Самое быстрое, полностью аппаратное решение - два таймера и объединённые выходные пины "открытый сток" + резистор + буфер по вкусу.

Но с прогонкой через логический элемент

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 12:27:46

azhel12, полярность выхода же задаётся.
Изображение
изображение_2022-10-13_122708177.png
(18.87 KiB) Скачиваний: 319

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 16:47:06

полярность выхода же задаётся.
Да, но когда таймер неактивен (CEN=0), выход находится в неактивном уровне, то есть в режиме ActiveLow это будет высокий, что не подходит.

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 16:57:06

Так по началу периода поднимать ногу, по сравнению опускать. Вот и получится искомое.

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 17:07:09

Я бы вообще поставил OPM на 600 мкс. На 50 мкс CM1 поменяет состояние ноги. Где-нибудь на 60 мкс войти в прерывание по CM2, отключить выход от таймера, перепрограммировать CM1 на 100 мкс и подключить выход обратно. Мне думается, на одном таймере всё получится.

Re: Аппаратное управление таймером состоянием вывода

Чт окт 13, 2022 17:26:11

Я бы вообще поставил OPM на 600 мкс. На 50 мкс CM1 поменяет состояние ноги. Где-нибудь на 60 мкс войти в прерывание по CM2, отключить выход от таймера, перепрограммировать CM1 на 100 мкс и подключить выход обратно. Мне думается, на одном таймере всё получится.
На двух получилось вообще без обработчика (с выключенным таймером только разобраться надо), но это, конечно, чисто академический интерес, наверно, оно того и не стоит.

Re: Аппаратное управление таймером состоянием вывода

Пт окт 14, 2022 09:34:38

DmitryR, входящие импульсы идут постоянно или возможны большие паузы?
и минимальная пауза между ними сколько?

Добавлено after 9 hours 15 minutes 55 seconds:
заглянул в RM0385. здесь богаче чем в RM0008 :)
два таймера, старт синхронно, выходы как бы "монтажным ИЛИ",
1 таймер в режиме по "22.3.20 Retriggerable one pulse mode (OPM)" - первые 50мкс,
2 таймер в режиме по "22.3.19 One-pulse mode" - задержка 100 импульс 500 мкс.
можно второй таймер от первого с соответствующе корректировкой задержки.
вроде должно взлететь
если есть возможность прикрутить "22.3.17 Clearing the OCxREF signal on an external event" можно вырезать "дырку" таймером 2 в импульсе таймера 1 (1 таймер 600мкс, 2 таймер з.50 и.50 мкс) - не понадобится "монтажное ИЛИ".

можно еще попробовать SPI тактируя от TIM , TIM чтоб все в нужное время было, SPI содержание этого "все"

Re: Аппаратное управление таймером состоянием вывода

Вт янв 17, 2023 14:47:26

На время откладывал решение этого вопроса. Но чтобы решение этого тут присутствовало, напишу. Сейчас перечитывать не стану, возможно это решение или схожее было кем-то предложено в ходе обсуждения.

Суть:
Таймер запускается по внешнему сигналу. Запускается как ШИМ с разрешенным перезапуском. Чтобы сформировать первые 50 мксек необходимо поставить у таймера CCR = 1 и ARR = 5000. В таком случае первый положительный импульс будет запускаться с 0, в противном случае он уже сразу запустится с высокого уровня, что недопустимо. Далее по окончанию первого цикла ШИМ вызывается коллбек HAL_TIM_PeriodElapsedCallback, в котором CCR меняется на 5000 и увеличивается ARR. Таким образом будет сформирован второй импульс 50 мксек. В это время пропускаем первый вход в коллбек HAL_TIM_PWM_PulseFinishedCallback и при втоором входе в него останавливаем таймер. Теперь останется через некоторое необходимое время опять запустить таймер и вернуть настройки CCR и ARR к первоначальным 1 и 5000.

Код:
Код:
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM2;
  sConfigOC.Pulse = 1;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

// Запускаем таймер
TIM2->CNT = 0;
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM1) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
  else if (htim->Instance == TIM2)
  {
     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_7);

     TIM2->CCR2 = 4999;
     TIM2->ARR = 9999;
  }
  else
  {
     __NOP();
  }
  /* USER CODE END Callback 1 */
}

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
   if(htim->Instance == TIM2)
   {
      if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
      {
         if(i == 0)
         {
            i++;
         }
         else
         {
            i = 0;

            HAL_TIM_Base_Stop_IT(&htim2);
            HAL_TIM_PWM_Stop_IT(&htim2, TIM_CHANNEL_2);
         }
      }
      else
      {
         __NOP();
      }
   }
   else if(htim->Instance == TIM5)
   {
      LL_TIM_SetCounter(TIM7, 0);
      LL_TIM_EnableIT_UPDATE(TIM7);
      LL_TIM_EnableCounter(TIM7);
   }
   else
   {
      __NOP();
   }
}

void TIM7_Callback(void)
{
   if(LL_TIM_IsActiveFlag_UPDATE(TIM7))
   {
      TIM2->CNT = 0;

      TIM2->CCR2 = 1;
      TIM2->ARR = 4999;
      TIM2->EGR = TIM_EGR_UG;

      HAL_TIM_Base_Start_IT(&htim2);
      HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_2);

      LL_TIM_ClearFlag_UPDATE(TIM7);
   }
   else
   {
      __NOP();
   }
}
Вложения
155.png
(12.58 KiB) Скачиваний: 28
Ответить