On an STM32F103C8T6 (72MHz) I want to use a delay in range of 100's of nanosecond (to create a LED strip driver, WS2813B).
Since HAL only provides a ms delay, I found at various places code to use the ticks/debug counter as timer.
I have the code below:
Initialization:
volatile unsigned int *DWT_CYCCNT = (volatile unsigned int *)0xE0001004; //address of the register
volatile unsigned int *DWT_CONTROL = (volatile unsigned int *)0xE0001000; //address of the register
volatile unsigned int *SCB_DEMCR = (volatile unsigned int *)0xE000EDFC; //address of the register
unsigned int count = 0;
Within main()
:
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CONTROL = *DWT_CONTROL | 1 ; // enable the counter
int ticks = 1;
while (1)
{
unsigned int start, current;
start = *DWT_CYCCNT;
do
{
current = *DWT_CYCCNT;
} while((current - start) < ticks);
if (count++ % 1000 == 0)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
}
}
When I connect a logic analyzer, I see a PWM signal of 0.53 ms per toggle. Since it is toggled every 1,000 counts, this means 0.53 us (530 ns). However, with 1 tick, I would expect something like 1/72,000,000 = 14 ns (plus some overhead for the while loop/counter). (note: the counter for 1,000 I used because my logic analyzer can only handle 200 kHz).
I'm not sure if the addresses in the initialization are correct (found them only for STM32F103VET6).
So my question: What is the mistake in the program above?
(side question: is this method good anyway for a LED driver, or should I send the data by interrupt or DMA?).
Update
The reason I need these kind of delays are for the T0H
, T1H
, T0L
and T1L
times which can be found at WS2813B datasheet, page 5.
Data Transfer Time (TH+TL=1.25µs±300ns)
T0H 0-code, High-level time 300ns~450ns
T1H 1-code, High-level time 750ns~1000ns
T0L 0-code, Low-level time 300ns~100us
T1L 1-code, Low-level time 300ns~100us
RES Frame unit, Low-level time 300µs or more