2016-05-04 01:50 PM
hi
im working on a project to drive a WS2812B led string. i use TIM1 as time source and TIM3 for the PWM generation. im so far able to achieve a PWM signal @ 800kHz. For testing, i tried (see stm32f1xx_it.c) to drive the first 3 leds in the led string (24bit per led), therefore, send 3x 0x555555 (3x24bit). i get a 0-1-0-1... data out by using the HAL_TIM_PWM_PulseFinishedCallback function. but unfortunately, after 3x24 times calling the callback, the output sent way more than these 3x24 pulses, since way more than 3 leds are turned on. is it possible that it is not possible, after each pulse to stop the timer and pwm, set the CCR register and then start it again? #no-hablo-hal #no-hablo-hal2016-05-04 01:52 PM
Attachments:
________________ Attachments : Archive.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hzxe&d=%2Fa%2F0X0000000bRa%2FR6CmxvC7rUlRk8LetwghKqNzA33DFbJQWyvHPy1COVc&asPdf=false2016-05-04 03:49 PM
The device is not going to be able to sustain an 800KHz interrupt rate. You will need to create a pulse width table, and use DMA to update the timer at the end of each interval. A table with 100 values would reduce the interrupt rate to 8KHz
2016-05-05 10:16 AM
Hi am.lu,
Yes you can do that either by Timer's DMA burst r by synchronizing two timers. I think Timer chaning is easier: As I understand your need to output periodic N pulses (N =3).To do that,
you Interconnect two timer peripherals peripheral TIM1 and TIM2. TIM1 timer peripheral will generate a PWM signal by a T1_on duty cycle programmed in TIM1_CCR1 and T1 period programmed in TIM1_ARR. TIM2 timer peripheral will ensure that the period of each generation cycle is equal to T2 which is programmed in its TIM2_ARR register.
The TIM2 peripheral timer is configured as master trigger mode to trig the TIM1 peripheral timer input ITR1 via its internal TRGO signal, each update event. The time between two Update Events is the T2 of the waveform targeted.
The TIM1 peripheral timer is configured as slave one pulse (OPM) mode, to generate one pulse when triggered by TIM2 timer peripheral.
In fact, when a rising edge occurs on the trigger input (ITR1) the counter starts up-counting for only one time until it matches the configure period (TIM1_CCR1) equal to 1/F1 and then an UEV occurs. To repeat the pulse generated (the up-counting), we use the repetition counter of TIM1 timer peripheral which we configure to the number of of pulses per the on-going signal waveform portion minus one (i.e. TIM1_RCR = Number_of_pluses_per_portion – 1 = 3-1 ). So, the UEV is only generated after up-counting is repeated for a number of time configured TIM1_RCR +1.
D’ont forget to enable the UEV (by setting UG bit) before ena bling TIM1 to avoid any delay on the generating the first pulse.
Try to apply my recommendation and come back if you face any problems in coding.
-Hannibal-
2016-05-06 04:13 AM
@clive
what i still dont get, if you say a 800kHz interrupt on the timer callback is way to high and i use DMA instead, how do you start the dma transfer after each period? the timer IT still needs to start the DMA transfer at 800kHz??2016-05-06 04:16 AM
hello hannibal, thanks for the suggestions as an alternative for the DMA solution.
I really would like to learn to use the DMAs correctly anyway. so im going first to get to this solution. but as soon as i will use your solution, i hope you can help me then to set up the project using the CubeMX software.2016-05-06 04:35 AM
@clive: here my idea:
1.) i set up the timer @ 800khz, pulse 0 /* TIM3 init function */ void MX_TIM3_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; htim3.Instance = TIM3; htim3.Init.Prescaler = 0; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 89; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim3); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_ENABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_MspPostInit(&htim3); }2.) cubeMX implements the DMA end of transfer callback routine /** * Enable DMA controller clock */ void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel3_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 2, 0); HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn); }3.) initialization /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_RTC_Init(); MX_TIM3_Init();4.) start the services as follows: HAL_TIM_Base_Start HAL_TIM_PWM_Start HAL_TIM_PWM_Start_IT HAL_DMA_Start HAL_DMA_Start_IT5.) application im now able to start the first DMA transfer with the function: HAL_TIM_DMABurst_WriteStart?? then, im going to ignore the DMA end of transfer callback: DMA1_Channel3_IRQHandler and with the Timer callback: TIM3_IRQHandler im going to start the DMA transfer all over again with the next pulse with?? HAL_TIM_DMABurst_WriteStart?? is this what i need to do?
2016-05-06 06:11 AM
what i still dont get, if you say a 800kHz interrupt on the timer callback is way to high and i use DMA instead, how do you start the dma transfer after each period? the timer IT still needs to start the DMA transfer at 800kHz??
The point of using DMA is that is serves the next 10 or 100 update events from a list of parameters, and in so doing decimates the interrupt loading to a point the CPU can actually function.2016-05-07 04:40 AM
so, could you correct me when im wrong:
1.) i start the timer timebase: HAL_TIM_Base_Start() 2.) i start the PWM via DMA: HAL_TIM_PWM_Start_DMA() 3.) when the DMA callback is reached, this means, i already had 100 periods on the output: HAL_DMA_IRQHandler() thats all im going to do? what about HAL_TIM_PWM_Start()? is this automatically started when i start the HAL_TIM_PWM_Start_DMA()? what about HAL_DMA_Start_IT?? is this not even necessary to start up?2016-05-07 07:45 AM
so, could you correct me when im wrong:
I'm not a HAL coder, so I'm not wading into coding issues with it, I have in the past posted several SPL based examples for different STM32 to output to this LED driver, and also ones where I modulate the TIM/PWM using a DMA driving table.