Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "ws2812.h"
- #define PWM_FREQ 800000UL /* Number in units of hertz */
- #define PWM_1US (1000000UL / PWM_FREQ) /* Number of PWM pulses for 1 us */
- #define RESET_LEN 100UL /* 50us pulse length */
- #define RESET_BYTES_COUNT (RESET_LEN * PWM_1US) /* Number of reset pulses */
- #define BYTES_PER_LED 24 /* Number of bytes per led */
- #define WS2812_LAST_SLOT_LEN 1 /* Additional 1 byte at the end */
- #define WS2812_1 (2 * TIM_PERIOD / 3) /* Logical 1 value */
- #define WS2812_0 (TIM_PERIOD / 3) /* Logical 0 value */
- #define WS2812_RST 0 /* Reset value */
- #define TIM_PRESCALER 0
- #define TIM_PERIOD 44 //works
- TIM_HandleTypeDef htim3;
- DMA_HandleTypeDef hdma_tim3_ch1_trig;
- uint32_t data[RESET_BYTES_COUNT + LED_COUNT * BYTES_PER_LED + WS2812_LAST_SLOT_LEN + RESET_BYTES_COUNT];
- void WS_Init(void) {
- TIM_MasterConfigTypeDef sMasterConfig;
- TIM_OC_InitTypeDef sConfigOC;
- GPIO_InitTypeDef GPIO_InitStruct;
- /* DMA controller clock enable */
- __HAL_RCC_DMA1_CLK_ENABLE();
- __HAL_RCC_TIM3_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- /* Init GPIO */
- GPIO_InitStruct.Pin = GPIO_PIN_4;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_PULLDOWN;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- /* Init timer */
- htim3.Instance = TIM3;
- htim3.Init.Prescaler = TIM_PRESCALER;
- htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
- htim3.Init.Period = TIM_PERIOD;
- htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- HAL_TIM_PWM_Init(&htim3);
- sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
- sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
- HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
- /* Init PWM channel */
- sConfigOC.OCMode = TIM_OCMODE_PWM1;
- sConfigOC.Pulse = htim3.Init.Period / 2;
- sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
- sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
- HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
- hdma_tim3_ch1_trig.Instance = DMA1_Channel6;
- hdma_tim3_ch1_trig.Init.Direction = DMA_MEMORY_TO_PERIPH;
- hdma_tim3_ch1_trig.Init.PeriphInc = DMA_PINC_DISABLE;
- hdma_tim3_ch1_trig.Init.MemInc = DMA_MINC_ENABLE;
- hdma_tim3_ch1_trig.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
- hdma_tim3_ch1_trig.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
- hdma_tim3_ch1_trig.Init.Mode = DMA_NORMAL;
- hdma_tim3_ch1_trig.Init.Priority = DMA_PRIORITY_LOW;
- HAL_DMA_Init(&hdma_tim3_ch1_trig);
- /* Several peripheral DMA handle pointers point to the same DMA handle.
- Be aware that there is only one channel to perform all the requested DMAs. */
- __HAL_LINKDMA(&htim3, hdma[TIM_DMA_ID_CC1], hdma_tim3_ch1_trig);
- __HAL_LINKDMA(&htim3, hdma[TIM_DMA_ID_TRIGGER], hdma_tim3_ch1_trig);
- /* DMA interrupt init */
- /* DMA1_Channel6_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn);
- }
- void WS_Update(void) {
- HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, data, sizeof(data) / sizeof(data[0])); /* Start sending and don't wait for it */
- while (htim3.hdma[TIM_DMA_ID_CC1]->Instance->CNDTR > 0); /* Check if anything to send */
- }
- void WS_SetColor(uint32_t ledIndex, uint8_t r, uint8_t g, uint8_t b, uint8_t update) {
- uint8_t i = 0;
- ledIndex = ledIndex % LED_COUNT;
- for (i = 0; i < 8; i++) { /* Set colors, order is green, red, blue */
- data[RESET_BYTES_COUNT + ledIndex * BYTES_PER_LED + 0 + i] = ((g << i) & 0x80) ? WS2812_1 : WS2812_0;
- data[RESET_BYTES_COUNT + ledIndex * BYTES_PER_LED + 8 + i] = ((r << i) & 0x80) ? WS2812_1 : WS2812_0;
- data[RESET_BYTES_COUNT + ledIndex * BYTES_PER_LED + 16 + i] = ((b << i) & 0x80) ? WS2812_1 : WS2812_0;
- }
- if (update) { /* Update leds on demand */
- WS_Update();
- }
- }
- void WS_SetColorAll(uint8_t r, uint8_t g, uint8_t b, uint8_t update) {
- uint16_t ledIndex = 0;
- /* Set color for all leds */
- for (ledIndex = 0; ledIndex < LED_COUNT; ledIndex++) {
- WS_SetColor(ledIndex, r, g, b, 0); /* Set colors without immediatelly update process */
- }
- if (update) { /* Update leds on demand */
- WS_Update();
- }
- }
- void WS_ScrollForwardColor(uint8_t r, uint8_t g, uint8_t b) { ///It is red, green, blue
- uint8_t index;
- for (index = 0; index < LED_COUNT; index++) {
- WS_SetColorAll(0, 0, 0, 0); /* Set colors for all leds and don't update immediatelly */
- WS_SetColor(index, r, g, b, 1); /* Set color for specific led and update */
- HAL_Delay(50); /* Little delay */
- }
- }
- /* Interrupt function service routine */
- void DMA1_Channel6_IRQHandler(void) {
- HAL_DMA_IRQHandler(&hdma_tim3_ch1_trig);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement