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.