Пробуем ШИМ


Быстрая проба ШИМ, основанной на таймере. Для эксперимента будем использовать Timer 4.
Подключим светодиод, как показано на схеме ниже. Пин PB9 можно использовать, как выход PWM (TIM4_CH4).



Выполним простые шаги:

Инициализация ШИМ:

PWM_TIM4_Init(1000 {частота ШИМ});

Установим коэффициент заполнения:

PWM_TIM4_Set_Duty(duty_cycle, _PWM_NON_INVERTED, _PWM_CHANNEL4);

Здесь мы указываем, что сигнал ШИМ не инвертирован, канал таймера - 4.

Запускаем ШИМ на четвертом канале таймера, который физически подключен к PB9:

PWM_TIM4_Start(_PWM_CHANNEL4, @_GPIO_MODULE_TIM4_CH4_PB9);

Максимальное значение коэффициента заполнения (Duty cycle) мы можем получить при вызове функции инициализации.

Period:= PWM_TIM4_Init(1000 {частота ШИМ});

Для каждого значения частоты ШИМ генератора, значение максимального коэффициента заполнения будет разным, чем выше частота, тем меньше разрешение генератора ШИМ.

Для STM32F103C8T6, для стандартных настроек тактирования, отношения частот и разрешения будет таким:

Frequency Duty cycle
100 65454
250 57600
500 48000
1000 36000
5000 14400
10000 7200
20000 3600
50000 1440
100000 720
500000 144
1000000 72
5000000 14
10000000 7
20000000 3

Применим наш энкодер для регулировки яркости светодиода.

program TestEncoderPWM;

var MenuIndex      : Word;
var Period         : Word;  {Новая переменная!}
var aux_s5         : array[1..5] of Char;
{LCD module connections}
var LCD_RS     : sbit at GPIOB_ODR.B10;
var LCD_EN     : sbit at GPIOB_ODR.B11;
var LCD_D4     : sbit at GPIOB_ODR.B12;
var LCD_D5     : sbit at GPIOB_ODR.B13;
var LCD_D6     : sbit at GPIOB_ODR.B14;
var LCD_D7     : sbit at GPIOB_ODR.B15;
{End LCD module connections}

Procedure InitTIM2(it2Mode: Byte; it2Edge1, it2Edge2: Byte; it2ARV : Word);
Begin
{ Mode 0 - Encoder mode, use input 1 only
  Mode 1 - Encoder mode, use input 2 only
  Mode 2 - Encoder mode, use both channels
  Mode 3 - Direct counting, use input 1
  Mode 4 - Direct counting, use input 2
           see below TIM2_CR1.DIR_ for count direction 
  Edge1  - Rising (0) or falling edge (1) detection for input 1
  Edge2  - Rising (0) or falling edge (1) detection for input 2  
  ARV    - Auto reload value for the Timer }
 GPIO_Alternate_Function_Enable(@_GPIO_MODULE_TIM2_CH1_PA15);
 GPIO_Alternate_Function_Enable(@_GPIO_MODULE_TIM2_CH2_PB3);
 GPIO_Set_Pin_Mode(@GPIOA_BASE, _GPIO_PIN_15, _GPIO_CFG_MODE_ALT_FUNCTION);
 GPIO_Set_Pin_Mode(@GPIOB_BASE, _GPIO_PIN_3,  _GPIO_CFG_MODE_ALT_FUNCTION);
 
 RCC_APB1ENR.TIM2EN       := 1; {Enable switching the Timer2}
 TIM2_CR1.CEN             := 0; {TIM2 disable}
 TIM2_CCER.CC1E           := 0; {Capture 1 disable}
 TIM2_CCER.CC2E           := 0; {Capture 2 disable}
 If it2Edge1 > 0 then TIM2_CCER.CC1P:= 1 else TIM2_CCER.CC1P:= 0;
 If it2Edge2 > 0 then TIM2_CCER.CC2P:= 1 else TIM2_CCER.CC2P:= 0;
 
 TIM2_CR1.DIR_            := 0; {Direction 0 - up, 1- down}
 TIM2_CCMR1_Input.CC1S0   := 1; {01: CC1 channel is configured as input, IC1 is mapped on TI1}
 TIM2_CCMR1_Input.CC1S1   := 0; {01: CC1 channel is configured as input, IC1 is mapped on TI1}
 TIM2_CCMR1_Input.CC2S0   := 1; {01: CC2 channel is configured as input, IC2 is mapped on TI2}
 TIM2_CCMR1_Input.CC2S0   := 0; {01: CC2 channel is configured as input, IC2 is mapped on TI2}

 Case it2Mode of
      0 : begin
           TIM2_SMCR.SMS0:= 0;
           TIM2_SMCR.SMS1:= 1;
           TIM2_SMCR.SMS2:= 0;
          end;
      1 : begin
           TIM2_SMCR.SMS0:= 1;
           TIM2_SMCR.SMS1:= 0;
           TIM2_SMCR.SMS2:= 0;
          end;
      2 : begin
           TIM2_SMCR.SMS0:= 1;
           TIM2_SMCR.SMS1:= 1;
           TIM2_SMCR.SMS2:= 0;
          end;
      3 : begin
           TIM2_SMCR.SMS0:= 1;
           TIM2_SMCR.SMS1:= 1;
           TIM2_SMCR.SMS2:= 1;
           TIM2_SMCR.TS0 := 1;
           TIM2_SMCR.TS1 := 0;
           TIM2_SMCR.TS2 := 1;

          end;
      4 : begin
           TIM2_SMCR.SMS0:= 1;
           TIM2_SMCR.SMS1:= 1;
           TIM2_SMCR.SMS2:= 1;
           TIM2_SMCR.TS0 := 0;
           TIM2_SMCR.TS1 := 1;
           TIM2_SMCR.TS2 := 1;
          end;
 end;                                {Case}
 
 TIM2_ARR                 := it2ARV; {Value for auto reload the counter}

 TIM2_CCMR1_Input.IC1F0   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC1F1   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC1F2   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC1F3   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC2F0   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC2F1   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC2F2   := 1; {Digital filter 00 - %1111}
 TIM2_CCMR1_Input.IC2F3   := 1; {Digital filter 00 - %1111}
 TIM2_CCER.CC1E           := 1; {Capture enable}
 TIM2_CCER.CC2E           := 1; {Capture enable}
 TIM2_CR1.CEN             := 1; {TIM2 enable}
End;

begin
 Period:= PWM_TIM4_Init(10000); {Частота ШИМ - 10 кГц} 
 {Инициализируем таймер для энкодера так, чтобы не выйти за границу максимального значения коэффициента заполнения ШИМ}
 InitTIM2(1, 1, 1, (Period * 2) + 1);
 PWM_TIM4_Set_Duty(0, _PWM_NON_INVERTED, _PWM_CHANNEL4);
 PWM_TIM4_Start(_PWM_CHANNEL4, @_GPIO_MODULE_TIM4_CH4_PB9);
 Lcd_Init;                      {Инициализация LCD}
 Lcd_Cmd(_LCD_CURSOR_OFF);      {Отключаем курсор}
 WordToStr(Period, aux_s5);
 Lcd_Out(2,1, aux_s5);          {Показываем максимальное значение коэффициента заполнения для выбранной частоты}
 InitTIM2(1, 1, 1, 39);         
 
 While True do begin            {Суперцикл}
  MenuIndex:= TIM2_CNT div 2;   {Значение счетчика делим на два}
  {Присваиваем значение положения энкодера значению коэффициента заполнения генератора ШИМ}
  PWM_TIM4_Set_Duty(MenuIndex, _PWM_NON_INVERTED, _PWM_CHANNEL4);
  WordToStr(MenuIndex, aux_s5); {Преобразуем Word в строку}
  Lcd_Out(1,1, aux_s5);         {Выводим строку}
 end;                           {Конец суперцикла}  

end.

Теперь светодиод изменяет свою яркость в зависимости от положения энкодера.

Комментарии

Популярные сообщения из этого блога

Настройка таймера STM32 для работы с энкодером

PS4 Dualshock инверсия правого стика по оси X за два часа.

Настраиваем показания энкодера для применения в меню