Перейти к содержанию
    

ШИМ сигнал по закону синуса без ЦАП на STM32

Все равно бред какой-то...
 

Скрытый текст

image.thumb.png.edc8afe6622a282c98e1b13578d8ca1c.png

Уже и фильтр подобрал точный. Ошибка в коде?
Текущая таблица: 
 

Скрытый текст

phase_A 
        {
            128, 131, 134, 137, 140, 143, 146, 149, 152, 156, 159, 162, 165, 168, 171, 
            174, 176, 179, 182, 185, 188, 191, 193, 196, 199, 201, 204, 206, 209, 211, 
            213, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 239, 240, 
            242, 243, 244, 246, 247, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 
            254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 253, 252, 252, 251, 
            250, 249, 248, 247, 246, 245, 244, 242, 241, 239, 238, 236, 235, 233, 231, 
            229, 227, 225, 223, 221, 219, 217, 215, 212, 210, 207, 205, 202, 200, 197, 
            195, 192, 189, 186, 184, 181, 178, 175, 172, 169, 166, 163, 160, 157, 154, 
            151, 148, 145, 142, 138, 135, 132, 129, 126, 123, 120, 117, 113, 110, 107, 
            104, 101, 98, 95, 92, 89, 86, 83, 80, 77, 74, 71, 69, 66, 63, 
            60, 58, 55, 53, 50, 48, 45, 43, 40, 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, 9, 11, 12, 
            13, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 
            42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 79, 
            81, 84, 87, 90, 93, 96, 99, 103, 106, 109, 112, 115, 118, 121, 124, 127
        };

 

Настройки таймера и обработчик прерывания:
 

Скрытый текст

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; // включаем тактирование портов А и В
    

    TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / _ARR_VALUE) - 1;
    TIM1->ARR = _ARR_VALUE;
    
    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->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;
    }
}

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, oldbrowze said:

Все равно бред какой-то...

Уже и фильтр подобрал точный. Ошибка в коде?

Вам прерывание по переполнению надо для TIM1 настроить и обработчик прерывания тоже для TIM1.

А TIM2 вообще убрать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавил прерывание таймеру TIM1 по переполнению
 

Скрытый текст

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; // включаем тактирование портов А и В
    

    TIM1->PSC = (F_CPU / _SIGNAL_FREQUENCY_MIN / _ARR_VALUE) - 1;
    TIM1->ARR = _ARR_VALUE;
    
    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;
    TIM1->DIER      = TIM_DIER_UIE;
    NVIC_EnableIRQ(TIM1_UP_IRQn);


    // установим выводы каналов как 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->PSC = 0;

    TIM2->DIER = TIM_DIER_UIE;
    NVIC_EnableIRQ(TIM2_IRQn);

    TIM2->CR1 |= TIM_CR1_CEN;
*/
}

extern "C" void TIM1_UP_IRQHandler()
{
    if (TIM1->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;
        TIM1->SR &= ~TIM_SR_UIF;
    }
}

 

Теперь осциллограмма принимает вот такой цикличный вид:
 

Скрытый текст

image.thumb.png.986a3444b05ecb725d45e13d248d2b24.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, oldbrowze said:

Добавил прерывание таймеру TIM1 по переполнению

Теперь осциллограмма принимает вот такой цикличный вид:

Сброс флага в обработчике сделайте так

TIM1->SR = 0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сделал. Вроде, не сильно изменилась, если сравнивать с прошлой....
В чем может быть проблема?

Скрытый текст

image.thumb.png.3b35fbfc6bba2c6ff07b1b8604df254c.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 minutes ago, oldbrowze said:

Сделал. Вроде, не сильно изменилась, если сравнивать с прошлой....

Вы с подключением RC цепочки ничего не напутали ?

Вот так должно быть

RC.thumb.JPG.8ca247e7ceb97c64ac7f609b872a7183.JPG

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И еще. У вас ошибка в настройке регистра.

У вас так

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

А надо так

GPIOA->CRH &=   ~(GPIO_CRH_CNF8 | GPIO_CRH_CNF9 | GPIO_CRH_CNF10);
GPIOA->CRH |=   (GPIO_CRH_CNF8_1 | GPIO_CRH_CNF9_1 | GPIO_CRH_CNF10_1);//cnf 10 - mode output

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, oldbrowze said:

Благодарю за ответ!
Исправил. Осциллограмма осталась та же

Даже не знаю, что еще посоветовать.

Я для ШИМ делал вот так. Только в этом примере прерывания не использовал.

/* Enable GPIOB and TIM17 clock */
	RCC->APB2ENR |= (RCC_APB2ENR_IOPBEN) | (RCC_APB2ENR_TIM17EN);
	GPIOB->CRH &= ~((3<<4)|(3<<6)); //PB9 is TIM17_CH1 alternative function
	GPIOB->CRH |= ((1<<4)|(2<<6)); //PB9 is TIM17_CH1 alternative function

	TIM17->ARR  = 200; // период ШИМ -> Fpwm = 100 kHz
	TIM17->PSC  = 0;
	TIM17->CNT  = 0;
	TIM17->CCR1 = 100; // Скважность ШИМ = 50%
	//  On - OCx signal is output on the corresponding output pin.
	TIM17->CCER = TIM_CCER_CC1E;
	TIM17->CCMR1 =((6<<4) | /* PWM mode1 */
				  TIM_CCMR1_OC1PE ); 					/* preload enable */
	TIM17->BDTR = TIM_BDTR_MOE;
	TIM17->CR1 = TIM_CR1_ARPE;
	TIM17->EGR = TIM_EGR_UG; // Set UG - Update Generation
	TIM17->CR1 |= TIM_CR1_CEN; // Start Timer

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

Т.е. не использовать например TIM1->CCER |= xxxxx,  а прописывать все необходимые не нулевые биты регистра так TIM1->CCER = bit1 | bit2 | ........

Да, еще бы посоветовал вам включить OC1PE: Output Compare 1 preload enable в регистре CCMR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Включил.
Эх, красиво. Жаль, не оно. 
Вырисовывается же что-то околосинусоидальное...
 

Скрытый текст

image.thumb.png.db17a7ed6768ee93b01faa5ff30ecdad.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

26 minutes ago, oldbrowze said:

Включил.
Эх, красиво. Жаль, не оно. 

Вот в этой строчке

RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN; // включаем тактирование портов А и В

уберите  RCC_APB2ENR_AFIOEN.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 минут назад, oldbrowze сказал:

Эх, красиво. Жаль, не оно. 

Увеличьте емкость или сопротивление раз в 10. У вас плохо давится несущая ШИМ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, Сергей Борщ said:

Увеличьте емкость или сопротивление раз в 10. У вас плохо давится несущая ШИМ.

У него расчетный синус с частотой 50 Гц. RC рассчитана на 100 Гц. Несущая должна быть 12800 Гц. Т.е эта RC цепь должна гасить несущую в 128 раз.

И амплитуда пульсаций будет примерно 25 мВ.

А если он резистор уменьшит в 10 раз, то частота среза будет 10 Гц и тогда она и синус тоже гасить.

Тут дело в чем-то другом.

 

14 minutes ago, oldbrowze said:

Убрал. Осциллограмма вида не изменила

UART1 или MCO случайно не включено ?

Для эксперимента попробуйте выключить прерывание, CCR1 установить на 128. И посмотреть осциллографом период несущей и скважность.

Совпадает ли с расчетным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...