How to re-enable the timer after a One pulse goes off (OPM)?
Hi guys I am using the stm32h753zi MCU and writing my own drivers to use the WS2812B led strip.
It uses a PWM to determine how much of the RGB you want.
I got the PWM part down and the OPM done, the problem is that I want to send let say a duty cycle of 80% follow by a 32% duty Cycle. I got it working for sending one burst but noted in the datasheet the OPM disables the CEN, however I can never re-enable it?
Is that how OPM works? One time and thats it?
Essentially sending a duty cycle of 80% = 1 and sending a duty cycle of 32% = 0, so thats why I want to send it in pulses in PWM form.
EDIT: 1 Using the TIM15 configured in PWM mode with DMA. The DMA will transfer from a buffer into CCR1 to alter the PW on the fly.
Code:
Timer Setup with DMA
/*
* Timer_Driver.c
*
* Created on: Jan. 8, 2021
* Author: Christopher
*/
#include "Timer.h"
void init_Timer(uint16_t * RGB_Array) {
RCC->APB2ENR |= RCC_APB2ENR_TIM15EN;
GPIOA->MODER &= ~GPIO_MODER_MODE2;
GPIOA->MODER |= GPIO_MODER_MODE2_ALT;
GPIOA->OSPEEDR &= ~GPIO_OSPEEDR_OSPEED2;
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED2_VERY_HIGH;
GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2;
GPIOA->AFR[0] |= GPIO_AFRL_AFSEL2_TIM15;
TIM15->CCMR1 &= ~TIM_CCMR1_CC1S;
TIM15->CCMR1 |= TIM_CCMR1_CC1S_OUTPUT_MODE;
TIM15->CCMR1 &= ~TIM_CCMR1_OC1M;
TIM15->CCMR1 |= TIM_CCMR1_OC1M_PWM1;
TIM15->ARR = 0x12B;
TIM15->PSC = 0x00;
TIM15->AF1 &= ~TIM15_AF1_BKINE;
TIM15->CCMR1 |= TIM_CCMR1_OC1PE;
TIM15->CR1 |= TIM_CR1_ARPE;
TIM15->CR1 |= TIM_CR1_URS;
//TIM15->CR1 |= TIM_CR1_OPM;
TIM15->DIER |= TIM_DIER_UDE;
//TIM15->CCMR1 &= ~TIM_CCMR1_OC1PE;
TIM15->BDTR |= TIM_BDTR_MOE;
TIM15->CCER |= TIM_CCER_CC1E;
//TIM15->CR1 |= TIM_CR1_CEN;
RCC -> AHB1ENR |= RCC_AHB1ENR_DMA1EN;
DMAMUX1_Channel2 -> CCR |= DMAMUX_CxCR_DMAREQ_ID_TIM15_CH1;
DMA1_Stream2 -> CR &= ~DMA_SxCR_CT;
DMA1_Stream2 -> CR &= ~DMA_SxCR_PL;
DMA1_Stream2 -> CR &= ~DMA_SxCR_MSIZE;
DMA1_Stream2 -> CR &= ~DMA_SxCR_PSIZE;
DMA1_Stream2 -> CR &= ~DMA_SxCR_MINC;
DMA1_Stream2 -> CR &= ~DMA_SxCR_CIRC;
DMA1_Stream2 -> CR &= ~DMA_SxCR_DIR;
DMA1_Stream2 -> CR &= ~DMA_SxCR_PFCTRL;
DMA1_Stream2 -> CR &= ~DMA_SxCR_TCIE;
DMA1_Stream2 -> CR &= ~DMA_SxCR_HTIE;
DMA1_Stream2 -> CR |= DMA_SxCR_CT_MEM0;
DMA1_Stream2 -> CR |= DMA_SxCR_PL_Very_High;
DMA1_Stream2 -> CR |= DMA_SxCR_MSIZE_32BIT;
DMA1_Stream2 -> CR |= DMA_SxCR_PSIZE_32BIT;
DMA1_Stream2 -> CR |= DMA_SxCR_MINC;
DMA1_Stream2 -> CR |= DMA_SxCR_CIRC;
DMA1_Stream2 -> CR |= DMA_SxCR_DIR_M_TO_P;
DMA1_Stream2 -> CR |= DMA_SxCR_PFCTRL_DMAFLOW;
//DMA1_Stream2 -> CR |= DMA_SxCR_TCIE;
DMA1_Stream2 -> NDTR = 25;
DMA1_Stream2 -> PAR = (int) &TIM15->CCR1;
DMA1_Stream2 -> M0AR = (int) RGB_Array;
DMA1_Stream2 -> CR |= DMA_SxCR_EN;
}Where the Action happens:
uint16_t RED [25] = {0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77,
0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77, 0x00};
uint16_t BLUE [25] = {0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77,
0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0x00};
uint32_t GREEN [25] = {0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77 ,0x77, 0x00};
void setLedLights(uint8_t color, uint16_t * RGB_Array) {
if (color == 1) {
memcpy(RGB_Array, GREEN, sizeof(uint16_t) * 25);
} else if (color == 2) {
memcpy(RGB_Array, RED, sizeof(uint16_t) * 25);
} else if (color == 3) {
memcpy(RGB_Array, BLUE, sizeof(uint16_t) * 25);
}
TIM15->CR1 |= TIM_CR1_CEN;
}Picture:
