conduciendo WS2812B usando DMA y temporizadores

1

Estoy intentando portar el octoWS2811 para STM32F103c8T6 .

Este tipo hubmartin ya hizo el trabajo pesado y creó una biblioteca utilizando HAL STM32 . Pero el problema es que no puedo hacer que funcione. Estoy usando Eclipse IDE.

esta es la página de github: github

Este es su sitio web donde explica todo el concepto: sitio web

A continuación se muestra una imagen que explica cómo están configurados todos los temporizadores y DMA para manejar el WS2812B

Intenté la depuración para ver si los DMA se estaban activando al poner un punto de interrupción en la devolución de llamada de semitransferencia y descubrí que no se había activado. Luego intenté poner un punto de interrupción en Temporizador de devolución de llamada con temporizador y descubrí que tampoco se activó.

Intenté remachar en línea y encontré algunos ejemplos similares y siento que los DMA y los temporizadores no están configurados correctamente.

Aquí está la parte del código que, según mi opinión, podría estar equivocada:

TIM_HandleTypeDef    Tim2Handle;
TIM_OC_InitTypeDef tim2OC1;
TIM_OC_InitTypeDef tim2OC2;

uint32_t tim_period;

static void TIM2_init(void)
{
    // TIM2 Periph clock enable
    __HAL_RCC_TIM2_CLK_ENABLE();
// This computation of pulse length should work ok,
// at some slower core speeds it needs some tuning.
tim_period =  SystemCoreClock / 800000; // 0,125us period (10 times lower the 1,25us period to have fixed math below)
uint32_t cc1 = (10 * tim_period) / 36;
uint32_t cc2 = (10 * tim_period) / 15;

Tim2Handle.Instance = TIM2;

Tim2Handle.Init.Period            = tim_period;
Tim2Handle.Init.RepetitionCounter = 0;
Tim2Handle.Init.Prescaler         = 0;
Tim2Handle.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
Tim2Handle.Init.CounterMode       = TIM_COUNTERMODE_UP;
//HAL_TIM_PWM_Init(&Tim2Handle);
if(HAL_TIM_PWM_Init(&Tim2Handle) != HAL_OK)
{
    Error_Handler();
  }

HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);

tim2OC1.OCMode       = TIM_OCMODE_PWM1;
tim2OC1.OCPolarity   = TIM_OCPOLARITY_HIGH;
tim2OC1.Pulse        = cc1;
tim2OC1.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
tim2OC1.OCFastMode   = TIM_OCFAST_DISABLE;
//HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1);
if(HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
      }
tim2OC2.OCMode       = TIM_OCMODE_PWM1;
tim2OC2.OCPolarity   = TIM_OCPOLARITY_HIGH;
tim2OC2.Pulse        = cc2;
tim2OC2.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
tim2OC2.OCFastMode   = TIM_OCFAST_DISABLE;
tim2OC2.OCIdleState  = TIM_OCIDLESTATE_RESET;
tim2OC2.OCNIdleState = TIM_OCNIDLESTATE_RESET;
//HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2);
if(HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2) != HAL_OK)
        {
            Error_Handler();
          }

HAL_TIM_Base_Start(&Tim2Handle);
HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_2);}
DMA_HandleTypeDef     dmaUpdate;
DMA_HandleTypeDef     dmaCC1;
DMA_HandleTypeDef     dmaCC2;

static void DMA_init(void)
{
// TIM2 Update event
__HAL_RCC_DMA1_CLK_ENABLE();
dmaUpdate.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaUpdate.Init.PeriphInc = DMA_PINC_DISABLE;
dmaUpdate.Init.MemInc = DMA_MINC_DISABLE;
dmaUpdate.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaUpdate.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dmaUpdate.Init.Mode = DMA_CIRCULAR;
dmaUpdate.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaUpdate.Instance = DMA1_Channel2;
//dmaUpdate.XferCpltCallback  = TransferComplete;
//dmaUpdate.XferErrorCallback = TransferError;
HAL_DMA_DeInit(&dmaUpdate);
//HAL_DMA_Init(&dmaUpdate);
if(HAL_DMA_Init(&dmaUpdate) != HAL_OK)
            {
                Error_Handler();
              }
//HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
//HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
HAL_DMA_Start(&dmaUpdate, (uint32_t)WS2812_IO_High, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE);


// TIM2 CC1 event
dmaCC1.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaCC1.Init.PeriphInc = DMA_PINC_DISABLE;
dmaCC1.Init.MemInc = DMA_MINC_ENABLE;
dmaCC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaCC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
dmaCC1.Init.Mode = DMA_CIRCULAR;
dmaCC1.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaCC1.Instance = DMA1_Channel5;
//dmaUpdate.XferCpltCallback  = TransferComplete;
//dmaUpdate.XferErrorCallback = TransferError;
//dmaUpdate.XferHalfCpltCallback = TransferHalf;
//HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0);
//HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
HAL_DMA_DeInit(&dmaCC1);
//HAL_DMA_Init(&dmaCC1);
if(HAL_DMA_Init(&dmaCC1) != HAL_OK)
                {
                    Error_Handler();
                  }
HAL_DMA_Start(&dmaCC1, (uint32_t)ws2812bDmaBitBuffer, (uint32_t)&WS2812B_PORT->BRR, BUFFER_SIZE);


// TIM2 CC2 event
dmaCC2.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaCC2.Init.PeriphInc = DMA_PINC_DISABLE;
dmaCC2.Init.MemInc = DMA_MINC_DISABLE;
dmaCC2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
dmaCC2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
dmaCC2.Init.Mode = DMA_CIRCULAR;
dmaCC2.Init.Priority = DMA_PRIORITY_VERY_HIGH;
dmaCC2.Instance = DMA1_Channel7;
dmaCC2.XferCpltCallback  = DMA_TransferCompleteHandler;
dmaCC2.XferHalfCpltCallback = DMA_TransferHalfHandler;
//dmaUpdate.XferErrorCallback = TransferError;
HAL_DMA_DeInit(&dmaCC2);
if(HAL_DMA_Init(&dmaCC2) != HAL_OK)
                    {
                        Error_Handler();
                      }

//  __HAL_LINKDMA(htim, hdma[TIM_DMA_ID_CC2], dmaCC2);
//  HAL_DMA_Init(htim->hdma[TIM_DMA_ID_CC2]);

HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
//HAL_DMA_Start(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE);

if(HAL_DMA_Start(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE) != HAL_OK)
                        {
                            Error_Handler();
                          }
}


void DMA1_Channel2_IRQHandler(void)
{
  // Check the interrupt and clear flag
  HAL_DMA_IRQHandler(&dmaUpdate);
}

void DMA1_Channel5_IRQHandler(void)
{
  // Check the interrupt and clear flag
  HAL_DMA_IRQHandler(&dmaCC1);
}

void DMA1_Channel7_IRQHandler(void)
{
  // Check the interrupt and clear flag
  HAL_DMA_IRQHandler(&dmaCC2);
}

Revisé las hojas de datos relevantes para ver si las solicitudes de DMA y los temporizadores están disponibles y encontré que el temporizador utilizado es compatible.

    
pregunta Rejin Jacob

0 respuestas

Lea otras preguntas en las etiquetas