This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

STM32F103 + PWM+ DMA +HAL problem?

I have STM32F103 working on 8MHz. Use new ST HAL Driver (STM32CubeMX) + MDK-ARM v5.17?
If I Init PWM on Ch1 Tim3

void MX_TIM3_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig;
  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 9;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_Base_Init(&htim3);

  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);

  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 = 1;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
}
...
// Start PWM
HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);

all working OK and output generate 125ns pulse on 800kHz (1.25us)
If replace Start_IT with DMA version

uint32_t pData[1]={6};
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1,pData,1);

all working OK and output generate 700ns pulse on 800kHz (1.25us),but if use

uint32_t pData[16]={3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0};
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1,pData,16);

this genreate 375ns its OK but frequency is 400kHz (2,5us)
If I trace and look on reg CCR1 I see
3,0,3,0,3,0,3,0,3,0,3,0,3,0,3,0
What's wrong, what's the problem?
Why is inserted 0 between 3?

Parents Reply Children
  • Thanks you, with int16 you have true.
    Confused me function HAL_TIM_PWM_Start_DMA() where is the pointer on uint32_t.

    "Also the period should be 9-1 for 72/9 = 8 MHz"
    Are you sure?
    But if I used 9 see Logic Analyzer in MDK-ARM
    http://imgur.com/XMX5Bmf

    Whole thing is intended for driving WS2812B LED www.adafruit.com/.../WS2812B.pdf
    If I only Run
    PWM with

     htim3.Init.Period =9;
    ...
     sConfigOC.Pulse = 6;
    ...
    HAL_TIM_Base_Start_IT(&htim3);
    


    LED Flash White, but if use

     htim3.Init.Period =9; // or 8
    ...
     sConfigOC.Pulse = 0;
    ...
    uint16_t pData[25]={3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,6,6,6,6,6,6,6,6,0};
    HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1,(uint32_t*)pData,25);
    


    in real hw is LED off
    on simulator see above

  • Complementing:
    I found another datasheet for WS2812B,it contains slightly different timings.
    http://goo.gl/oONsSQ
    The Chinese are great magician on datasheet.
    Maybe the problem is only the timing Log 1

  • Other additions

    Period (ARR) = (Frequency of counter / required frequency)-1
    Period (ARR) = (8MHz / 800kHz)-1
    Period (ARR) = 9

  • I find problem

    ...
    // STM32F103ZE Clock 8MHz
    
      htim3.Init.Period = 9;
    ...
    //                    G G G G G G G G R R R R R R R R B B B B B B B B
    //                    1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
      uint16_t pData[25]={3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,6,6,6,6,6,6,6,6,0};
    //                    --------0------ --------0------ ------256------ STOP
      HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1,(uint32_t*)pData,25);
    


    and HW logic analyzer show this:
    http://imgur.com/QQclNlq

    Instead of 16 ZERO bit is generate 19 ZERO bit
    and instead of 8 ONE bit is generate 9 ONE bit

    Suspect someone in what could be the problem?

  • Data needs to be 16-bit wide like the register, not 32-bit, where high-order 16-bit words are zero, thus alternating 3/0

    Sure? That would indicate a grave error on the part of the library API designer. If the expected data format is really an array of 16 bit integers, then it's badly wrong for the function argument to be of type (uint32_t *).

    Casting a pointer to a different type besides (void *) and (uint8_t *) just to pass it to a function, as suggested here, is almost always either superfluous or very wrong.