Trong hướng dẫn này, tôi sẽ chia sẻ cách sử dụng PWM trên bảng Discovery STM32F4. PWM (Điều chế độ rộng xung) là một kỹ thuật để tạo ra điện áp tương tự (giá trị trung bình) bằng cách sử dụng các đầu ra kỹ thuật số của vi điều khiển. PWM được sử dụng trong điều khiển tốc độ động cơ DC, điều khiển động cơ servo, đèn LED mờ, tạo âm thanh và nhiều hơn nữa.
Thay đổi PWM Là tạo giá trị ON /OFF các giá trị 0,1 giữ nguyên chu kỳ T ,tần số không thay đổi
Vd đây là giá trị 25% chu kỳ PWM
Để tạo ra PWM với STM32F4, chúng ta có thể sử dụng bộ đếm thời gian. Bộ đếm thời gian có thể đếm từ 0 đến một giá trị nhất định và kích hoạt một số sự kiện ở giữa. Trong chế độ PWM, bộ hẹn giờ có thể điều khiển đầu ra kỹ thuật số của 1 hoặc nhiều kênh đầu ra. Khi bộ đếm thời gian đạt giá trị 0, tối đa hoặc so sánh, giá trị kênh đầu ra có thể được thay đổi để tạo tín hiệu PWM
Khởi tạo PWM
void TIM_Init() { // Enable clock for TIM4 // We use TIM4 because green LED (PD12) is connected // to TIM4_CH1 GPIO AF mapping RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // Timer initialization struct TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; // Create 1kHz PWM // TIM4 is connected to APB1 bus that have default clock 84MHz // So, the frequency of TIM4 is 84MHz // We use prescaler 10 here // So, the frequency of TIM4 now is 8.4MHz TIM_TimeBaseInitStruct.TIM_Prescaler = 10; // TIM_Period determine the PWM frequency by this equation: // PWM_frequency = timer_clock / (TIM_Period + 1) // If we want 1kHz PWM we can calculate: // TIM_Period = (timer_clock / PWM_frequency) - 1 // TIM_Period = (8.4MHz / 1kHz) - 1 = 8399 TIM_TimeBaseInitStruct.TIM_Period = 8399; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // Initialize TIM4 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStruct); // Start TIM4 TIM_Cmd(TIM4, ENABLE); }
void PWM_Init() { // PWM initialization struct TIM_OCInitTypeDef TIM_OCInitStruct; // Common PWM settings TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // Duty cycle calculation equation: // TIM_Pulse = (((TIM_Period + 1) * duty_cycle) / 100) - 1 // Ex. 25% duty cycle: // TIM_Pulse = (((8399 + 1) * 25) / 100) - 1 = 2099 // TIM_Pulse = (((8399 + 1) * 75) / 100) - 1 = 6299 // We initialize PWM value with duty cycle of 25% TIM_OCInitStruct.TIM_Pulse = 2099; TIM_OC1Init(TIM4, &TIM_OCInitStruct); TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); }
#include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" #include "stm32f4xx_tim.h" #include "clock.h" #include "delay.h" int main(void) { // Set clock to 168MHz CLOCK_SetClockTo168MHz(); // Delay initialization DELAY_Init(); // TIM4 initialization TIM_Init(); // PWM initialization PWM_Init(); /* Set clock for GPIOD ------------------------------------------ */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); // Set alternate function of GPIOD pin 12 as PWM outputs GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4); // GPIOD pin 12 as outputs GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOD, &GPIO_InitStruct); /* -------------------------------------------------------------- */ while (1) { // Set green LED brightness from 0 to max int i; for (i = 0; i <= 8399; i += 5) { // If we want to set PWM duty cycle after initialize, // we can't use TIM_OCInitStruct.TIM_Pulse, // but directly to TIM4 compare register 1 (CCR1) TIM4->CCR1 = i; DELAY_Ms(1); } } }