Всем привет! Я только учусь работать с микроконтроллером и нужна помощь:) Работаю с микроконтроллером STM32G431, в программе CubeIDE. В самом коде совмещаю HAL и CMSIS. Вот мой код:
При компиляции кода ошибок никаких не возникает, при нажатии кнопки PB0 таймер запускается, проблем никаких нет. Но при нажатии кнопки PC5 происходит просто ничего:( на выходах мк нет синусоидального ШИМа. Да и частота соответственно не меняется. В чем может быть ошибка и куда мне двигаться?
* Сразу прошу прощение за это "извращение"
** Я пытался работать с DMA, но в ровным счетом ситуация такая же, на выходе всегда ШИМ с постоянной скважностью.
#include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h" #include <math.h> #define BUFFER_SIZE 2000 double pi = 3.14159; uint32_t sine_wave[BUFFER_SIZE] = {0}; uint32_t frequency = 50; bool increasing = true; float pwm_number; float pwm_coef; uint16_t i; float a; float q; float z; void generate_sine_wave(); void configure_timer_pwm(); void configure_button_interrupts(); void EXTI0_IRQHandler(); void EXTI9_5_IRQHandler(); extern TIM_HandleTypeDef htim1; void SystemClock_Config(void); void generate_sine_wave() { if (frequency != 0) { // Число периодов ШИМ для частоты поля pwm_number = (10 * 16000) / frequency; // Коэффициент скалярного управления pwm_coef = (float)7; z = 630 / 2; a = (float)2.0 * (1.0 / pwm_number); q = 0; for (i = 0; i < pwm_number; i++) { q = z + (z * sin(pi * i * a)); sine_wave[i] = q * pwm_coef; } } } void configure_timer_pwm() { RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; TIM1->PSC = 0; TIM1->ARR = 4799; TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // CH1 TIM1->CCMR1 |= TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; TIM1->CCMR2 |= TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE; // CH1 инверсии TIM1->CCER |= TIM_CCER_CC2E | TIM_CCER_CC2NE; // CH2 инверсии TIM1->CCER |= TIM_CCER_CC3E | TIM_CCER_CC3NE; // CH3 инверсии TIM1->BDTR |= TIM_BDTR_MOE; TIM1->CR1 |= TIM_CR1_CEN; } void configure_button_interrupts() { RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; SYSCFG->EXTICR[0] &= ~SYSCFG_EXTICR1_EXTI0_Msk; SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI0_PB; EXTI->RTSR1 |= EXTI_RTSR1_RT0; EXTI->IMR1 |= EXTI_IMR1_IM0; NVIC_EnableIRQ(EXTI0_IRQn); SYSCFG->EXTICR[1] &= ~SYSCFG_EXTICR2_EXTI5_Msk; SYSCFG->EXTICR[1] |= SYSCFG_EXTICR2_EXTI5_PC; EXTI->RTSR1 |= EXTI_RTSR1_RT5; EXTI->IMR1 |= EXTI_IMR1_IM5; NVIC_EnableIRQ(EXTI9_5_IRQn); } void EXTI0_IRQHandler() { if ((EXTI->PR1 & EXTI_PR1_PIF0) != 0) { EXTI->PR1 |= EXTI_PR1_PIF0; if (TIM1->CR1 & TIM_CR1_CEN) { TIM1->CR1 &= ~TIM_CR1_CEN; } else { configure_timer_pwm(); } } } void EXTI9_5_IRQHandler() { if ((EXTI->PR1 & EXTI_PR1_PIF5) != 0) { EXTI->PR1 |= EXTI_PR1_PIF5; if (increasing) { frequency += 1; if (frequency > 400) { frequency = 400; increasing = false; } } else { frequency -= 1; if (frequency < 50) { frequency = 50; increasing = true; } } generate_sine_wave(); } } int main(void) { HAL_Init(); SystemClock_Config(); HAL_TIM_Base_Start_IT(&htim1); MX_GPIO_Init(); MX_TIM1_Init(); MX_USART2_UART_Init(); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2); HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); generate_sine_wave(); configure_timer_pwm(); configure_button_interrupts(); while (1) { if (i >= pwm_number) { i = 0; } if (htim1.Instance == TIM1) { TIM1->CCR1 = sine_wave[i]; TIM1->CCR2 = sine_wave[i + (int)(pwm_number / 3)]; TIM1->CCR3 = sine_wave[i + (int)(2*pwm_number / 3)]; i++; } } }
Привет! Надо под отладчиком посмотреть поэтапно, попадает ли в обработчик нажатия PC5, затем, какие значения непосредственно в CCRx записываются и что в массиве sine_wave[] генерируется в итоге, какие значения.
@aveal обработчик попадает, но такое ощущение, что он записывает только 1 число в массива, скважность 1 раз изменилась и все. как заставить, чтобы он постоянно считывал значения с массива не понимаю. 🙁
Кстати в основном цикле, там где:
TIM1->CCR1 = sine_wave[i];
надо какую-то задержку как минимум, потому что в CCR значение обновляется на каждом цикле, таймер не успевает новый сигнал физически сгенерировать.
@aveal да, значения разные, адекватный
попробую добавить задержку с CCR, спасибо!
Вот пример.
Я по нему делал. Работало.