- в каких задачах применима синхронизация каналов ШИМ;Добрый день!
Можно. Только распишите, пожалуйста, поподробнее что именно вы хотели бы увидеть.
- механизм реализации на микроконтроллере;
- результат (временная диаграмма...)
Модераторы: ea, dav, bkolbov, Alis, pip, _sva_
- в каких задачах применима синхронизация каналов ШИМ;Добрый день!
Можно. Только распишите, пожалуйста, поподробнее что именно вы хотели бы увидеть.
При управлении единым устройством с несколькими силовыми ключами для обеспечения согласованного управления. Обычно синхронизируются несущие таймеры, генерирующие ШИМ, чтобы они работали синхронно. Задавая разные уставки сравнения можно получить желаемый ШИМ. Например, для трехфазного двигателя для векторной, скалярной да и любой другой ШИМ все три таймера обычно синхронизируются вместе без сдвига.-в каких задачах применима синхронизация каналов ШИМ;
Внутри микроконтроллера ШИМы устроены в виде независимых блоков, каждый из которых имеет свой таймер и управляет двумя выходами (двумя ключами). Для шестиключевого инвертора напряжения, например, задействуются три таких блока. Для одновременной работы таймеров используется сигнал синхронизации: можно сконфигурировать, какой блок ШИМ испускает синхросигнал, какие принимают. Например, первый блок ШИМ может испускать синхросигнал по событию обнуления, а остальные блоки по его приему также обнулять свои счетчики. Это самая простая типовая настройка. Также можно синхронизировать ШИМы между двумя разными контролерами, синхросигнал может быть и внешним. Также можно разнести таймеры по фазе, используя регистр фазового сдвига по приему сигнала синхронизации.- механизм реализации на микроконтроллере;
Здравствуйте.Лашкевич писал(а): ↑19 апр 2017, 18:27 Пример инициализации модулей ШИМ для работы с трехфазным двигателем:Код: Выделить всё
NT_COMMON_REG->PWM_SYNC_bit.TBCLKSYNC = 0; //синхронизация таймеров - сброс внутренних счетчиков /* Синхронизировать ШИМы */ NT_COMMON_REG->PWM_CTRL = 0x8; // ------------------------------------------------------------------------ // Настраиваем модуль ePWM1 // ------------------------------------------------------------------------ if (p->Frequency < PWM_FREQ_MIN) p->Frequency = PWM_FREQ_MIN; if (p->Frequency > PWM_FREQ_MAX) p->Frequency = PWM_FREQ_MAX; NT_PWM0->TBPRD = _IQ10div(_IQ10(CORE_CLK/1000.0), p->Frequency << 1) >> 10; //период p->k_pwm = NT_PWM0->TBPRD; p->FreqPrev = p->Frequency; //предыдущая частота NT_PWM0->TBPHS_bit.TBPHS = 0x0000; // Phase is 0 NT_PWM0->TBCTR = 0x0000; // Clear counter // Setup counter mode NT_PWM0->TBCTL_bit.PRDLD = TB_SHADOW; // загрузка TBPRD при TBCTR = 0 NT_PWM0->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down NT_PWM0->TBCTL_bit.PHSEN = TB_DISABLE; // Disable phase loading NT_PWM0->TBCTL_bit.PHSDIR = TB_UP; // Считать вверх после загрузки фазы NT_PWM0->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale NT_PWM0->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale NT_PWM0->TBCTL_bit.SYNCOSEL = TB_CTR_ZERO; // выдаём синхро-сигнал при TBCTR = 0 // Setup shadowing NT_PWM0->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM0->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero NT_PWM0->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM0->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero // Set Compare values NT_PWM0->CMPA_bit.CMPA = 0; // Set compare A value // Set actions NT_PWM0->AQCTLA = AQ_EPWM_DISABLE; // для начала события для PWM1A запрещены NT_PWM0->AQCTLA_bit.ZRO = 1; //обнуляем при нуле счетчика NT_PWM0->AQCTLA_bit.CAU = 2; //включаем при сравнении и инкрементиовании NT_PWM0->AQCTLA_bit.CAD = 1; //обнуляем при сравнении и декрементровании //Для PWMB тоже самое, что для PWMА. Без инверсии. Инверсия далее в модуле МВ NT_PWM0->AQCTLB = NT_PWM0->AQCTLA; // для начала события для PWM1B запрещены NT_PWM0->AQCTLB_bit.ZRO = NT_PWM0->AQCTLA_bit.ZRO; //обнуляем при нуле счетчика NT_PWM0->AQCTLB_bit.CAU = NT_PWM0->AQCTLA_bit.CAU; //включаем при сравнении и инкрементиовании NT_PWM0->AQCTLB_bit.CAD = NT_PWM0->AQCTLA_bit.CAD; //обнуляем при сравнении и декрементровании NT_PWM0->AQSFRC_bit.RLDCSF = 3; //реагировать на софтвенную привязку ног без теневого регистра // Setup Deadband // DBRED = DBFED = 150 * Tм_мкс / 4 NT_PWM0->DBRED = _IQ4mpy(_IQ4(150 / 4), p->DeadBand >> 20) >> 4; NT_PWM0->DBFED = NT_PWM0->DBRED; NT_PWM0->DBCTL_bit.IN_MODE = DBA_RED_DBB_FED; //s4=0, s5=1 на картинке DT NT_PWM0->DBCTL_bit.OUT_MODE = DB_FULL_ENABLE; //S1=1, S2=2 на картинке DT NT_PWM0->DBCTL_bit.POLSEL = DB_ACTV_HIC; // PWM1B = !PWM1A; S2=0, S3=1 NT_PWM0->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT (шимовское) NT_PWM0->ETSEL_bit.INTEN = 0; // Disable INT NT_PWM0->TBCTL_bit.FREE_SOFT = 0; //разрешаем TZ быть источником аппаратной аварии (one-shot) // NT_PWM0->TZSEL_bit.OSHT1 = TZ_ENABLE; // NT_PWM0->TZSEL_bit.OSHT2 = TZ_ENABLE; // NT_PWM0->TZSEL_bit.OSHT3 = TZ_ENABLE; // Trip-Zone NT_PWM0->TZCTL_bit.TZA = TZ_STATE; // по событию "One-Shot Trip" переводим NT_PWM0->TZCTL_bit.TZB = TZ_STATE; // ШИМ выходы в нужное состояние //Для VectorCARD от ШИМа запускается ADC //NT_PWM0->ETSEL_bit.SOCAEN = 1; // Разрешить запуск ацп //NT_PWM0->ETSEL_bit.SOCASEL = 1; // Запускать при CTR == 0 (Underflow) // ------------------------------------------------------------------------ // Настраиваем модуль ePWM2 // ------------------------------------------------------------------------ // Setup TBCLK NT_PWM1->TBPRD = NT_PWM0->TBPRD; //период такой же NT_PWM1->TBPHS_bit.TBPHS = 0x0001; // Фаза равна 1 из-за баги в проце (0 не работает) NT_PWM1->TBCTR = 0x0000; // Clear counter // Setup counter mode NT_PWM1->TBCTL_bit.PRDLD = TB_SHADOW; // загрузка TBPRD при TBCTR = 0 NT_PWM1->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down NT_PWM1->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading NT_PWM1->TBCTL_bit.PHSDIR = TB_UP; // Считать вверх после загрузки фазы NT_PWM1->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale NT_PWM1->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale NT_PWM1->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // пропускаем синхро-сигнал "насквозь" // Setup shadowing NT_PWM1->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM1->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero NT_PWM1->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM1->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero // Set Compare values NT_PWM1->CMPA_bit.CMPA = 0; // Set compare A value // Set actions NT_PWM1->AQCTLA = AQ_EPWM_DISABLE; // для начала события запрещены NT_PWM1->AQCTLA_bit.ZRO = 1; //обнуляем при нуле счетчика NT_PWM1->AQCTLA_bit.CAU = 2; //включаем при сравнении и инкрементиовании NT_PWM1->AQCTLA_bit.CAD = 1; //обнуляем при сравнении и декрементровании //Для PWMB тоже самое, что для PWMА. Без инверсии. Инверсия далее в модуле МВ NT_PWM1->AQCTLB = NT_PWM0->AQCTLA; // для начала события для PWM1B запрещены NT_PWM1->AQCTLB_bit.ZRO = NT_PWM0->AQCTLA_bit.ZRO; //обнуляем при нуле счетчика NT_PWM1->AQCTLB_bit.CAU = NT_PWM0->AQCTLA_bit.CAU; //включаем при сравнении и инкрементиовании NT_PWM1->AQCTLB_bit.CAD = NT_PWM0->AQCTLA_bit.CAD; //обнуляем при сравнении и декрементровании NT_PWM1->AQSFRC_bit.RLDCSF = 3; //реагировать на софтвенную привязку ног без теневого регистра // Active high complementary PWMs - Setup Deadband NT_PWM1->DBRED = NT_PWM0->DBRED; NT_PWM1->DBFED = NT_PWM1->DBRED; NT_PWM1->DBCTL_bit.IN_MODE = NT_PWM0->DBCTL_bit.IN_MODE; NT_PWM1->DBCTL_bit.OUT_MODE = NT_PWM0->DBCTL_bit.OUT_MODE; NT_PWM1->DBCTL_bit.POLSEL = NT_PWM0->DBCTL_bit.POLSEL; // Interrupt where we will change the Compare Values NT_PWM1->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT NT_PWM1->ETSEL_bit.INTEN = 0; // Disable INT NT_PWM1->TBCTL_bit.FREE_SOFT = 0; //разрешаем TZ быть источником аппаратной аварии (one-shot) // NT_PWM1->TZSEL_bit.OSHT1 = TZ_ENABLE; // NT_PWM1->TZSEL_bit.OSHT2 = TZ_ENABLE; // NT_PWM1->TZSEL_bit.OSHT3 = TZ_ENABLE; // Trip-Zone NT_PWM1->TZCTL_bit.TZA = TZ_STATE; // по событию "One-Shot Trip" переводим NT_PWM1->TZCTL_bit.TZB = TZ_STATE; // ШИМ выходы в нужное состояние // ------------------------------------------------------------------------ // Настраиваем модуль ePWM3 // ------------------------------------------------------------------------ // Setup TBCLK NT_PWM2->TBPRD = NT_PWM0->TBPRD; NT_PWM2->TBPHS_bit.TBPHS = 0x0001; // Фаза равна 1 из-за баги в проце (0 не работает) NT_PWM2->TBCTR = 0x0000; // Clear counter // Setup counter mode NT_PWM2->TBCTL_bit.PRDLD = TB_SHADOW; // загрузка TBPRD при TBCTR = 0 NT_PWM2->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down NT_PWM2->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading NT_PWM2->TBCTL_bit.PHSDIR = TB_UP; // Считать вверх после загрузки фазы NT_PWM2->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale NT_PWM2->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale NT_PWM2->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // разрешаем выдачу синхро-сигнала // Setup shadowing NT_PWM2->CMPCTL_bit.SHDWAMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM2->CMPCTL_bit.LOADAMODE = CC_CTR_ZERO; // Load on period and zero NT_PWM2->CMPCTL_bit.SHDWBMODE = CC_SHADOW; //включить SHADOW для сравнения NT_PWM2->CMPCTL_bit.LOADBMODE = CC_CTR_ZERO; // Load on period and zero // Set Compare values NT_PWM2->CMPA_bit.CMPA = 0; // Set compare A value // Set actions NT_PWM2->AQCTLA = AQ_EPWM_DISABLE; // для начала события запрещены NT_PWM2->AQCTLA_bit.ZRO = 1; //обнуляем при нуле счетчика NT_PWM2->AQCTLA_bit.CAU = 2; //включаем при сравнении и инкрементиовании NT_PWM2->AQCTLA_bit.CAD = 1; //обнуляем при сравнении и декрементровании //Для PWMB тоже самое, что для PWMА. Без инверсии. Инверсия далее в модуле МВ NT_PWM2->AQCTLB = NT_PWM0->AQCTLA; // для начала события для PWM1B запрещены NT_PWM2->AQCTLB_bit.ZRO = NT_PWM0->AQCTLA_bit.ZRO; //обнуляем при нуле счетчика NT_PWM2->AQCTLB_bit.CAU = NT_PWM0->AQCTLA_bit.CAU; //включаем при сравнении и инкрементиовании NT_PWM2->AQCTLB_bit.CAD = NT_PWM0->AQCTLA_bit.CAD; //обнуляем при сравнении и декрементровании NT_PWM2->AQSFRC_bit.RLDCSF = 3; //реагировать на софтвенную привязку ног без теневого регистра // Active high complementary PWMs - Setup Deadband NT_PWM2->DBRED = NT_PWM0->DBRED; NT_PWM2->DBFED = NT_PWM2->DBRED; NT_PWM2->DBCTL_bit.IN_MODE = NT_PWM0->DBCTL_bit.IN_MODE; NT_PWM2->DBCTL_bit.OUT_MODE = NT_PWM0->DBCTL_bit.OUT_MODE; NT_PWM2->DBCTL_bit.POLSEL = NT_PWM0->DBCTL_bit.POLSEL; // Interrupt where we will change the Compare Values NT_PWM2->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT NT_PWM2->ETSEL_bit.INTEN = 0; // Disable INT //разрешаем TZ быть источником аппаратной аварии (one-shot) // NT_PWM2->TZSEL_bit.OSHT1 = TZ_ENABLE; // NT_PWM2->TZSEL_bit.OSHT2 = TZ_ENABLE; // NT_PWM2->TZSEL_bit.OSHT3 = TZ_ENABLE; NT_PWM2->TBCTL_bit.FREE_SOFT = 0; // Trip-Zone NT_PWM2->TZCTL_bit.TZA = TZ_STATE; // по событию "One-Shot Trip" переводим NT_PWM2->TZCTL_bit.TZB = TZ_STATE; // ШИМ выходы в нужное состояние // ------------------------------------------------------------------------ // Настраиваем модуль ePWM3 под АЦП // ------------------------------------------------------------------------ // Setup TBCLK NT_PWM3->TBPRD = NT_PWM0->TBPRD; NT_PWM3->TBPHS_bit.TBPHS = 0x0001; // Фаза равна 1 из-за баги в проце (0 не работает) NT_PWM3->TBCTR = 0x0000; // Clear counter // Setup counter mode NT_PWM3->TBCTL_bit.PRDLD = TB_SHADOW; // загрузка TBPRD при TBCTR = 0 NT_PWM3->TBCTL_bit.CTRMODE = TB_COUNT_UPDOWN; // Count up-down NT_PWM3->TBCTL_bit.PHSEN = TB_ENABLE; // Enable phase loading NT_PWM3->TBCTL_bit.PHSDIR = TB_UP; // Считать вверх после загрузки фазы NT_PWM3->TBCTL_bit.HSPCLKDIV = 0; // High Speed Time-base Clock Prescale NT_PWM3->TBCTL_bit.CLKDIV = 0; // Time-base Clock Prescale NT_PWM3->TBCTL_bit.SYNCOSEL = TB_SYNC_IN; // разрешаем выдачу синхро-сигнала // Interrupt where we will change the Compare Values NT_PWM3->ETSEL_bit.INTSEL = ET_DISABLE; // Disable INT NT_PWM3->ETSEL_bit.INTEN = 0; // Disable INT NT_PWM3->TBCTL_bit.FREE_SOFT = 0; NT_PWM3->ETSEL_bit.SOCAEN = 1; // Разрешить запуск ацп NT_PWM3->ETSEL_bit.SOCASEL = 1; // Запускать при CTR == 0 (Underflow) //сбрасываем все флаги аварий NT_PWM0->TZCLR = 0x7; NT_PWM1->TZCLR = 0x7; NT_PWM2->TZCLR = 0x7; //настройка ножек NT_GPIOG->ALTFUNCSET = (1 << 2) + (1 << 3) + (1 << 4); //A[0],A[1],A[2] // Периферийная функция - PWM NT_COMMON_REG->GPIOPCTLA_bit.PIN10 = 2; NT_COMMON_REG->GPIOPCTLF_bit.PIN2 = 0; NT_COMMON_REG->GPIOPCTLF_bit.PIN4 = 0; NT_COMMON_REG->GPIOPCTLG_bit.PIN2 = 0; NT_COMMON_REG->GPIOPCTLG_bit.PIN3 = 0; NT_COMMON_REG->GPIOPCTLG_bit.PIN4 = 0; //A[10], F[2], F[4] ножки резета NT_GPIOA->ALTFUNCCLR = (1 << 10); //B[0] NT_GPIOA->OUTENSET = (1 << 10); NT_GPIOF->OUTENSET = (1 << 2); NT_GPIOF->OUTENSET = (1 << 4); //A[10], F[2], F[4] //Синхронный запуск ШИМ NT_COMMON_REG->PWM_SYNC_bit.TBCLKSYNC = 0x1FF; }
следует помнить про багу из ерраты, о том что нельзя TBPHS задавать равной нулю.
особенность схемы – генерация и
распространение сигнала синхронизации от блока ШИМ занимает один такт TBCLK.
К примеру, если по событию синхронизации блока 0 в счетчик блока 1 должен быть
записан ноль, то этот ноль запишется только на следующий такт после события
(см. рисунок 14.3б). Таким образом, при синхронизации от другого блока ШИМ нужно
всегда учитывать этот такт и записывать значение фазы, следующее по порядку, в
соответствии с режимом счета (см. рисунок 14.3в)