Question
TIM15 can't be enabled when OPM bit is set, why?
Hi everyone,
I am having issues getting One Shot Mode enable when using the TIM15. I am currently using the STM32H743ZI as the MCU.
When setting the OPM bit in the TIM15_CR1 register the CEN bit in same register no longer can be enabled for whatever reason. I tried disabling the Auto-reload preload enable (ARPE bit) in the CR1 register but nothing changed.
Code:
LL_DMA_InitTypeDef WS2812B_Config_DMA;
LL_GPIO_InitTypeDef WS2812B_Config_GPIO;
LL_TIM_InitTypeDef WS2812B_Config_TIM15;
LL_TIM_OC_InitTypeDef WS2812B_Config_OC;
LL_TIM_BDTR_InitTypeDef WS2812B_Config_BDTR;
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM15);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_TIM_StructInit(&WS2812B_Config_TIM15);
LL_TIM_OC_StructInit(&WS2812B_Config_OC);
LL_TIM_BDTR_StructInit(&WS2812B_Config_BDTR);
LL_GPIO_StructInit(&WS2812B_Config_GPIO);
LL_DMA_StructInit(&WS2812B_Config_DMA);
//Configure GPIO
WS2812B_Config_GPIO.Alternate = LL_GPIO_AF_4;
WS2812B_Config_GPIO.Mode = LL_GPIO_MODE_ALTERNATE;
WS2812B_Config_GPIO.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
WS2812B_Config_GPIO.Pin = LL_GPIO_PIN_2;
WS2812B_Config_GPIO.Pull = LL_GPIO_PULL_NO;
WS2812B_Config_GPIO.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
LL_GPIO_Init(GPIOA, &WS2812B_Config_GPIO);
//Configure DMA
WS2812B_Config_DMA.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
WS2812B_Config_DMA.FIFOMode = LL_DMA_FIFOMODE_DISABLE;
WS2812B_Config_DMA.MemBurst = LL_DMA_MBURST_SINGLE;
WS2812B_Config_DMA.MemoryOrM2MDstAddress = (uint32_t)WS28128B_BUFF;
WS2812B_Config_DMA.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD;
WS2812B_Config_DMA.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
WS2812B_Config_DMA.Mode = LL_DMA_MODE_NORMAL;
WS2812B_Config_DMA.NbData = NUM_LED;
WS2812B_Config_DMA.PeriphBurst = LL_DMA_PBURST_SINGLE;
WS2812B_Config_DMA.PeriphOrM2MSrcAddress = (uint32_t)&TIM15->CCR1;
WS2812B_Config_DMA.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD;
WS2812B_Config_DMA.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
WS2812B_Config_DMA.PeriphRequest = LL_DMAMUX1_REQ_TIM15_UP;
WS2812B_Config_DMA.Priority = LL_DMA_PRIORITY_LOW;
//Interrupt: DMA
LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_4);
NVIC_EnableIRQ(DMA1_Stream4_IRQn);
NVIC_SetPriority(DMA1_Stream4_IRQn, 0);
LL_DMA_Init(DMA1, LL_DMA_STREAM_4, &WS2812B_Config_DMA);
WS2812B_Config_TIM15.Autoreload = 240e6/LED_FREQ;
WS2812B_Config_TIM15.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
WS2812B_Config_TIM15.CounterMode = LL_TIM_COUNTERMODE_UP;
WS2812B_Config_TIM15.Prescaler = 0;
WS2812B_Config_TIM15.RepetitionCounter = 0;
LL_TIM_Init(TIM15, &WS2812B_Config_TIM15);
WS2812B_Config_OC.CompareValue = 0;
WS2812B_Config_OC.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
WS2812B_Config_OC.OCMode = LL_TIM_OCMODE_PWM1;
WS2812B_Config_OC.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
WS2812B_Config_OC.OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
WS2812B_Config_OC.OCNState = LL_TIM_OCSTATE_DISABLE;
WS2812B_Config_OC.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
WS2812B_Config_OC.OCState = LL_TIM_OCSTATE_ENABLE;
LL_TIM_OC_Init(TIM15, LL_TIM_CHANNEL_CH1, &WS2812B_Config_OC);
WS2812B_Config_BDTR.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
WS2812B_Config_BDTR.Break2Filter = LL_TIM_BREAK2_FILTER_FDIV1;
WS2812B_Config_BDTR.Break2Polarity = LL_TIM_BREAK2_POLARITY_LOW;
WS2812B_Config_BDTR.Break2State = LL_TIM_BREAK2_DISABLE;
WS2812B_Config_BDTR.BreakFilter = LL_TIM_BREAK_FILTER_FDIV1;
WS2812B_Config_BDTR.BreakPolarity = LL_TIM_BREAK_POLARITY_LOW;
WS2812B_Config_BDTR.BreakState = LL_TIM_BREAK_DISABLE;
WS2812B_Config_BDTR.DeadTime = 0;
WS2812B_Config_BDTR.LockLevel = LL_TIM_LOCKLEVEL_OFF;
WS2812B_Config_BDTR.OSSIState = LL_TIM_OSSI_DISABLE;
WS2812B_Config_BDTR.OSSRState = LL_TIM_OSSR_DISABLE;
LL_TIM_BDTR_Init(TIM15, &WS2812B_Config_BDTR);
LL_TIM_OC_EnablePreload(TIM15, LL_TIM_CHANNEL_CH1);
LL_TIM_EnableARRPreload(TIM15);
LL_TIM_EnableDMAReq_UPDATE(TIM15);
LL_TIM_SetOnePulseMode(TIM15, LL_TIM_ONEPULSEMODE_SINGLE);
LL_TIM_GenerateEvent_UPDATE(TIM15);
LL_TIM_EnableAllOutputs(TIM15);Where TIM15 is enable. Essentially fill up the buffer before enabling the TIMER
void WS2812B::setColour(uint8_t GREEN, uint8_t RED, uint8_t BLUE) {
for (uint32_t LED = 0; LED < NUM_LED; LED++) {
for (int8_t G_bit = 7; G_bit >= 0; G_bit--) {
if ((GREEN & (1<<(7 - G_bit)))) {
WS28128B_BUFF[G_bit] = 0xC0;
} else {
WS28128B_BUFF[G_bit] = 0x60;
}
}
for (int8_t R_bit = 15; R_bit >= 8; R_bit--) {
if ((RED & (1<<(15 - R_bit)))) {
WS28128B_BUFF[R_bit] = 0xC0;
} else {
WS28128B_BUFF[R_bit] = 0x60;
}
}
for (int8_t B_bit = 23; B_bit >= 16; B_bit--) {
if ((BLUE & (1<<(23 - B_bit)))) {
WS28128B_BUFF[B_bit] = 0xC0;
} else {
WS28128B_BUFF[B_bit] = 0x60;
}
}
}
WS28128B_BUFF[(NUM_LED * 24)] = 0x2EE0;
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_4);
LL_TIM_EnableCounter(TIM15);
}