zoukankan      html  css  js  c++  java
  • stm-ledstrip : Driver and test routine for WS2811 RGB-LED

    stm-ledstrip : Driver and test routine for WS2811 RGB-LED  

    #include "ws2812.h"
    #include <stm32f4xx.h>
    #include <stm32f4xx_rcc.h>
    #include <stm32f4xx_gpio.h>
    #include <stm32f4xx_tim.h>
    #include <stm32f4xx_dma.h>
    
    static uint16_t PWM_Buffer[ PWM_BUFFER_SIZE ];
    uint32_t frame_pos = 0;
    int incomplete_return = 0;
    
    void Update_Buffer( uint16_t* buffer );
    
    static void start_dma( void )
    {
      static DMA_InitTypeDef dma_init =
      { .DMA_BufferSize = PWM_BUFFER_SIZE, .DMA_Channel = DMA_Channel_5, .DMA_DIR =
        DMA_DIR_MemoryToPeripheral, .DMA_FIFOMode = DMA_FIFOMode_Disable,
        .DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull, .DMA_Memory0BaseAddr =
          (uint32_t) PWM_Buffer, .DMA_MemoryBurst = DMA_MemoryBurst_Single,
        .DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord, .DMA_MemoryInc =
          DMA_MemoryInc_Enable, .DMA_Mode = DMA_Mode_Circular,
        .DMA_PeripheralBaseAddr = (uint32_t) &TIM3->CCR4, .DMA_PeripheralBurst =
          DMA_PeripheralBurst_Single, .DMA_PeripheralDataSize =
          DMA_PeripheralDataSize_HalfWord, .DMA_PeripheralInc =
          DMA_PeripheralInc_Disable, .DMA_Priority = DMA_Priority_Medium };
      
      DMA_Init( DMA1_Stream2, &dma_init );
      DMA_Cmd( DMA1_Stream2, ENABLE );
      TIM_DMACmd( TIM3, TIM_DMA_CC4, ENABLE );
    }
    
    static void init_buffers( void )
    {
      for ( int i = 0; i < PWM_BUFFER_SIZE; i++ )
      {
        PWM_Buffer[ i ] = 0;
      }
      for ( int i = 0; i < FRAMEBUFFER_SIZE; i++ )
      {
        ws2812_framebuffer[ i ].red = 0;
        ws2812_framebuffer[ i ].green = 0;
        ws2812_framebuffer[ i ].blue = 0;
      }
    }
    
    void ws2812_init( )
    {
      init_buffers( );
      
      //InitStructures...
      GPIO_InitTypeDef GPIO_InitStructure;
      TIM_TimeBaseInitTypeDef TIM_TimeBase_InitStructure;
      TIM_OCInitTypeDef TIM_OC_InitStructure;
      NVIC_InitTypeDef nvic_init;
      
      //Clock für GPIO setzen
      RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOC, ENABLE );
      
      //Clock für TIM4 setzen
      RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
      
      //GPIO_PIN konfigurieren
      
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_Init( GPIOC, &GPIO_InitStructure );
      
      //GPIO Alternate function verbinden
      GPIO_PinAFConfig( GPIOC, GPIO_PinSource9, GPIO_AF_TIM3 );
      
      TIM_TimeBase_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
      TIM_TimeBase_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
      TIM_TimeBase_InitStructure.TIM_Period = 104;
      TIM_TimeBase_InitStructure.TIM_Prescaler = 0;
      TIM_TimeBaseInit( TIM3, &TIM_TimeBase_InitStructure );
      
      TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      TIM_OC_InitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
      TIM_OC_InitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
      TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
      TIM_OC_InitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
      TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OC_InitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
      TIM_OC_InitStructure.TIM_Pulse = 0;
      TIM_OC4Init( TIM3, &TIM_OC_InitStructure );
      
      TIM_CtrlPWMOutputs( TIM3, ENABLE );
      
      TIM_OC4PreloadConfig( TIM3, TIM_OCPreload_Enable );
      TIM_ARRPreloadConfig( TIM3, ENABLE );
      
      TIM_CCxCmd( TIM3, TIM_Channel_4, TIM_CCx_Enable );
      TIM_Cmd( TIM3, ENABLE );
      
      // DMA
      RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA1, ENABLE );
      TIM_DMACmd( TIM3, TIM_DMA_CC4, ENABLE );
      DMA_ITConfig( DMA1_Stream2, DMA_IT_HT, ENABLE );
      DMA_ITConfig( DMA1_Stream2, DMA_IT_TC, ENABLE );
      
      start_dma( );
      
      // NVIC for DMA
      nvic_init.NVIC_IRQChannel = DMA1_Stream2_IRQn;
      nvic_init.NVIC_IRQChannelPreemptionPriority = 4;
      nvic_init.NVIC_IRQChannelSubPriority = 0;
      nvic_init.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init( &nvic_init );
    }
    
    // writes the pwm values of one byte into the array which will be used by the dma
    static inline void color2pwm( uint16_t ** const dest, const uint8_t color )
    {
      uint8_t mask = 0x80;
      
      do
      {
        if ( color & mask )
        {
          * *dest = 49;
        }
        else
        {
          * *dest = 20;
        }
        *dest += 1;
        mask >>= 1;
      }while ( mask != 0 );
    }
    
    void Update_Buffer( uint16_t* buffer )
    {
      struct led *framebufferp;
      uint32_t i, j;
      uint16_t * bufp;
      
      for ( i = 0; i < ( PWM_BUFFER_SIZE / 2 ) / 24; i++ )
      {
        if ( incomplete_return )
        {
          incomplete_return = 0;
          for ( j = 0; j < 24; j++ )
          {
            buffer[ i * 24 + j ] = 0;
          }
          
        }
        else
        {
          if ( frame_pos == FRAMEBUFFER_SIZE )
          {
            incomplete_return = 1;
            frame_pos = 0;
            
            for ( j = 0; j < 24; j++ )
            {
              buffer[ i * 24 + j ] = 0;
            }
          }
          else
          {
            framebufferp = &ws2812_framebuffer[ frame_pos++ ];
            bufp = buffer + ( i * 24 );
            
            // edit here to change order of colors in "ws2812_framebuffer" (0x00RRGGBB, 0x00GGBBRR, etc)
            // the chip needs G R B
            color2pwm( &bufp, framebufferp->green ); // green
            color2pwm( &bufp, framebufferp->red ); // red
            color2pwm( &bufp, framebufferp->blue ); // blue
          }
        }
      }
    }
    
    void DMA1_Stream2_IRQHandler( void )
    {
      // Half-Transfer completed
      if ( DMA_GetITStatus( DMA1_Stream2, DMA_IT_HTIF2 ) )
      {
        DMA_ClearITPendingBit( DMA1_Stream2, DMA_IT_HTIF2 );
        Update_Buffer( PWM_Buffer );
      }
      
      // Transfer completed
      if ( DMA_GetITStatus( DMA1_Stream2, DMA_IT_TCIF2 ) )
      {
        DMA_ClearITPendingBit( DMA1_Stream2, DMA_IT_TCIF2 );
        Update_Buffer( PWM_Buffer + ( PWM_BUFFER_SIZE / 2 ) );
      }
      
    }
  • 相关阅读:
    12月10日,小雪
    12月10日,小雪
    BUG
    Twenty Hours
    BUG
    07中华小姐大赛落幕 20岁佳丽曾光夺冠
    Twenty Hours
    jeecg 页面标签规则
    jeecg导入备份
    jeecg查询分页
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4762102.html
Copyright © 2011-2022 走看看