oldbrowze 0 November 6, 2021 Posted November 6, 2021 · Report post Всем здравствуйте! Стоит задача: нужно на выходе трех ножек(PA8-10) получить соответственно 3 фазы ШИМ, который определяется по закону синуса(3 синусоидальные фазы нужно получить). Столкнулся с проблемой неправильной настройки. Фазу 2 и 3 вырезал, пока не разберусь с первой. В общем: таймер 1 отвечает за вывод значений на ножки. Его частота рассчитывается по формуле: Fcpu / ((arr+1) (psc+1)) = 72*10^6 / 2402 = 29.9kHz!!!!!! <<<< Второй таймер грузит значение в таймер 2. Его частота: Fcpu / ((arr+1) (psc+1)) = 65kHz!!!!!!!!! <<<<<<<< В одной беседе подсказали такие формулы(они в коде). Очень большие частоты. Но формул, по которым нужно считать правильно, я не знаю. Подскажите, пожалуйста, если знаете. Синус формировал по формуле: 2^16 / 2 * sin(T) + 2^16 / 2. т.е чтобы в отрицательную часть не заходить, сместил его на половину 2^16. Буду очень признателен, если подскажите. где тут ошибка. Понимаю, что где-то намутил воду.... Этот сигнал потом пойдет на 3-х фазный драйвер, который уже и будет управлять ключами. Заранее спасибо! Константы: Скрытый текст constexpr auto _F_CPU = 72000000u; // частота процессора constexpr auto _SIGNAL_FREQUENCY_MAX = 50u; // максимальная частота синусоиды constexpr auto _SIGNAL_FREQUENCY_MIN = 100u; // минимальная частота синусоиды constexpr auto _DISCRETIZE = 300u; // дискретизация синусоиды(количество точек) constexpr auto _VOLTAGE_ON_PORT = 3.3f; // напряжение на порту(напряжение питания) constexpr auto _BITNESS = 16u; // разрядность таймера[~цап] constexpr auto _AMPLITUDE = ((1 << 16) - 1) / 2; // максимальное значение таймера constexpr auto _ADC_MAX_VALUE = (1 << 12) - 1; // максимальное значение в АЦП Массив значений, размером 300: Скрытый текст static inline std::array<T, _DISCRETIZE> phase_A { 32768, 33456, 34144, 34832, 35519, 36204, 36888, 37570, 38250, 38928, 39603, 40275, 40943, 41608, 42269, 42926, 43578, 44226, 44868, 45506, 46137, 46763, 47382, 47995, 48602, 49201, 49793, 50377, 50954, 51523, 52083, 52635, 53178, 53713, 54237, 54753, 55259, 55754, 56240, 56715, 57180, 57634, 58077, 58508, 58929, 59338, 59735, 60120, 60493, 60854, 61202, 61538, 61861, 62172, 62469, 62753, 63024, 63282, 63526, 63757, 63974, 64177, 64366, 64541, 64702, 64850, 64983, 65101, 65206, 65296, 65372, 65433, 65480, 65513, 65531, 65535, 65524, 65498, 65459, 65404, 65336, 65253, 65155, 65044, 64918, 64778, 64624, 64455, 64273, 64077, 63867, 63643, 63406, 63155, 62890, 62613, 62322, 62018, 61701, 61372, 61030, 60675, 60308, 59929, 59538, 59135, 58720, 58294, 57857, 57408, 56949, 56479, 55998, 55508, 55007, 54496, 53976, 53447, 52908, 52360, 51804, 51240, 50667, 50086, 49498, 48902, 48299, 47690, 47073, 46451, 45822, 45188, 44548, 43903, 43253, 42598, 41939, 41276, 40609, 39939, 39266, 38589, 37910, 37229, 36546, 35861, 35175, 34488, 33800, 33112, 32423, 31735, 31047, 30360, 29674, 28989, 28306, 27625, 26946, 26269, 25596, 24926, 24259, 23596, 22937, 22282, 21632, 20987, 20347, 19713, 19084, 18462, 17845, 17236, 16633, 16037, 15449, 14868, 14295, 13731, 13175, 12627, 12088, 11559, 11039, 10528, 10027, 9537, 9056, 8586, 8127, 7678, 7241, 6815, 6400, 5997, 5606, 5227, 4860, 4505, 4163, 3834, 3517, 3213, 2922, 2645, 2380, 2129, 1892, 1668, 1458, 1262, 1080, 911, 757, 617, 491, 380, 282, 199, 131, 76, 37, 11, 0, 4, 22, 55, 102, 163, 239, 329, 434, 552, 685, 833, 994, 1169, 1358, 1561, 1778, 2009, 2253, 2511, 2782, 3066, 3363, 3674, 3997, 4333, 4681, 5042, 5415, 5800, 6197, 6606, 7027, 7458, 7901, 8355, 8820, 9295, 9781, 10276, 10782, 11298, 11822, 12357, 12900, 13452, 14012, 14581, 15158, 15742, 16334, 16933, 17540, 18153, 18772, 19398, 20029, 20667, 21309, 21957, 22609, 23266, 23927, 24592, 25260, 25932, 26607, 27285, 27965, 28647, 29331, 30016, 30703, 31391, 32079 }; Код инициализации таймеров: Скрытый текст void FreqConverter::timer_initialize() { RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // включаем TIM1 (тактирование от APB2 - 72 MHz) RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN; // включаем тактирование портов А и В /* Частота таймера прерываний равна = кол-во отсчетов * частоту сигнала. ARR = 1000 для видной скважности. на ARR != 1000 проверено не было!. */ //TIM1->ARR = ((_F_CPU / (1 << _BITNESS)) - 1); TIM1->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM1->PSC = 0; //TIM1->PSC = 0; //TIM1->ARR = (_F_CPU / (1 << _BITNESS)) - 1; TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E; // включаем выход 1, 2, 3 каналов ножек как выход TIM1->CCER |= (TIM_CCER_CC1P | TIM_CCER_CC2P | TIM_CCER_CC3P); // устанавливаем норм. полярность(1 - высокий) TIM1->BDTR |= TIM_BDTR_MOE; // разрешили работу выводов TIM1->CCMR1 |= (0b110 << TIM_CCMR1_OC1M_Pos) | (0b110 << TIM_CCMR1_OC2M_Pos); // установили работу каналов 1,2 как PWM1 TIM1->CCMR2 |= (0b110 << TIM_CCMR2_OC3M_Pos); // установили работу канала 3 как PWM1 //TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; TIM1->CR1 &= ~TIM_CR1_DIR; TIM1->CR1 &= ~TIM_CR1_CMS; // установим выводы каналов как alternative push-pull выходы GPIOA->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10); //mode 01 - alernative push-pull GPIOA->CRH |= GPIO_CRH_MODE8_1 | GPIO_CRH_MODE9_1 | GPIO_CRH_MODE10_1; GPIOA->CRH &= ~(GPIO_CRH_CNF8_0 | GPIO_CRH_CNF9_0 | GPIO_CRH_CNF10_0); GPIOA->CRH |= (GPIO_CRH_CNF8_1 | GPIO_CRH_CNF9_1 | GPIO_CRH_CNF10_1);//cnf 10 - mode output TIM1->CR1 |= TIM_CR1_CEN; TIM2->ARR = ((_F_CPU / (1 << _BITNESS)) - 1); //TIM2->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM2->PSC = 0; TIM2->DIER = TIM_DIER_UIE; NVIC_EnableIRQ(TIM2_IRQn); TIM2->CR1 |= TIM_CR1_CEN; } extern "C" void TIM2_IRQHandler() { if (TIM2->SR & TIM_SR_UIF) { static uint16_t _counter_phase{0}; TIM1->CCR1 = FreqConverter::phase_A[_counter_phase]; //TIM1->CCR2 = FreqConverter::phase_B[_counter_phase]; //TIM1->CCR3 = FreqConverter::phase_C[_counter_phase]; if(++_counter_phase == _DISCRETIZE) _counter_phase = 0; TIM2->SR &= ~TIM_SR_UIF; } } Share this post Link to post Share on other sites More sharing options...
Priest_89 0 November 6, 2021 Posted November 6, 2021 · Report post Из сообщения непонятно, в чем конкретно проблема, и какая модель контроллера, но вот что бросилось в глаза. Таймер в выбранном режиме работает так - после перезапуска (СNT = 0) на выходе выставляется логическая единица, затем, когда таймер досчитает до значения, записанного в регистр CCRx, на выходе устанавливается логический ноль. Когда же таймер досчитает до значения в регистре ARR, он перезапускается и цикл начинается по новой. Вы же задаете частоту ШИМ, записывая в ARR значение 2400, при этом большинство значений в таблице, записываемых в CCRx, больше этого числа, и они никак не влияют на работу таймера - он перезапускается раньше. А вообще, вся работа периферии подробно описана в Reference Manual на соответствующий контроллер. Share this post Link to post Share on other sites More sharing options...
oldbrowze 0 November 6, 2021 Posted November 6, 2021 · Report post Спасибо за ответ. Микроконтроллер - STM32F103C8T6. По поводу ARR понял. Но как быть в таком случае? И, все же, интересует вопрос по поводу частоты: правильно ли я посчитал, не велика ли она? Share this post Link to post Share on other sites More sharing options...
Priest_89 0 November 6, 2021 Posted November 6, 2021 · Report post Задавать частоту значением регистра PSC. Тем более, у STM32 тут хороший бонус - можно выбрать любой предделитель от 1 до 65536. Quote И, все же, интересует вопрос по поводу частоты: правильно ли я посчитал, не велика ли она? Ну для заданных значений - да, только в знаменателе 2400 должно быть Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 6, 2021 Posted November 6, 2021 · Report post Какую частоту синуса вы хотите получить ? Пускай 50 Гц. Сделайте ваш ШИМ 8-ми битный. Тогда на период синуса у вас получится 256 отсчетов. И пускай скважность ШИМ у вас меняется каждый период таймера. Тогда ARR можно сделать равным 256. Остается найти частоту предделителя PSC. PSC = 72000000/50/256 - 1= 5624. Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 26 November 6, 2021 Posted November 6, 2021 · Report post 22 минуты назад, dimka76 сказал: Тогда на период синуса у вас получится 256 отсчетов. Которые, увы, нацело не делятся на три фазы. Я подобную задачу решал методом прямого цифрового синтеза - https://kit-e.ru/elcomp/dds-pryamoj-czifrovoj-sintez-chastoty-2/ Таким способом можно получить частоту с очень высокой точностью как частоты так и сдвига фаз при любой, даже некратной несущей частоте ШИМ. Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 6, 2021 Posted November 6, 2021 · Report post 9 minutes ago, Сергей Борщ said: Которые, увы, нацело не делятся на три фазы. Ошибка 0.4% А вот интересно по ГОСТ или МЭК или ISO какое допустимое отклонение на сдвиг фаз между фазами в трехфазной сети ? Share this post Link to post Share on other sites More sharing options...
oldbrowze 0 November 6, 2021 Posted November 6, 2021 · Report post 33 минуты назад, dimka76 сказал: Остается найти частоту предделителя PSC. PSC = 72000000/50/256 - 1= 5624. Таким образом, вместо TIM1->ARR = (F_CPU / (_DISCRETIZE * _SIGNAL_FREQUENCY_MIN)) - 1; TIM1->PSC = 0; я получил: TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / 256) - 1; TIM1->ARR = 256; где 256 в PSC - это значение, которое мы внесли в ARR? 13 минут назад, Сергей Борщ сказал: Которые, увы, нацело не делятся на три фазы. Я подобную задачу решал методом прямого цифрового синтеза - https://kit-e.ru/elcomp/dds-pryamoj-czifrovoj-sintez-chastoty-2/ Таким способом можно получить частоту с очень высокой точностью как частоты так и сдвига фаз при любой, даже некратной несущей частоте ШИМ. Спасибо за информацию! Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 6, 2021 Posted November 6, 2021 · Report post 8 minutes ago, oldbrowze said: я получил: TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / 256) - 1; TIM1->ARR = 256; где 256 в PSC - это значение, которое мы внесли в ARR? Да. Можно так #define ARR_VAL (256UL) TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / ARR_VAL) - 1UL; TIM1->ARR = ARR_VAL - 1UL; Share this post Link to post Share on other sites More sharing options...
oldbrowze 0 November 7, 2021 Posted November 7, 2021 · Report post Спасибо за ответы! 12 часов назад, dimka76 сказал: Можно так Можно, но предпочитаю constexpr. :) Сделал, как сказали. Эта осциллограмма - и есть шим, формированный по закону синуса? Скрытый текст Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 7, 2021 Posted November 7, 2021 · Report post 2 hours ago, oldbrowze said: Эта осциллограмма - и есть шим, формированный по закону синуса? Подключите к выходу вашего ШИМ RC цепочку с частотой среза 100 Гц и смотрите осциллографом после нее. Если все правильно, то увидите синус. Share this post Link to post Share on other sites More sharing options...
oldbrowze 0 November 7, 2021 Posted November 7, 2021 · Report post Точных номиналов на R, C нет. Приблизительно подобрал. Получается какая-то пила. Я в правильном направлении? Огромное спасибо за консультацию!) Скрытый текст Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 7, 2021 Posted November 7, 2021 · Report post 19 minutes ago, oldbrowze said: Получается какая-то пила. Покажите вашу таблицу синуса. Share this post Link to post Share on other sites More sharing options...
oldbrowze 0 November 7, 2021 Posted November 7, 2021 · Report post Скрытый текст static inline std::array<T, _DISCRETIZE> phase_A { 128, 131, 134, 137, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 191, 194, 197, 199, 202, 205, 207, 209, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198, 195, 193, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 126, 123, 120, 117, 114, 111, 108, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 41, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 47, 49, 51, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 119, 122, 125 }; Генерировал в матлабе по формуле: Y = round(2^bitness / 2 * sin(T) + 2^bitness / 2); Share this post Link to post Share on other sites More sharing options...
dimka76 12 November 7, 2021 Posted November 7, 2021 · Report post 4 minutes ago, oldbrowze said: Hide contents static inline std::array<T, _DISCRETIZE> phase_A { 128, 131, 134, 137, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 191, 194, 197, 199, 202, 205, 207, 209, 212, 214, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 256, 256, 256, 256, 256, 256, 256, 255, 255, 254, 254, 253, 253, 252, 251, 250, 249, 248, 247, 246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 226, 224, 222, 220, 218, 215, 213, 211, 208, 206, 203, 201, 198, 195, 193, 190, 187, 184, 181, 179, 176, 173, 170, 167, 164, 161, 158, 155, 152, 148, 145, 142, 139, 136, 133, 130, 126, 123, 120, 117, 114, 111, 108, 104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 75, 72, 69, 66, 63, 61, 58, 55, 53, 50, 48, 45, 43, 41, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 19, 17, 16, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 47, 49, 51, 54, 57, 59, 62, 65, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 119, 122, 125 }; Значения должны быть от 0 до 255. А у вас встречаются 256. Y = round(((((2^bitness)-1) / 2) * sin(T)) + (((2^bitness)-1) / 2)); Share this post Link to post Share on other sites More sharing options...