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

Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 10:48:40

Доброго дня уважаемые инженеры.
Столкнулся с проблемой связанной с появлением фазового сдвига на ШИМ сигналах.
Задача: Получить два синхронных сигнала прямоугольной формы частотой 8КГц и 1024КГц соответственно на PD.15 и PC.9 контроллера STM32F107.
Реализация: Синхронизируем таймеры TIM3 и TIM4 от таймера TIM1 (TIM1 - master, TIM3,TIM4 - slave). С таймеров TIM3 и TIM4 выводим 50% ШИМ сигнал на нужные ноги
Проблема: На выходных сигналах появляется сдвиг фазы на 500нС

Сигналы называются CLK и SYNK
Для чистоты эксперимента пытаюсь вывести два одинаковых сигнала частотой 8КГц и наблюдаю сдвиг.

.h файл:
Код:
#define Si3210_SYNC_PIN                    GPIO_Pin_15                   /* PD.15 */
#define Si3210_SYNC_GPIO_PORT              GPIOD                       /* GPIOD */
#define Si3210_SYNC_GPIO_CLK               RCC_APB2Periph_GPIOD

#define Si3210_CLK_PIN                 GPIO_Pin_9                     /* PC.9  */
#define Si3210_CLK_GPIO_PORT           GPIOC                          /* GPIOC */
#define Si3210_CLK_GPIO_CLK            RCC_APB2Periph_GPIOC

#define Si3210_TIM3                       TIM3
#define Si3210_TIM_CLK                   RCC_APB1Periph_TIM3

#define Si3210_TIM4                       TIM4
#define Si3210_TIM_SYNC                  RCC_APB1Periph_TIM4


.с файл:
Код:
void PWM_Sync_CLK_Init(void)

 
    // подаем тактовую частоту на таймер порта С
    RCC_APB1PeriphClockCmd(Si3210_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(Si3210_CLK_GPIO_CLK, ENABLE);
 
    // подаем тактовую частоту на таймер порта D
    RCC_APB1PeriphClockCmd(Si3210_TIM_SYNC, ENABLE);
    RCC_APB2PeriphClockCmd(Si3210_SYNC_GPIO_CLK, ENABLE);
 
    RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //под вопросом
 
//************************ внастраеваем выводы таймеров ************************
    GPIO_InitStructure.GPIO_Pin = Si3210_SYNC_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(Si3210_SYNC_GPIO_PORT, &GPIO_InitStructure);
 
    GPIO_InitStructure.GPIO_Pin = Si3210_CLK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(Si3210_CLK_GPIO_PORT, &GPIO_InitStructure);
//************** закончили внастраивать выводы таймеров ************************
 
    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //включение альтернативной функции
    GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);     //включение альтернативной функции

    // Конфигурация таймера
    TIM_TimeBaseInitTypeDef TIM_BaseConfig;
    // Конфигурация выхода таймера
    TIM_OCInitTypeDef TIM_OCConfig;
    // конфигурируем что то там для TIM1
    //TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
   
//************************ведущий таймер Т1*************************************
    TIM_BaseConfig.TIM_Prescaler = 0;
    TIM_BaseConfig.TIM_Period = 4;
    TIM_BaseConfig.TIM_ClockDivision = 0;
    // Отсчет от нуля до TIM_Period
    TIM_BaseConfig.TIM_CounterMode = TIM_CounterMode_Up;
    // Инициализирум таймер №3 (его выходы как раз на порту С)
    TIM_TimeBaseInit(TIM1, &TIM_BaseConfig);
   
//******************************************************************************
    // Automatic Output enable, Break, dead time and lock configuration
    //TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
    //TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
    //TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
    //TIM_BDTRInitStructure.TIM_DeadTime = 200;//5;
    //TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
    //TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
    //TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
   
//******************************************************************************           
    //Select the Master Slave Mode
    TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
 
    //TIM1->SMCR |= 0x0080; //ручная установка бита MSM в регистр SMCR
    //Master Mode selection
    TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);

//*********************** закончили с Т1****************************************
   
//***************************  CLK на TIM3 *************************************
    TIM_BaseConfig.TIM_Prescaler = 9; 
    TIM_BaseConfig.TIM_Period = 179;
    TIM_BaseConfig.TIM_ClockDivision = 0;
    //TIM_BaseConfig.TIM_RepetitionCounter = 4;
    // Отсчет от нуля до TIM_Period
    TIM_BaseConfig.TIM_CounterMode = TIM_CounterMode_Up;
    // Инициализирум таймер №3 (его выходы как раз на порту С)
    TIM_TimeBaseInit(Si3210_TIM3, &TIM_BaseConfig);
//******************************************************************************   
    // Конфигурируем выход таймера, режим - PWM1
    TIM_OCConfig.TIM_OCMode = TIM_OCMode_PWM1;
    // Собственно - выход включен
    TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable;
    // Пульс длинной 250 тактов => 7/14 = 50%
    TIM_OCConfig.TIM_Pulse = 90;
    // Полярность => пульс - это единица (+3.3V)
    TIM_OCConfig.TIM_OCPolarity = TIM_OCPolarity_High;
    // инициализируем третий выход таймера №3
    TIM_OC4Init(Si3210_TIM3, &TIM_OCConfig);
       
    //Slave Mode selection: TIM3
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
    TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);
    //TIM3->SMCR |= 0x0080;
//******************************************************************************
    //TIM_OC3PreloadConfig(Si3210_TIM3, TIM_OCPreload_Enable);
    //TIM_OC4PreloadConfig(Si3210_TIM3, TIM_OCPreload_Enable);
    //TIM_ARRPreloadConfig(Si3210_TIM3, ENABLE); 
//****************** закончили с CLK на TIM3 ***********************************
//******************************  SYNC на TIM4  ********************************
    TIM_BaseConfig.TIM_Prescaler = 9;
    TIM_BaseConfig.TIM_Period = 179; //499;
    TIM_BaseConfig.TIM_ClockDivision = 0;
    //TIM_BaseConfig.TIM_RepetitionCounter = 4;
    // Отсчет от нуля до TIM_Period
    TIM_BaseConfig.TIM_CounterMode = TIM_CounterMode_Up;
    // Инициализирум таймер №3 (его выходы как раз на порту D)
    TIM_TimeBaseInit(Si3210_TIM4, &TIM_BaseConfig);
//******************************************************************************   
    // Конфигурируем выход таймера, режим - PWM1
    TIM_OCConfig.TIM_OCMode = TIM_OCMode_PWM1;
    // Собственно - выход включен
    TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable;
    // Пульс длинной 250 тактов => 250/500 = 50%
    TIM_OCConfig.TIM_Pulse = 90;
    // Полярность => пульс - это единица (+3.3V)
    TIM_OCConfig.TIM_OCPolarity = TIM_OCPolarity_High;  //TIM_OCPolarity_High;
    // инициализируем третий выход таймера №3
    TIM_OC4Init(Si3210_TIM4, &TIM_OCConfig);

    //Slave Mode selection: TIM3
    TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated);
    TIM_SelectInputTrigger(TIM4, TIM_TS_ITR0);
    //TIM4->SMCR |= 0x0080; 
    // Как я понял - автоматическая перезарядка таймера, если не прав -поправте.
    //TIM_OC3PreloadConfig(Si3210_TIM4, TIM_OCPreload_Enable);
    //TIM_OC4PreloadConfig(Si3210_TIM4, TIM_OCPreload_Enable);
    //TIM_ARRPreloadConfig(Si3210_TIM4, ENABLE);
//******************* закончили с SYNC на TIM4  ********************************
   
  // Обнуляем таймерыв, неуверен что надо, но пусть будет на всякий случай 
  //TIM_SetCounter(TIM1, 0);
  //TIM_SetCounter(TIM3, 0);
  //TIM_SetCounter(TIM4, 0);
 
//******************* запускаем TIM1 TIM3 TIM4  ******************************** 
  TIM_Cmd(TIM1, ENABLE);       // Включаем таймер №3.
  TIM_Cmd(TIM3, ENABLE);       // Включаем таймер №3.
  TIM_Cmd(TIM4, ENABLE);       // Включаем таймер №4.
 
  // Main Output Enable
  //TIM_CtrlPWMOutputs(TIM1, ENABLE); // вроде это включает перефирию TIM1 но в данном случае она не нужна 
}


Собственно что я вижу на осциллографе:

В общем виде
Изображение

Фронты
Изображение

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

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 14:34:11

Попробуйте поменять местами кусок программы с TIM3 на кусок программы с TIM4, я на 99% уверен, что фронты поменяются местами, если это действительно так произойдет, тогда ван нужно стараться выводить сигналы почти одновременно, а не по очереди, для этого нужно както объединить эти куски программы в один.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 14:55:33

zero648 писал(а):Попробуйте поменять местами кусок программы с TIM3 на кусок программы с TIM4, я на 99% уверен, что фронты поменяются местами, если это действительно так произойдет, тогда ван нужно стараться выводить сигналы почти одновременно, а не по очереди, для этого нужно както объединить эти куски программы в один.


Я на 100% уверен что нет! ВО первых эти "куски" программы это всего лишь запись параметров в перефирию (в таймеры). Последовательность не имеет значение (у каждого таймера свои регистры). запуск производится СИНХРОННО.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 15:04:35

А вы все таки попробуйте поменять кучки программы включения таймеров 3 и 4.
А также попробуйте включить 1 таймер последним.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 15:08:32

sokl писал(а):Я на 100% уверен что нет!

А я на 100% уверен, что если написать всё правильно, то будет абсолютная синхронность...
Если у вас всё правильно настроено, то нужно сначала разрешать работу TIM3 и TIM4, а потом только TIM1... он синхронизирует...
Если до запуска TIM1 стартует самопроизвольно TIM3 или TIM4, то что-то не так в настройках...

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 15:10:08

попробуйте сначала включить Т3 и Т4, а потом только Т1.
больше ничего в глаза не бросается.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Ср дек 05, 2012 21:20:04

Это ерунда, синхронизация происходит чаще чем вы думаете господа коты. Синхронизация происходит по переполнению TIM1, каждый его цикл!!! и таймеры не стартуют когда их запускают в этой ситуации, они стартуют от TIM1, и пока он не начнет их тактировать, ничего не произойдет. Но для успокоения совести я попробовал, и естественно чуда не случилось.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Пт дек 07, 2012 10:25:08

1800*8к = 14.4 MHz - тактовая счетчика. Один отстает от другого на 7 тактов. Если бы это был счетчик, то зедержка была бы кратна 10. А так застревание может происходить в прескалере.
Попробуйте убрать прескалер в счетчике и вместо 10 прескалер и 180 счетчик поставить прескалер 1 и 1800 счетчик. Если сработает, то это будет означать, что гейтится счетчик, а на прескалер синал гейта не оказывает влияния.
Воторой вариант опробирования использовать не gate, а старт или сброс обеих таймеров. Вроде в этом случае вроде должен сбрасываться и прескалер.
Вы написали, что опробовали все варианты. Каков был результат обмена запуска TIM3 и TIM4?
Если есть возможность, отпишитесь, что получилось.

Re: Фазовый сдвиг ШИМ сигнала STM32F107

Пн дек 10, 2012 22:09:28

Galizin писал(а):1800*8к = 14.4 MHz - тактовая счетчика. Один отстает от другого на 7 тактов. Если бы это был счетчик, то зедержка была бы кратна 10. А так застревание может происходить в прескалере.
Попробуйте убрать прескалер в счетчике и вместо 10 прескалер и 180 счетчик поставить прескалер 1 и 1800 счетчик. Если сработает, то это будет означать, что гейтится счетчик, а на прескалер синал гейта не оказывает влияния.
Воторой вариант опробирования использовать не gate, а старт или сброс обеих таймеров. Вроде в этом случае вроде должен сбрасываться и прескалер.
Вы написали, что опробовали все варианты. Каков был результат обмена запуска TIM3 и TIM4?
Если есть возможность, отпишитесь, что получилось.


Спасибо за подсказку, я попробую чуть попозже, по результатам обязательно отпишусь.
Ответить