ШИМ

32-разрядные микроконтроллеры разработки ОАО "НИИЭТ"

Модераторы: pip, _sva_

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

ШИМ

Сообщение MR.Smith » 17 июн 2017, 12:23

Здравствуйте!

Столкнулся с непонятной ситуацией, помогите пожалуйста разрешить.

Процессор затактирован на 96 МГц. Тактирующий сигнал на ШИМ без делителя, счетчик вверх-вниз по основанию 2000 (96 МГц / 4000 = 24 КГц). Работаю с ШИМ. Включены все 9 блоков. Аппаратная синхронизация (работает, проверено). Комплиментарный режим, мертвое время 120 тиков камня (119 + 1 в соответствии с errata).

Два прерывания:
1) Для PWM0 по событию CTR=PRD (NT_PWM0->ETSEL_bit.INTSEL = 2)
2) Для PWM1 по событию CTR=ZERO (NT_PWM1->ETSEL_bit.INTSEL = 1)

Включена отложенная загрузка из теневого регистра для всех ШИМ:
NT_PWM8->CMPCTL_bit.LOADAMODE = 0;
NT_PWM8->CMPCTL_bit.SHDWAMODE = 0;


Ниже диаграмма иллюстрирует происходящее (нарисовал треугольник - счетчик для лучшего понимания):
Изображение

На максимальном значении счетчика вырабатывается прерывание (1).
В обработчике (1) принимается решение (2) изменить значение скважности с 0 до 100% (запись в NT_PWM8->CMPA_bit.CMPA и установка флага на запуск для следующего прерывания) и разрешить работу ШИМ (до этого запрещена работа через Trip Zone, выводы подтянуты в высокий уровень).
Далее вырабатывается прерывание (3) по события VTR=ZERO в котором смотрим флаг от предыдущего прерывания (1) и разрешаем работу ШИМ (NT_PWM8->TZCLR_bit.OST = 1). ШИМ включается сразу же и уже здесь я ожидал, что регистр CMPA перезапишется из теневого по событию CTR=ZERO, но этого не происходит. ШИМ включается (4), но на старом значении скважности, а перезапись из теневого происходит (6) только при следующем событии CTR=PRD (5)

При этом изменение значений регистра CMPCTL на любое значение вообще не приводит ни к какому эффекту! Как бы я не настроил этот регистр - картина вообще не меняется.

Подскажите, что я делаю не так? Почему перезапись CMPA из теневого регистра происходит не при том событии?

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

Re: ШИМ

Сообщение MR.Smith » 19 июн 2017, 09:28

Забыл указать среду разработки - Vector IDE

Аватара пользователя
Лашкевич
Сообщения: 62
Зарегистрирован: 13 май 2015, 13:10
Предприятие: ООО "НПФ Вектор"
Откуда: Москва
Контактная информация:

Re: ШИМ

Сообщение Лашкевич » 19 июн 2017, 11:50

Тонкий эксперимент описан. Пока непонятно. Хочу спросить про уточнения:
Вы пишете, что в обработчике 1 вы делаете
разрешить работу ШИМ (до этого запрещена работа через Trip Zone, выводы подтянуты в высокий уровень).
При этом в обработчике 3 вы делаете как бы тоже самое
NT_PWM8->TZCLR_bit.OST = 1
Можете привести чуть больше кода, выборочно, что именно делается там и сям и заодно инициализацию? LOADAMODE и SHDWAMODE настраиваются заранее в инициализации или прямо в прерывании?
С уважением,
Лашкевич Максим.
Инженер-программист ООО "НПФ Вектор", Москва.
http://motorcontrol.ru/

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

Re: ШИМ

Сообщение MR.Smith » 19 июн 2017, 12:43

Я делаю программный отложенный запуск ШИМ. В обработчике (1) я только принимаю решение о необходимости запуска (или останова) и выставляю соответствующий программный флаг (переменная). В обработчике (3) этот флаг читается и именно там (и только там) делается NT_PWM8->TZFRC_bit.OST = 1 для остановки или NT_PWM8->TZCLR_bit.OST = 1 для запуска ШИМ. Это делается для того, чтобы включать ШИМ в начале периода счетчика, когда значение скважности из теневого регистра уже перезагрузится. Чтобы как раз избежать ШИМ на старом значении скважности до перезаписи.

Все ШИМ у меня настроены одинаково. Код настройки ног, тактирования и т.д. я опущу для компактности.

Настройка ШИМ контроллера:

Код: Выделить всё

	// Настройка синхронизации блоков - последовательное включение
	NT_COMMON_REG->PWM_CTRL_bit.SYNCSELECT = 0;

	// *** PWM0 ***
	// Режим работы
	NT_PWM0->TBCTL_bit.PRDLD = 0;			// Отложенная загрузка
	NT_PWM0->TBCTL_bit.CTRMODE = 2;			// Режим работы счетчика вверх-вниз
	NT_PWM0->TBCTL_bit.PHSEN = 1;			// Загрузка фазы запрещена
	NT_PWM0->TBCTL_bit.PHSDIR = 1;			// Фазовое направление - вверх
	NT_PWM0->TBCTL_bit.CLKDIV = 0;			// Первый делитель тактовой частоты
	NT_PWM0->TBCTL_bit.HSPCLKDIV = 0;		// Второй делитель тактовой частоты
	NT_PWM0->TBCTL_bit.SYNCOSEL = 1;		// Выдаем тактовый сигнал при CTR=0

	// Настройка компараторов
	NT_PWM0->CMPCTL_bit.SHDWAMODE = 0;		// Отложенная загрузка значений
	NT_PWM0->CMPCTL_bit.SHDWBMODE = 0;		// CMPA и CMPB через теневой регистр
	NT_PWM0->CMPCTL_bit.LOADAMODE = 0;		// Загрузка CMPA при CTR=Zero
	NT_PWM0->CMPCTL_bit.LOADBMODE = 0;		// Загрузка CMPB при CTR=Zero
	NT_PWM0->CMPA_bit.CMPA = 0;

	// Действия при событиях
	// 01b - переключение в 0;  10b - переключение в 1
	NT_PWM0->AQCTLA = 0;					// Сначала очищаем
	NT_PWM0->AQCTLB = 0;
	NT_PWM0->AQCTLA_bit.CAU = 2;			// Группа A на фронте
	NT_PWM0->AQCTLA_bit.CAD = 1;			// Группа A на спаде
	NT_PWM0->AQCTLB_bit.CAU = 2;			// Группа B на фронте
	NT_PWM0->AQCTLB_bit.CAD = 1;			// Группа B на спаде
Настройка прерываний:

Код: Выделить всё

	// Прерывание по вершине счетчика
	NT_PWM0->ETSEL_bit.INTSEL = 2;		// Прерывание по события CTR=PRD
	NT_PWM0->ETSEL_bit.INTEN = 1;		// Разрешить прерывание

	// Запуск секвенсоров по вершине счетчика
	NT_PWM0->ETSEL_bit.SOCASEL = 2;		// Запуск секвенсоров при CTR=PRD
	NT_PWM0->ETSEL_bit.SOCAEN = 1;		// Разрешить запуск секвенсоров
	NT_PWM0->ETSEL_bit.SOCBSEL = 2;		// Запуск секвенсоров при CTR=PRD
	NT_PWM0->ETSEL_bit.SOCBEN = 1;		// Разрешить запуск секвенсоров

	// Прерывание прир пересечении счетчиком НУЛЯ
	NT_PWM1->ETSEL_bit.INTSEL = 1;		// Прерывание по события CTR=ZERO
	NT_PWM1->ETSEL_bit.INTEN = 1;		// Разрешить прерывание
Обработчик (1):

Код: Выделить всё

void EPWM_0_IRQHandler(void)
{
	WD_RESET;

	if(dbgDutyCounter == 1)
	{
		NT_PWM8->CMPA_bit.CMPA = 0;  // Минимальная скважности
		pwmFan.enableA = TRUE;
	}
	else if(dbgDutyCounter == 100)
	{
		pwmFan.enableA = FALSE;
	}
	else if(dbgDutyCounter == 200)
	{
		NT_PWM8->CMPA_bit.CMPA = 2000;  // Максимальная скважности
		pwmFan.enableA = TRUE;
	}
	else if(dbgDutyCounter == 300)
	{
		pwmFan.enableA = FALSE;
	}
	else if(dbgDutyCounter >= 400)
	{
		dbgDutyCounter = 0;
	}
	dbgDutyCounter++;

	NT_PWM0->ETCLR_bit.INT = 1;
	NT_PWM0->ETCLR_bit.SOCA = 1;
	NT_PWM0->ETCLR_bit.SOCB = 1;
	NT_PWM0->INTCLR_bit.INT = 1;
	NVIC_ClearPendingIRQ(PWM0_IRQn);
}
Обработчик (3):

Код: Выделить всё

#define PWM6_ENABLE	NT_PWM6->TZCLR_bit.OST = 1
#define PWM7_ENABLE	NT_PWM7->TZCLR_bit.OST = 1
#define PWM8_ENABLE	NT_PWM8->TZCLR_bit.OST = 1

#define PWM6_DISABLE	NT_PWM6->TZFRC_bit.OST = 1
#define PWM7_DISABLE	NT_PWM7->TZFRC_bit.OST = 1
#define PWM8_DISABLE	NT_PWM8->TZFRC_bit.OST = 1

void EPWM_1_IRQHandler(void)
{
	// Фаза C
	if(pwmFan.enableC) PWM6_ENABLE;
	else PWM6_DISABLE;

	// Фаза B
	if(pwmFan.enableB) PWM7_ENABLE;
	else PWM7_DISABLE;

	// Фаза A
	if(pwmFan.enableA) PWM8_ENABLE;
	else PWM8_DISABLE;

	NVIC_ClearPendingIRQ(PWM1_IRQn);
	NT_PWM1->ETCLR_bit.INT = 1;
	NT_PWM1->INTCLR_bit.INT = 1;
}
Моя проблема заключается в том, что перезагрузка из теневых регистров CMPA и CMPB происходит не при событииCTR=ZERO, а при событии CTR=PRD. И значение регистров LOADAMODE и SHDWAMODE никак не влияют на происходящее, хотя должны!

Аватара пользователя
Лашкевич
Сообщения: 62
Зарегистрирован: 13 май 2015, 13:10
Предприятие: ООО "НПФ Вектор"
Откуда: Москва
Контактная информация:

Re: ШИМ

Сообщение Лашкевич » 19 июн 2017, 13:22

Я пока не почитал ваш код, но поэкспериментировал с софтом MotorControlDemo с битбакета и поснимал им осцы для проверки работы SHDWAMODE и LOADAMODE. С виду все работает. Я поставил частоту ШИМ 1кГц и снимал в осциллограмму данные на частоте 10кГц. Получил вот такой график для загрузки по нулю:
Изображение
здесь голубой это счетчик таймера ШИМ, осциллографированный непосредственно как Debug1=NT_PWM0->TBCTR;
фиолетовый синус - это формируемое и присваиваемое на каждом периоде на 10кГц задание в уставку сравнения NT_PWM0->CMPA_bit.CMPA = (Uint16) p->GammaA;
Синий - это прочитываемое из регистра уставки сравнения значение: Debug3= NT_PWM0->CMPA_bit.CMPA;
а красный - значение ножки ШИМ, считанное прямо с GPIO как Debug2=(NT_GPIOG->DATA>>2)&1;
Как видно по синему графику, скважность из теневого регистра попадает в уставку сравнения как и нужно по нулю, и верно воспроизводится.

Далее тоже самое для загрузки по периоду:
Изображение


Для нуля и периода:
Изображение


И с отключенным теневым регистром:
Изображение
С уважением,
Лашкевич Максим.
Инженер-программист ООО "НПФ Вектор", Москва.
http://motorcontrol.ru/

Аватара пользователя
Лашкевич
Сообщения: 62
Зарегистрирован: 13 май 2015, 13:10
Предприятие: ООО "НПФ Вектор"
Откуда: Москва
Контактная информация:

Re: ШИМ

Сообщение Лашкевич » 19 июн 2017, 13:44

Попробуйте повторить мой эксперимент - запустите ШИМ на постоянную работу без всяких пусков/остановов, меняйте быстро скважность, раз 5 за один период ШИМ, и смотрите, как меняется результат в зависимости от конфигурирования регистров LOADAMODE и SHDWAMODE. В зависимости от результата эксперимента можно будет думать дальше.
С уважением,
Лашкевич Максим.
Инженер-программист ООО "НПФ Вектор", Москва.
http://motorcontrol.ru/

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

Re: ШИМ

Сообщение MR.Smith » 19 июн 2017, 17:05

Лашкевич писал(а):
19 июн 2017, 13:44
Попробуйте повторить мой эксперимент - запустите ШИМ на постоянную работу без всяких пусков/остановов, меняйте быстро скважность, раз 5 за один период ШИМ, и смотрите, как меняется результат в зависимости от конфигурирования регистров LOADAMODE и SHDWAMODE. В зависимости от результата эксперимента можно будет думать дальше.
Проделал опыт. Дело, похоже, действительно не в этом.
Если не останавливать и запускать ШИМ-контроллер механизмом Trip Zone, то перезапись из теневого регистра в CMPA происходит в верный момент времени.

Все выглядит так, будто бы при активном сигнале аварии не осуществляется перезапись CMPA из теневого регистра в момент CTR=ZERO. Перезапись происходит в момент CTR=PRD.

В прерывании по событию CTR=ZERO я снимаю сигнал аварии, но на момент CTR=ZERO он еще был активен и перезапись из теневого регистра в CMPA не выполнилась, а ШИМ заработал на старом значении. Это мое предположение. Такого (блокировка перезаписи CMPA из теневого регистра), насколько я понимаю, быть не должно. Думаю капать надо в этом направлении.

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

Re: ШИМ

Сообщение MR.Smith » 19 июн 2017, 17:13

MR.Smith писал(а):
19 июн 2017, 17:05
В прерывании по событию CTR=ZERO я снимаю сигнал аварии, но на момент CTR=ZERO он еще был активен и перезапись из теневого регистра в CMPA не выполнилась, а ШИМ заработал на старом значении. Это мое предположение. Такого (блокировка перезаписи CMPA из теневого регистра), насколько я понимаю, быть не должно. Думаю капать надо в этом направлении.
Хотя нет, проверил, немного иначе все. Перезапись осуществляется, но не в момент CTR=ZERO, а в момент CTR=PRD.
После запуска ШИМ продолжается со старым значением некоторое время. Но только на первой итерации после запуска.

bkolbov
Сообщения: 67
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: ШИМ

Сообщение bkolbov » 20 июн 2017, 14:35

Добрый день!
Если не останавливать и запускать ШИМ-контроллер механизмом Trip Zone, то перезапись из теневого регистра в CMPA происходит в верный момент времени.
Механизм TZ никак не влияет на теневую перезагрузку, однозначно. Здесь наблюдаются некоторые другие эффекты, причину которых нужно выяснить.

Когда вы говорите, что CMPA обновился/не обновился - это значит что в прерывании вы его вычитываете и видите, что он обновляется не в (3), а в (5), верно?

Есть предположение, что наблюдаются проблемы с синхронизацией счетчиков ШИМ. Они у вас точно все работают синхронно? Не может ли быть работы в противофазе, т.е. когда в PWM1 - CTR=ZERO (3), то в PWM8 в этот момент CTR=PRD, а PWM8 CTR=ZERO наступает соответсвенно когда PWM1 CTR=PRD (5)?

Каким образом вы включаете предделители ШИМ (поле TBCLKSYNC регистра PWM_SYNC регистров общего назначения)?
До настройки всех ШИМ или после? По хорошему, запись должна быть одна, вида NT_COMMON_REG->PWM_SYNC=0xFFFFFFFF, и идти лишь после настройки всех ШИМ.
Хотя нет, проверил, немного иначе все. Перезапись осуществляется, но не в момент CTR=ZERO, а в момент CTR=PRD.
После запуска ШИМ продолжается со старым значением некоторое время. Но только на первой итерации после запуска.
Что вы понимаете под первой итерацией после запуска? Момент после включения мк, когда ШИМы только настроились и начали работать?

Аватара пользователя
MR.Smith
Сообщения: 49
Зарегистрирован: 25 апр 2016, 10:56

Re: ШИМ

Сообщение MR.Smith » 22 июн 2017, 16:57

Богдан, здравствуйте!
bkolbov писал(а):
20 июн 2017, 14:35
Когда вы говорите, что CMPA обновился/не обновился - это значит что в прерывании вы его вычитываете и видите, что он обновляется не в (3), а в (5), верно?
Я этот момент еще раз проверил. Ранее не пытался вычитывать этот регистр, делал предположения основываясь на осциллограммах. Так вот, в (3) перезапись из теневого регистра осуществляется, NT_PWM8->CMPA_bit.CMPA вычитывается именно как то значение. которое я ожидаю получить. Но на осциллограмме я вижу, что значение скважности стоит старое - это момент с (4) по (6).
bkolbov писал(а):
20 июн 2017, 14:35
Есть предположение, что наблюдаются проблемы с синхронизацией счетчиков ШИМ. Они у вас точно все работают синхронно? Не может ли быть работы в противофазе, т.е. когда в PWM1 - CTR=ZERO (3), то в PWM8 в этот момент CTR=PRD, а PWM8 CTR=ZERO наступает соответсвенно когда PWM1 CTR=PRD (5)?
Синхронизацию я проверял так: запускал все 9 ШИМ на одном и том-же значении CMPA. Далее на многоканальном осциллографе накладывал друг на друга выходные сигналы и убедился, что они полностью совпадают на всех каналах. Возможно, такой проверки недостаточно.
bkolbov писал(а):
20 июн 2017, 14:35
Каким образом вы включаете предделители ШИМ (поле TBCLKSYNC регистра PWM_SYNC регистров общего назначения)?
До настройки всех ШИМ или после? По хорошему, запись должна быть одна, вида NT_COMMON_REG->PWM_SYNC=0xFFFFFFFF, и идти лишь после настройки всех ШИМ.
В последней строчке функции настройки я делаю так: NT_COMMON_REG->PWM_SYNC_bit.TBCLKSYNC = 0x01FF;
bkolbov писал(а):
20 июн 2017, 14:35
Что вы понимаете под первой итерацией после запуска? Момент после включения мк, когда ШИМы только настроились и начали работать?
Под "первой итерацией" я понимаю первый период счетчика ШИМ после того, как программа разрешает выдачу ШИМ. После того, как делается NT_PWM8->TZCLR_bit.OST = 1 в прерывании CTR=ZERO. На рисунке это период с момента (3) и далее.

Пока я временно вышел из ситуации путем переноса кода разрешения работы (NT_PWM8->TZCLR_bit.OST = 1) ШИМ из прерывания CTR=ZERO в прерывание CTR=PRD.

Ответить

Вернуться в «32-разрядные микроконтроллеры на ядре ARM Cortex»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя