2023-03-15 06:38 AM
Hello,
I'm using Timer_2 channel_1 PWM with DMA to generate the low polarity Pulse.
I set the value of PSC = 72, ARR = 2000 and Fosc = 72 MHz.
uint16_t TIM2_CCR1_Value[25] = {2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 1200, 1500, 1500, 1500, 1500, 500, 1500, 1500, 1500, 1500, 500, 500, 1500, 1500, 1500, 1500, 500};
Explanation of above I given TIM2_CCR1 array value,
Free bit {2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100} = {0, 0, 0, 0, 0, 0, 0, 0}.
Start bit 1200 mean 1.2ms off and 0.8ms on.
Data_0 {1500, 1500, 1500, 1500, 500, 1500, 1500, 1500} = {0, 0, 0, 0, 1, 0, 0, 0}.
Data_1 {1500, 500, 500, 1500, 1500, 1500, 1500, 500} = {0, 1, 1, 0, 0, 0, 0, 1}.
below I given the TIM2_CCR1 array values WaveForm,
here, Free bit and Start bit timing is 20.0155 ms. Data_0 and Data_1 totally 16 bit but i get only 15 bit. after I found that missing first bit data(value is 0).
I don't know where I made a mistake and how to slove this.
2023-03-15 10:25 AM
Try to change TIM2_CCR1_Value so that it displays some different sequence. Still missing one pulse?
JW
2023-03-16 05:12 AM
@Community member
Thank you for your comment and i change the
Free bit {2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001} = {0, 0, 0, 0, 0, 0, 0, 0}.
but still missing one pulse(same problem).
2023-03-16 06:00 AM
I don't know what are you doing and how are you doing it, you've posted no code - and honestly, even if you would, I probably wouldn't want to read it.
Also, as far as timer functionality goes, there's no difference between
Free bit {2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001} = {0, 0, 0, 0, 0, 0, 0, 0}
and
Free bit {2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100} = {0, 0, 0, 0, 0, 0, 0, 0}.
both are CCR1>ARR thus both result in output being permanently low.
What I had in mind was, that you change the values which actually produce pulses, in a way that you can see on the waveform what has changed; change the number of those pulses, maybe to a small number - four perhaps? - and make all of them different so you can distinguish them on the output.
You have an error in your program, and I want you to find that error. Quite likely it's something like you are stopping DMA or timer prematurely or something like that. Making significant/related changes and observing the result is the way to debug.
JW
2023-03-19 12:45 AM
hi,
i try to achive this(above example) type of wave form.
i upload my code,
#include<stm32f10x.h>
uint16_t TIM2_CCR1_Value[25] = {2001, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 1200, 1500, 1500, 1500, 1500, 500, 1500, 1500, 1500, 1500, 500, 500, 1500, 1500, 1500, 1500, 500};
void TIM2_PWM()
{
RCC->APB1ENR |= 0x00000001; //Timer 2 clock is Enable
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN ; // I/O port A clock is Enable
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // DMA1 clock enable
GPIOA->CRL = 0x0000000B; // Output Mode For PWM Pin is PA0
TIM2->ARR = 2000; //ARR VALUE IS 0 - 65535
TIM2->PSC = 72 - 1; //PERSCALER VALUE IS 0 - 65535
TIM2->CNT = 0; //Reset the current count
TIM2->CCMR1 |= 0x00000068; //Configure the pins as PWM
TIM2->CCER |= (TIM_CCER_CC1E | TIM_CCER_CC1P); //Capture/Compare 1 output enable & Capture/Compare 1 output polarity
TIM2->DIER |= TIM_DIER_CC1DE; //Capture/Compare 1 DMA request enable
TIM2->DIER |= TIM_DIER_UIE; //Update interrupt enable
NVIC_EnableIRQ(TIM2_IRQn); //Interrupt enable
TIM2->CR1 |= 0x00000001; //Enable counter
/********** TIM2_CHANNEL1 PWM with DMA1_CHANNEL_5 **********/
DMA1_Channel5->CPAR =(uint32_t)&TIM2->CCR1; // Configure the peripheral data register address
DMA1_Channel5->CMAR =(uint32_t)TIM2_CCR1_Value; // Configure the memory address
DMA1_Channel5->CNDTR = 25; // Number of data to transfer
/*** Data transfer direction, Memory increment mode, Circular mode ***/
DMA1_Channel5->CCR |= (DMA_CCR5_DIR | DMA_CCR5_MINC | DMA_CCR5_CIRC);
DMA1_Channel5->CCR |= (DMA_CCR5_MSIZE_0 | DMA_CCR5_PSIZE_0); // Memory size is 01: 16-bits & Peripheral size is 01: 16-bits
DMA1_Channel5->CCR |= DMA_CCR5_EN; // Enable DMA Channel 5
}
int main()
{
TIM2_PWM();
while(1)
{
}
}
void TIM2_IRQHandler(void)
{
TIM2->SR&= ~TIM_SR_UIF;
}
I don't know where I made a mistake. help me.
2023-03-19 12:32 PM
> TIM2->DIER |= TIM_DIER_CC1DE; //Capture/Compare 1 DMA request enable
No. Use TIM_DIER_UDE.
JW
2023-03-19 12:56 PM
CNT acting-CCR1 buffer-CCR1
1999 2001 2001 acting-CCR1 and buffer-CCR1 from
previous DMA transfers
2000 2001 2001 CNT==ARR => update event,
at the same time CC1 event
(because CCR1>ARR)
=> request towards DMA
0 2001 2001 buffer-CCR1 was transferred to
acting-CCR1 because of Update
(because CCMR1.OC1PE=1)
1
...
5 2001 1200 it took some time for DMA to be
triggered and perform transfer
- maybe not 5 timer ticks, but
lets say this is a good rough
estimate - so buffer-CCR1 now
holds the new value DMA moved
from the array in memory
...
1999 2001 1200
2000 2001 1200 CNT==ARR => update event,
at the same time CC1 event
(because CCR1>ARR)
=> request towards DMA
0 1200 1200 buffer-CCR1 transferred to
acting-CCR1
1 1200 1200
...
5 1200 first 1500 DMA transferred the first 1500
...
1190 1200 first 1500
1200 1200 first 1500 CC1 event => request towards DMA
...
1205 1200 second 1500 DMA transferred the second 1500
-- note, that the first 1500 is
at this point overwritten without
having been used
...
2000 1200 second 1500 CNT==ARR => update event
0 second 1500 second 1500 buffer-CCR1 transferred
to acting-CCR1
etc. - in this period, pulse is output at 1500 as expected,
but there were two DMA transfers in the previous period
thus one value (the "first 1500") was already "lost",
which is exactly what was observed
Using Update for DMA triggering, instead of CC1, ensures
that there is exactly one DMA transfer each period,
avoiding this problem.
2023-03-22 03:15 AM
Another take (created using https://wavedrom.com/ an impresive free online waveform "drawer"), maybe more illustrative ?
a, f, k, t, y -- when CNT==ARR, CNT is zeroed and UPdate event is generated
d, i, n, u, z -- UPdate event causes the value from buffer-CCR1
to be transferred into acting-CCR1
b, g, l -- if acting-CCR1>ARR, Compare (CC1) event is generated at UPdate
q, v -- if acting-CCR1<=ARR (as is usual), CC1 event is generated
when CNT==acting_CCR1
c, h, m, r, w -- DMA is set so that it is triggered by the CC1 event;
it takes some time until DMA fulfills the request by transferring data from
memory to buffer-CCR1, here we used as an example 5 timer-cycles
e, j, o, s, x -- DMA transfers value from buffer in RAM into buffer-CCR1
and increments the pointer into memory (DMA_MAR)
Note, that in the period between k and t there are two DMA transfers. This means,
that there's one less timer period than total DMA transfers, thus one less pulse
in the observed pulsetrain. The value 1500 from memory buffer position 8 (marked
as 1500 [1]) gets overwritten in the buffer-CCR1 by the next value (1500 [2])
before UPdate, i.e. it never contributes to pulse generation, so between
the 1200- and 500-pulse there are only two 1500-pulses, instead of three.
Remedy is simple, for PWM, perform the DMA-to-CCRx transfer upon UPdate event,
not upon the CCRx event. In that way, there's exactly one transfer per period.
CCRx buffering ensures that whatever the DMA transfer delay is, the new value
won't be used in this particular period, but in the next period (after the next
UPdate event transfers this value from buffer-CCRx into acting-CCR).
JW