78-WS2812-Library (STM32F4)
78-WS2812-Library (STM32F4)
//--------------------------------------------------------------
// File : stm32_ub_ws2812.h
//-------------------------------------------------------------- //--------------------------------------------------------------
#ifndef __STM32F4_UB_WS2812_H
#define __STM32F4_UB_WS2812_H //--------------------------------------------------------------
// Includes
//--------------------------------------------------------------
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_dma.h"
#include "misc.h" //--------------------------------------------------------------
// Anzahl der WS2812-LEDs (1...n) in den einzelnen Ketten
// CPU -> LED_1 -> LED_2 -> LED_3 -> LED_n
//
// falls ein Channel nicht benutzt wird => laenge auf 0 setzen
//--------------------------------------------------------------
#define WS2812_LED_CH1_ANZ 5 // [CH1 an PC6] LED-Kette mit 5 LEDs
#define WS2812_LED_CH2_ANZ 0 // [CH2 an PB5] CH2 wird nicht benutzt
#define WS2812_LED_CH3_ANZ 0 // [CH3 an PB0] CH3 wird nicht benutzt
#define WS2812_LED_CH4_ANZ 0 // [CH4 an PB1] CH4 wird nicht benutzt #define WS2812_LED_MAX_ANZ 5 // anzahl der LEDs in der laengsten Kette //--------------------------------------------------------------
// check der laengenangaben
//--------------------------------------------------------------
#if WS2812_LED_CH1_ANZ>WS2812_LED_MAX_ANZ
#error wrong len
#endif
#if WS2812_LED_CH2_ANZ>WS2812_LED_MAX_ANZ
#error wrong len
#endif
#if WS2812_LED_CH3_ANZ>WS2812_LED_MAX_ANZ
#error wrong len
#endif
#if WS2812_LED_CH4_ANZ>WS2812_LED_MAX_ANZ
#error wrong len
#endif #if (WS2812_LED_MAX_ANZ>WS2812_LED_CH1_ANZ) && (WS2812_LED_MAX_ANZ>WS2812_LED_CH2_ANZ)
#if (WS2812_LED_MAX_ANZ>WS2812_LED_CH3_ANZ) && (WS2812_LED_MAX_ANZ>WS2812_LED_CH4_ANZ)
#error wrong len
#endif
#endif //--------------------------------------------------------------
// benutzer Timer fuer das Daten-Signal => TIM3
//--------------------------------------------------------------
#define WS2812_TIM_CLOCK RCC_APB1Periph_TIM3
#define WS2812_TIM TIM3
#define WS2812_TIM_AF GPIO_AF_TIM3
#define WS2812_TIM_CH1 1
#define WS2812_TIM_CCR_REG1 TIM3->CCR1
#define WS2812_TIM_DMA_TRG1 TIM_DMA_CC1
#define WS2812_TIM_CH2 2
#define WS2812_TIM_CCR_REG2 TIM3->CCR2
#define WS2812_TIM_DMA_TRG2 TIM_DMA_CC2
#define WS2812_TIM_CH3 3
#define WS2812_TIM_CCR_REG3 TIM3->CCR3
#define WS2812_TIM_DMA_TRG3 TIM_DMA_CC3
#define WS2812_TIM_CH4 4
#define WS2812_TIM_CCR_REG4 TIM3->CCR4
#define WS2812_TIM_DMA_TRG4 TIM_DMA_CC4 //--------------------------------------------------------------
// GPIO-Pins (CH1...CH4) fuer Data-OUT
//
// moegliche Pinbelegungen (bei TIM3)
// CH1 : [PA6, PB4, PC6]
// CH2 : [PA7, PB5, PC7]
// CH3 : [PB0, PC8]
// CH4 : [PB1, PC9]
//--------------------------------------------------------------
#define WS2812_CH1_CLOCK RCC_AHB1Periph_GPIOC
#define WS2812_CH1_PORT GPIOC
#define WS2812_CH1_PIN GPIO_Pin_6
#define WS2812_CH1_SOURCE GPIO_PinSource6 #define WS2812_CH2_CLOCK RCC_AHB1Periph_GPIOB
#define WS2812_CH2_PORT GPIOB
#define WS2812_CH2_PIN GPIO_Pin_5
#define WS2812_CH2_SOURCE GPIO_PinSource5 #define WS2812_CH3_CLOCK RCC_AHB1Periph_GPIOB
#define WS2812_CH3_PORT GPIOB
#define WS2812_CH3_PIN GPIO_Pin_0
#define WS2812_CH3_SOURCE GPIO_PinSource0 #define WS2812_CH4_CLOCK RCC_AHB1Periph_GPIOB
#define WS2812_CH4_PORT GPIOB
#define WS2812_CH4_PIN GPIO_Pin_1
#define WS2812_CH4_SOURCE GPIO_PinSource1 //--------------------------------------------------------------
// benutzer DMA
// => TIM3-CC1 => DMA1, Channel5, Stream4
// => TIM3-CC2 => DMA1, Channel5, Stream5
// => TIM3-CC3 => DMA1, Channel5, Stream7
// => TIM3-CC4 => DMA1, Channel5, Stream2
// (siehe Seite 216+217 vom Referenz Manual)
//--------------------------------------------------------------
#define WS2812_DMA_CLOCK RCC_AHB1Periph_DMA1 #define WS2812_DMA_CH1_STREAM DMA1_Stream4
#define WS2812_DMA_CH1_CHANNEL DMA_Channel_5 #define WS2812_DMA_CH2_STREAM DMA1_Stream5
#define WS2812_DMA_CH2_CHANNEL DMA_Channel_5 #define WS2812_DMA_CH3_STREAM DMA1_Stream7
#define WS2812_DMA_CH3_CHANNEL DMA_Channel_5 #define WS2812_DMA_CH4_STREAM DMA1_Stream2
#define WS2812_DMA_CH4_CHANNEL DMA_Channel_5 //--------------------------------------------------------------
// Transfer-Complete Interrupt
// CC1 => DMA1, Stream4
// CC2 => DMA1, Stream5
// CC3 => DMA1, Stream7
// CC4 => DMA1, Stream2
//--------------------------------------------------------------
#define WS2812_DMA_CH1_IRQn DMA1_Stream4_IRQn
#define WS2812_DMA_CH1_ISR DMA1_Stream4_IRQHandler
#define WS2812_DMA_CH1_IRQ_FLAG DMA_IT_TCIF4 #define WS2812_DMA_CH2_IRQn DMA1_Stream5_IRQn
#define WS2812_DMA_CH2_ISR DMA1_Stream5_IRQHandler
#define WS2812_DMA_CH2_IRQ_FLAG DMA_IT_TCIF5 #define WS2812_DMA_CH3_IRQn DMA1_Stream7_IRQn
#define WS2812_DMA_CH3_ISR DMA1_Stream7_IRQHandler
#define WS2812_DMA_CH3_IRQ_FLAG DMA_IT_TCIF7 #define WS2812_DMA_CH4_IRQn DMA1_Stream2_IRQn
#define WS2812_DMA_CH4_ISR DMA1_Stream2_IRQHandler
#define WS2812_DMA_CH4_IRQ_FLAG DMA_IT_TCIF2 //--------------------------------------------------------------
// RGB LED Farbdefinition (3 x 8bit)
//--------------------------------------------------------------
typedef struct
{
uint8_t red; // 0...255 (als PWM-Wert)
uint8_t green; // 0...255 (als PWM-Wert)
uint8_t blue; // 0...255 (als PWM-Wert)
} WS2812_RGB_t; //--------------------------------------------------------------
// HSV LED Farbdefinition
//--------------------------------------------------------------
typedef struct
{
uint16_t h; // 0...359 (in Grad, 0=R, 120=G, 240=B)
uint8_t s; // 0...100 (in Prozent)
uint8_t v; // 0...100 (in Prozent)
} WS2812_HSV_t; //--------------------------------------------------------------
// Globale Buffer fuer die Farben (als RGB-Wert)
//--------------------------------------------------------------
#if WS2812_LED_CH1_ANZ>0
WS2812_RGB_t WS2812_LED_BUF_CH1[ WS2812_LED_CH1_ANZ ];
#endif #if WS2812_LED_CH2_ANZ>0
WS2812_RGB_t WS2812_LED_BUF_CH2[WS2812_LED_CH2_ANZ];
#endif #if WS2812_LED_CH3_ANZ>0
WS2812_RGB_t WS2812_LED_BUF_CH3[WS2812_LED_CH3_ANZ];
#endif #if WS2812_LED_CH4_ANZ>0
WS2812_RGB_t WS2812_LED_BUF_CH4[WS2812_LED_CH4_ANZ];
#endif //--------------------------------------------------------------
// standard Farben (R,G,B)
//--------------------------------------------------------------
#define WS2812_RGB_COL_OFF (WS2812_RGB_t) {0x00,0x00,0x00} #define WS2812_RGB_COL_BLUE (WS2812_RGB_t) {0x00,0x00,0xFF}
#define WS2812_RGB_COL_GREEN (WS2812_RGB_t) {0x00,0xFF,0x00}
#define WS2812_RGB_COL_RED (WS2812_RGB_t) {0xFF,0x00,0x00}
#define WS2812_RGB_COL_WHITE (WS2812_RGB_t) {0xFF,0xFF,0xFF} #define WS2812_RGB_COL_CYAN (WS2812_RGB_t) {0x00,0xFF,0xFF}
#define WS2812_RGB_COL_MAGENTA (WS2812_RGB_t) {0xFF,0x00,0xFF}
#define WS2812_RGB_COL_YELLOW (WS2812_RGB_t) {0xFF,0xFF,0x00} //--------------------------------------------------------------
// standard Farben (H,S,V)
//--------------------------------------------------------------
#define WS2812_HSV_COL_OFF (WS2812_HSV_t) {0, 0, 0} #define WS2812_HSV_COL_BLUE (WS2812_HSV_t) {240,100,100}
#define WS2812_HSV_COL_GREEN (WS2812_HSV_t) {120,100,100}
#define WS2812_HSV_COL_RED (WS2812_HSV_t) {0, 100,100} #define WS2812_HSV_COL_CYAN (WS2812_HSV_t) {180,100,100}
#define WS2812_HSV_COL_MAGENTA (WS2812_HSV_t) {300,100,100}
#define WS2812_HSV_COL_YELLOW (WS2812_HSV_t) {60, 100,100} //--------------------------------------------------------------
// WS2812 Timing : (1.25us = 800 kHz)
// logische-0 => HI:0.35us , LO:0.90us
// logische-1 = HI:0.90us , LO:0.35us
//
// WS23812 Bit-Format : (8G8R8B)
// 24bit pro LED (30us pro LED)
// 8bit pro Farbe (MSB first)
// Farbreihenfolge : GRB
//
// nach jedem Frame von n-LEDs kommt eine Pause von >= 50us
//
// Grundfrequenz (TIM3) = 2*APB1 (APB1=42MHz) => TIM_CLK=84MHz
// periode : 0 bis 0xFFFF
// prescale : 0 bis 0xFFFF
//
// PWM-Frq = TIM_CLK/(periode+1)/(vorteiler+1)
//--------------------------------------------------------------
#define WS2812_TIM_PRESCALE 0 // F_T3 = 84 MHz (11.9ns)
#define WS2812_TIM_PERIODE 104 // F_PWM = 80 kHz (1.25us) #define WS2812_LO_TIME 29 // 29 * 11.9ns = 0.34us
#define WS2812_HI_TIME 76 // 76 * 11.9ns = 0.90us //--------------------------------------------------------------
// defines vom WS2812 (nicht abaendern)
//--------------------------------------------------------------
#define WS2812_BIT_PER_LED 24 // 3*8bit pro LED
#define WS2812_PAUSE_ANZ 2 // fuer Pause (2*30us) #define WS2812_TIMER_BUF_LEN1 (WS2812_LED_CH1_ANZ+WS2812_PAUSE_ANZ)*WS2812_BIT_PER_LED
#define WS2812_TIMER_BUF_LEN2 (WS2812_LED_CH2_ANZ+WS2812_PAUSE_ANZ)*WS2812_BIT_PER_LED
#define WS2812_TIMER_BUF_LEN3 (WS2812_LED_CH3_ANZ+WS2812_PAUSE_ANZ)*WS2812_BIT_PER_LED
#define WS2812_TIMER_BUF_LEN4 (WS2812_LED_CH4_ANZ+WS2812_PAUSE_ANZ)*WS2812_BIT_PER_LED
#define WS2812_TIMER_BUF_LEN (WS2812_LED_MAX_ANZ+WS2812_PAUSE_ANZ)*WS2812_BIT_PER_LED //--------------------------------------------------------------
// Globale Funktionen
//--------------------------------------------------------------
void UB_WS2812_Init( void );
void UB_WS2812_SetChannel( uint8_t ch );
void UB_WS2812_Refresh( void );
void UB_WS2812_RGB_2_HSV( WS2812_HSV_t hsv_col, WS2812_RGB_t *rgb_col );
void UB_WS2812_One_Led_RGB( uint32_t nr, WS2812_RGB_t rgb_col, uint8_t refresh );
void UB_WS2812_All_Led_RGB( WS2812_RGB_t rgb_col, uint8_t refresh );
void UB_WS2812_One_Led_HSV( uint32_t nr, WS2812_HSV_t hsv_col, uint8_t refresh );
void UB_WS2812_All_Led_HSV( WS2812_HSV_t hsv_col, uint8_t refresh );
void UB_WS2812_Shift_Left( void );
void UB_WS2812_Shift_Right( void );
void UB_WS2812_Rotate_Left( void );
void UB_WS2812_Rotate_Right( void ); //--------------------------------------------------------------
#endif // __STM32F4_UB_WS2812_H
//--------------------------------------------------------------
// File : stm32_ub_ws2812.c
// Datum : 25.04.2014
// Version : 1.2
// Autor : UB
// EMail : mc-4u(@)t-online.de
// Web : www.mikrocontroller-4u.de
// CPU : STM32F4
// IDE : CooCox CoIDE 1.7.4
// GCC : 4.7 2012q4
// Module : GPIO, TIM, DMA, MISC
// Funktion : RGB-LED mit WS2812-Chip (LED Vcc = 3,3V !!)
// (einzelne LED oder bis zu 4 Ketten von n-LEDs)
//
// Hinweis : es koennen bis zu 4 LED-Ketten betrieben werden
// die Anzahl der LEDs pro Kette und der benutzte
// GPIO-Pin muss im H-File eingestellt werden
//
// CH1 = PC6 (LED-Kette mit 5 LEDs)
// CH2 = PB5 (nicht aktiv)
// CH3 = PB0 (nicht aktiv)
// CH4 = PB1 (nicht aktiv)
//-------------------------------------------------------------- //--------------------------------------------------------------
// Includes
//--------------------------------------------------------------
#include "stm32_ub_ws2812.h" //--------------------------------------------------------------
// Globale interne Variabeln
//--------------------------------------------------------------
uint32_t ws2812_dma_status;
uint16_t WS2812_TIMER_BUF[ WS2812_TIMER_BUF_LEN ];
uint8_t ws2812_channel;
WS2812_RGB_t *ws2812_ptr;
uint32_t ws2812_maxanz; //--------------------------------------------------------------
// interne Funktionen
//--------------------------------------------------------------
void p_WS2812_clearAll( void );
void p_WS2812_calcTimerBuf( void );
void p_WS2812_InitIO( void );
void p_WS2812_InitTIM( void );
void p_WS2812_InitDMA( void );
void p_WS2812_InitNVIC( void );
void p_WS2812_DMA_Start( void ); //--------------------------------------------------------------
// init aller WS2812-Ketten
// alle LEDs ausschalten
// (aktiv ist die Kette mit der niedrigsten Channel-Nr)
//--------------------------------------------------------------
void UB_WS2812_Init( void )
{
uint32_t n; // init aller Variabeln
ws2812_dma_status = ;
ws2812_channel = ;
ws2812_maxanz = ; // init vom Timer Array
for ( n = ; n < WS2812_TIMER_BUF_LEN; n++ )
{
WS2812_TIMER_BUF[ n ] = ; // 0 => fuer Pausenzeit
} // init der LED Arrays aller Ketten
#if WS2812_LED_CH4_ANZ>0
for(n=;n<WS2812_LED_CH4_ANZ;n++)
{
WS2812_LED_BUF_CH4[n]=WS2812_RGB_COL_OFF;
}
ws2812_channel=;
#endif
#if WS2812_LED_CH3_ANZ>0
for(n=;n<WS2812_LED_CH3_ANZ;n++)
{
WS2812_LED_BUF_CH3[n]=WS2812_RGB_COL_OFF;
}
ws2812_channel=;
#endif
#if WS2812_LED_CH2_ANZ>0
for(n=;n<WS2812_LED_CH2_ANZ;n++)
{
WS2812_LED_BUF_CH2[n]=WS2812_RGB_COL_OFF;
}
ws2812_channel=;
#endif
#if WS2812_LED_CH1_ANZ>0
for(n=;n<WS2812_LED_CH1_ANZ;n++)
{
WS2812_LED_BUF_CH1[n]=WS2812_RGB_COL_OFF;
}
ws2812_channel=;
#endif if ( ws2812_channel == )
return; // aktive WS2812-Kette auswaehlen
UB_WS2812_SetChannel( ws2812_channel ); // init vom GPIO
p_WS2812_InitIO( );
// init vom Timer
p_WS2812_InitTIM( );
// init vom NVIC
p_WS2812_InitNVIC( );
// init vom DMA
p_WS2812_InitDMA( ); // alle WS2812-Ketten loeschen
p_WS2812_clearAll( );
} //--------------------------------------------------------------
// auswahl welche WS2812-Kette aktiv sein soll
// (LED Anzahl der Kette muss >0 sein)
// ch = [1...4]
//--------------------------------------------------------------
void UB_WS2812_SetChannel( uint8_t ch )
{
#if WS2812_LED_CH1_ANZ>0
if(ch==)
{
ws2812_channel=;
ws2812_ptr=&WS2812_LED_BUF_CH1[];
ws2812_maxanz=WS2812_LED_CH1_ANZ;
}
#endif
#if WS2812_LED_CH2_ANZ>0
if(ch==)
{
ws2812_channel=;
ws2812_ptr=&WS2812_LED_BUF_CH2[];
ws2812_maxanz=WS2812_LED_CH2_ANZ;
}
#endif
#if WS2812_LED_CH3_ANZ>0
if(ch==)
{
ws2812_channel=;
ws2812_ptr=&WS2812_LED_BUF_CH3[];
ws2812_maxanz=WS2812_LED_CH3_ANZ;
}
#endif
#if WS2812_LED_CH4_ANZ>0
if(ch==)
{
ws2812_channel=;
ws2812_ptr=&WS2812_LED_BUF_CH4[];
ws2812_maxanz=WS2812_LED_CH4_ANZ;
}
#endif
} //--------------------------------------------------------------
// Refresh der aktiven WS2812-Kette
// (update aller LEDs)
// Die RGB-Farbwerte der LEDs muss im Array "WS2812_LED_BUF[n]" stehen
// n = [0...WS2812_LED_ANZ-1]
//--------------------------------------------------------------
void UB_WS2812_Refresh( void )
{
if ( ws2812_channel == )
return; // warte bis DMA-Transfer fertig
while ( ws2812_dma_status != )
; // Timer Werte berrechnen
p_WS2812_calcTimerBuf( ); // DMA starten
p_WS2812_DMA_Start( );
} //--------------------------------------------------------------
// wandelt einen HSV-Farbwert in einen RGB-Farbwert um
// (Funktion von UlrichRadig.de)
//--------------------------------------------------------------
void UB_WS2812_RGB_2_HSV( WS2812_HSV_t hsv_col, WS2812_RGB_t *rgb_col )
{
uint8_t diff; // Grenzwerte
if ( hsv_col.h > )
hsv_col.h = ;
if ( hsv_col.s > )
hsv_col.s = ;
if ( hsv_col.v > )
hsv_col.v = ; if ( hsv_col.h < )
{
rgb_col->red = ;
rgb_col->green = ( * hsv_col.h ) / ;
rgb_col->blue = ;
}
else if ( hsv_col.h < )
{
rgb_col->red = - ( ( * ( hsv_col.h - ) ) / );
rgb_col->green = ;
rgb_col->blue = ;
}
else if ( hsv_col.h < )
{
rgb_col->red = ;
rgb_col->green = ;
rgb_col->blue = ( * ( hsv_col.h - ) ) / ;
}
else if ( hsv_col.h < )
{
rgb_col->red = ;
rgb_col->green = - ( ( * ( hsv_col.h - ) ) / );
rgb_col->blue = ;
}
else if ( hsv_col.h < )
{
rgb_col->red = ( * ( hsv_col.h - ) ) / ;
rgb_col->green = ;
rgb_col->blue = ;
}
else
{
rgb_col->red = ;
rgb_col->green = ;
rgb_col->blue = - ( ( * ( hsv_col.h - ) ) / );
} hsv_col.s = - hsv_col.s;
diff = ( ( - rgb_col->red ) * hsv_col.s ) / ;
rgb_col->red = rgb_col->red + diff;
diff = ( ( - rgb_col->green ) * hsv_col.s ) / ;
rgb_col->green = rgb_col->green + diff;
diff = ( ( - rgb_col->blue ) * hsv_col.s ) / ;
rgb_col->blue = rgb_col->blue + diff; rgb_col->red = ( rgb_col->red * hsv_col.v ) / ;
rgb_col->green = ( rgb_col->green * hsv_col.v ) / ;
rgb_col->blue = ( rgb_col->blue * hsv_col.v ) / ;
} //--------------------------------------------------------------
// eine LED der aktiven WS2812-Kette auf eine Farbe setzen (RGB)
// nr : [0...WS2812_LED_ANZ-1]
// rgb_col : Farbwert (in RGB)
// refresh : 0=ohne refresh, 1=mit refresh
//--------------------------------------------------------------
void UB_WS2812_One_Led_RGB( uint32_t nr, WS2812_RGB_t rgb_col, uint8_t refresh )
{
if ( ws2812_channel == )
return; if ( nr < ws2812_maxanz )
{
ws2812_ptr[ nr ] = rgb_col; if ( refresh == )
UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette auf eine Farbe setzen (RGB)
// rgb_col : Farbwert (in RGB)
// refresh : 0=ohne refresh, 1=mit refresh
//--------------------------------------------------------------
void UB_WS2812_All_Led_RGB( WS2812_RGB_t rgb_col, uint8_t refresh )
{
uint32_t n; if ( ws2812_channel == )
return; for ( n = ; n < ws2812_maxanz; n++ )
{
ws2812_ptr[ n ] = rgb_col;
}
if ( refresh == )
UB_WS2812_Refresh( );
} //--------------------------------------------------------------
// eine LED der aktiven WS2812-Kette auf eine Farbe setzen (HSV)
// nr : [0...WS2812_LED_ANZ-1]
// hsv_col : Farbwert (in HSV)
// refresh : 0=ohne refresh, 1=mit refresh
//--------------------------------------------------------------
void UB_WS2812_One_Led_HSV( uint32_t nr, WS2812_HSV_t hsv_col, uint8_t refresh )
{
WS2812_RGB_t rgb_col; if ( ws2812_channel == )
return; if ( nr < ws2812_maxanz )
{
// farbe in RGB umwandeln
UB_WS2812_RGB_2_HSV( hsv_col, &rgb_col );
ws2812_ptr[ nr ] = rgb_col; if ( refresh == )
UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette auf eine Farbe setzen (HSV)
// hsv_col : Farbwert (in HSV)
// refresh : 0=ohne refresh, 1=mit refresh
//--------------------------------------------------------------
void UB_WS2812_All_Led_HSV( WS2812_HSV_t hsv_col, uint8_t refresh )
{
uint32_t n;
WS2812_RGB_t rgb_col; if ( ws2812_channel == )
return; // farbe in RGB umwandeln
UB_WS2812_RGB_2_HSV( hsv_col, &rgb_col );
for ( n = ; n < ws2812_maxanz; n++ )
{
ws2812_ptr[ n ] = rgb_col;
}
if ( refresh == )
UB_WS2812_Refresh( );
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette eine position nach links schieben
// letzte LED wird ausgeschaltet
//--------------------------------------------------------------
void UB_WS2812_Shift_Left( void )
{
uint32_t n; if ( ws2812_channel == )
return; if ( ws2812_maxanz > )
{
for ( n = ; n < ws2812_maxanz; n++ )
{
ws2812_ptr[ n - ] = ws2812_ptr[ n ];
}
ws2812_ptr[ n - ] = WS2812_RGB_COL_OFF; UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette eine position nach rechts schieben
// erste LED wird ausgeschaltet
//--------------------------------------------------------------
void UB_WS2812_Shift_Right( void )
{
uint32_t n; if ( ws2812_channel == )
return; if ( ws2812_maxanz > )
{
for ( n = ws2812_maxanz - ; n > ; n-- )
{
ws2812_ptr[ n ] = ws2812_ptr[ n - ];
}
ws2812_ptr[ n ] = WS2812_RGB_COL_OFF; UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette eine position nach links rotieren
// letzte LED bekommt den Farbwert der ersten LED
//--------------------------------------------------------------
void UB_WS2812_Rotate_Left( void )
{
uint32_t n;
WS2812_RGB_t d; if ( ws2812_channel == )
return; if ( ws2812_maxanz > )
{
d = ws2812_ptr[ ];
for ( n = ; n < ws2812_maxanz; n++ )
{
ws2812_ptr[ n - ] = ws2812_ptr[ n ];
}
ws2812_ptr[ n - ] = d; UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// alle LEDs der aktiven WS2812-Kette eine position nach rechts rotieren
// erste LED bekommt den Farbwert der letzten LED
//--------------------------------------------------------------
void UB_WS2812_Rotate_Right( void )
{
uint32_t n;
WS2812_RGB_t d; if ( ws2812_channel == )
return; if ( ws2812_maxanz > )
{
d = ws2812_ptr[ ws2812_maxanz - ];
for ( n = ws2812_maxanz - ; n > ; n-- )
{
ws2812_ptr[ n ] = ws2812_ptr[ n - ];
}
ws2812_ptr[ n ] = d; UB_WS2812_Refresh( );
}
} //--------------------------------------------------------------
// interne Funktion
// loescht alle WS2812-Ketten
//--------------------------------------------------------------
void p_WS2812_clearAll( void )
{
//-------------------------
// einmal DMA starten
// (ohne Signal, Dauer LoPegel)
//-------------------------
if ( WS2812_LED_CH4_ANZ > )
{
// auf Kanal 4 schalten
UB_WS2812_SetChannel( );
// warte bis DMA-Transfer fertig
while ( ws2812_dma_status != )
;
// DMA starten
p_WS2812_DMA_Start( );
}
if ( WS2812_LED_CH3_ANZ > )
{
// auf Kanal 3 schalten
UB_WS2812_SetChannel( );
// warte bis DMA-Transfer fertig
while ( ws2812_dma_status != )
;
// DMA starten
p_WS2812_DMA_Start( );
}
if ( WS2812_LED_CH2_ANZ > )
{
// auf Kanal 2 schalten
UB_WS2812_SetChannel( );
// warte bis DMA-Transfer fertig
while ( ws2812_dma_status != )
;
// DMA starten
p_WS2812_DMA_Start( );
}
if ( WS2812_LED_CH1_ANZ > )
{
// auf Kanal 1 schalten
UB_WS2812_SetChannel( );
// warte bis DMA-Transfer fertig
while ( ws2812_dma_status != )
;
// DMA starten
p_WS2812_DMA_Start( );
} //-------------------------
// alle LEDs ausschalten
//-------------------------
if ( WS2812_LED_CH4_ANZ > )
{
// auf Kanal 4 schalten
UB_WS2812_SetChannel( );
UB_WS2812_All_Led_RGB( WS2812_RGB_COL_OFF, );
}
if ( WS2812_LED_CH3_ANZ > )
{
// auf Kanal 3 schalten
UB_WS2812_SetChannel( );
UB_WS2812_All_Led_RGB( WS2812_RGB_COL_OFF, );
}
if ( WS2812_LED_CH2_ANZ > )
{
// auf Kanal 2 schalten
UB_WS2812_SetChannel( );
UB_WS2812_All_Led_RGB( WS2812_RGB_COL_OFF, );
}
if ( WS2812_LED_CH1_ANZ > )
{
// auf Kanal 1 schalten
UB_WS2812_SetChannel( );
UB_WS2812_All_Led_RGB( WS2812_RGB_COL_OFF, );
}
} //--------------------------------------------------------------
// interne Funktion
// errechnet aus den RGB-Farbwerten der aktiven LEDs
// die notwendigen PWM-Werte fuer die Datenleitung
//--------------------------------------------------------------
void p_WS2812_calcTimerBuf( void )
{
uint32_t n;
uint32_t pos;
WS2812_RGB_t led; if ( ws2812_channel == )
return; pos = ;
// timingzeiten fuer alle LEDs setzen
for ( n = ; n < ws2812_maxanz; n++ )
{
led = ws2812_ptr[ n ]; // Col:Green , Bit:7..0
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x80 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x40 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x20 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x10 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x08 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x04 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x02 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.green & 0x01 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++; // Col:Red , Bit:7..0
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x80 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x40 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x20 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x10 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x08 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x04 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x02 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.red & 0x01 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++; // Col:Blue , Bit:7..0
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x80 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x40 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x20 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x10 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x08 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x04 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x02 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
WS2812_TIMER_BUF[ pos ] = WS2812_LO_TIME;
if ( ( led.blue & 0x01 ) != )
WS2812_TIMER_BUF[ pos ] = WS2812_HI_TIME;
pos++;
} // nach den Farbinformationen eine Pausenzeit anh鋘gen (2*30ms)
for ( n = ; n < WS2812_PAUSE_ANZ * WS2812_BIT_PER_LED; n++ )
{
WS2812_TIMER_BUF[ pos ] = ; // 0 => fuer Pausenzeit
pos++;
}
} //--------------------------------------------------------------
// interne Funktion
// DMA und Timer starten
// (gestoppt wird per Transfer-Complete-Interrupt)
//--------------------------------------------------------------
void p_WS2812_DMA_Start( void )
{
if ( ws2812_channel == )
return; // status auf "busy" setzen
ws2812_dma_status = ;
// init vom DMA
p_WS2812_InitDMA( );
if ( ws2812_channel == )
{
// enable vom Transfer-Complete Interrupt
DMA_ITConfig( WS2812_DMA_CH1_STREAM, DMA_IT_TC, ENABLE );
// DMA enable
DMA_Cmd( WS2812_DMA_CH1_STREAM, ENABLE );
}
else if ( ws2812_channel == )
{
// enable vom Transfer-Complete Interrupt
DMA_ITConfig( WS2812_DMA_CH2_STREAM, DMA_IT_TC, ENABLE );
// DMA enable
DMA_Cmd( WS2812_DMA_CH2_STREAM, ENABLE );
}
else if ( ws2812_channel == )
{
// enable vom Transfer-Complete Interrupt
DMA_ITConfig( WS2812_DMA_CH3_STREAM, DMA_IT_TC, ENABLE );
// DMA enable
DMA_Cmd( WS2812_DMA_CH3_STREAM, ENABLE );
}
else if ( ws2812_channel == )
{
// enable vom Transfer-Complete Interrupt
DMA_ITConfig( WS2812_DMA_CH4_STREAM, DMA_IT_TC, ENABLE );
// DMA enable
DMA_Cmd( WS2812_DMA_CH4_STREAM, ENABLE );
}
// Timer enable
TIM_Cmd( WS2812_TIM, ENABLE );
} //--------------------------------------------------------------
// interne Funktion
// init vom GPIO Pin
//--------------------------------------------------------------
void p_WS2812_InitIO( void )
{
GPIO_InitTypeDef GPIO_InitStructure; #if WS2812_LED_CH1_ANZ>0
// Clock Enable
RCC_AHB1PeriphClockCmd(WS2812_CH1_CLOCK, ENABLE); // Config des Pins als Digital-Ausgang
GPIO_InitStructure.GPIO_Pin = WS2812_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(WS2812_CH1_PORT, &GPIO_InitStructure); // Lo-Pegel ausgeben
WS2812_CH1_PORT->BSRRH = WS2812_CH1_PIN; // Alternative-Funktion mit dem IO-Pin verbinden
GPIO_PinAFConfig(WS2812_CH1_PORT, WS2812_CH1_SOURCE, WS2812_TIM_AF);
#endif #if WS2812_LED_CH2_ANZ>0
// Clock Enable
RCC_AHB1PeriphClockCmd(WS2812_CH2_CLOCK, ENABLE); // Config des Pins als Digital-Ausgang
GPIO_InitStructure.GPIO_Pin = WS2812_CH2_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(WS2812_CH2_PORT, &GPIO_InitStructure); // Lo-Pegel ausgeben
WS2812_CH2_PORT->BSRRH = WS2812_CH2_PIN; // Alternative-Funktion mit dem IO-Pin verbinden
GPIO_PinAFConfig(WS2812_CH2_PORT, WS2812_CH2_SOURCE, WS2812_TIM_AF);
#endif #if WS2812_LED_CH3_ANZ>0
// Clock Enable
RCC_AHB1PeriphClockCmd(WS2812_CH3_CLOCK, ENABLE); // Config des Pins als Digital-Ausgang
GPIO_InitStructure.GPIO_Pin = WS2812_CH3_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(WS2812_CH3_PORT, &GPIO_InitStructure); // Lo-Pegel ausgeben
WS2812_CH3_PORT->BSRRH = WS2812_CH3_PIN; // Alternative-Funktion mit dem IO-Pin verbinden
GPIO_PinAFConfig(WS2812_CH3_PORT, WS2812_CH3_SOURCE, WS2812_TIM_AF);
#endif #if WS2812_LED_CH4_ANZ>0
// Clock Enable
RCC_AHB1PeriphClockCmd(WS2812_CH4_CLOCK, ENABLE); // Config des Pins als Digital-Ausgang
GPIO_InitStructure.GPIO_Pin = WS2812_CH4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(WS2812_CH4_PORT, &GPIO_InitStructure); // Lo-Pegel ausgeben
WS2812_CH4_PORT->BSRRH = WS2812_CH4_PIN; // Alternative-Funktion mit dem IO-Pin verbinden
GPIO_PinAFConfig(WS2812_CH4_PORT, WS2812_CH4_SOURCE, WS2812_TIM_AF);
#endif
} //--------------------------------------------------------------
// interne Funktion
// init vom Timer
//--------------------------------------------------------------
void p_WS2812_InitTIM( void )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; // Clock enable (TIM)
RCC_APB1PeriphClockCmd( WS2812_TIM_CLOCK, ENABLE ); // Clock Enable (DMA)
RCC_AHB1PeriphClockCmd( WS2812_DMA_CLOCK, ENABLE ); // Timer init
TIM_TimeBaseStructure.TIM_Period = WS2812_TIM_PERIODE;
TIM_TimeBaseStructure.TIM_Prescaler = WS2812_TIM_PRESCALE;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit( WS2812_TIM, &TIM_TimeBaseStructure ); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; #if WS2812_LED_CH1_ANZ>0
TIM_OC1Init(WS2812_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(WS2812_TIM, TIM_OCPreload_Enable);
#endif
#if WS2812_LED_CH2_ANZ>0
TIM_OC2Init(WS2812_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(WS2812_TIM, TIM_OCPreload_Enable);
#endif
#if WS2812_LED_CH3_ANZ>0
TIM_OC3Init(WS2812_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(WS2812_TIM, TIM_OCPreload_Enable);
#endif
#if WS2812_LED_CH4_ANZ>0
TIM_OC4Init(WS2812_TIM, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(WS2812_TIM, TIM_OCPreload_Enable);
#endif // Timer enable
TIM_ARRPreloadConfig( WS2812_TIM, ENABLE );
} //--------------------------------------------------------------
// interne Funktion
// init vom DMA
//--------------------------------------------------------------
void p_WS2812_InitDMA( void )
{
DMA_InitTypeDef DMA_InitStructure; if ( ws2812_channel == )
return; // DMA init
if ( ws2812_channel == )
{
DMA_Cmd( WS2812_DMA_CH1_STREAM, DISABLE );
DMA_DeInit( WS2812_DMA_CH1_STREAM );
DMA_InitStructure.DMA_Channel = WS2812_DMA_CH1_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &WS2812_TIM_CCR_REG1;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) WS2812_TIMER_BUF;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2812_TIMER_BUF_LEN1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init( WS2812_DMA_CH1_STREAM, &DMA_InitStructure );
}
else if ( ws2812_channel == )
{
DMA_Cmd( WS2812_DMA_CH2_STREAM, DISABLE );
DMA_DeInit( WS2812_DMA_CH2_STREAM );
DMA_InitStructure.DMA_Channel = WS2812_DMA_CH2_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &WS2812_TIM_CCR_REG2;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) WS2812_TIMER_BUF;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2812_TIMER_BUF_LEN2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init( WS2812_DMA_CH2_STREAM, &DMA_InitStructure );
}
else if ( ws2812_channel == )
{
DMA_Cmd( WS2812_DMA_CH3_STREAM, DISABLE );
DMA_DeInit( WS2812_DMA_CH3_STREAM );
DMA_InitStructure.DMA_Channel = WS2812_DMA_CH3_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &WS2812_TIM_CCR_REG3;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) WS2812_TIMER_BUF;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2812_TIMER_BUF_LEN3;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init( WS2812_DMA_CH3_STREAM, &DMA_InitStructure );
}
else if ( ws2812_channel == )
{
DMA_Cmd( WS2812_DMA_CH4_STREAM, DISABLE );
DMA_DeInit( WS2812_DMA_CH4_STREAM );
DMA_InitStructure.DMA_Channel = WS2812_DMA_CH4_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &WS2812_TIM_CCR_REG4;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) WS2812_TIMER_BUF;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2812_TIMER_BUF_LEN4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16bit
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init( WS2812_DMA_CH4_STREAM, &DMA_InitStructure );
}
} //--------------------------------------------------------------
// interne Funktion
// init vom NVIC
//--------------------------------------------------------------
void p_WS2812_InitNVIC( void )
{
NVIC_InitTypeDef NVIC_InitStructure; #if WS2812_LED_CH1_ANZ>0
TIM_DMACmd(WS2812_TIM, WS2812_TIM_DMA_TRG1, ENABLE);
#endif
#if WS2812_LED_CH2_ANZ>0
TIM_DMACmd(WS2812_TIM, WS2812_TIM_DMA_TRG2, ENABLE);
#endif
#if WS2812_LED_CH3_ANZ>0
TIM_DMACmd(WS2812_TIM, WS2812_TIM_DMA_TRG3, ENABLE);
#endif
#if WS2812_LED_CH4_ANZ>0
TIM_DMACmd(WS2812_TIM, WS2812_TIM_DMA_TRG4, ENABLE);
#endif #if WS2812_LED_CH1_ANZ>0
NVIC_InitStructure.NVIC_IRQChannel = WS2812_DMA_CH1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if WS2812_LED_CH2_ANZ>0
NVIC_InitStructure.NVIC_IRQChannel = WS2812_DMA_CH2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if WS2812_LED_CH3_ANZ>0
NVIC_InitStructure.NVIC_IRQChannel = WS2812_DMA_CH3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
#if WS2812_LED_CH4_ANZ>0
NVIC_InitStructure.NVIC_IRQChannel = WS2812_DMA_CH4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
} //--------------------------------------------------------------
// interne Funktion
// ISR vom DMA (CH1)
// (wird aufgerufen, wenn alle Daten uebertragen wurden)
//--------------------------------------------------------------
void WS2812_DMA_CH1_ISR( void )
{
// Test auf Transfer-Complete Interrupt Flag
if ( DMA_GetITStatus( WS2812_DMA_CH1_STREAM, WS2812_DMA_CH1_IRQ_FLAG ) )
{
// Flag zuruecksetzen
DMA_ClearITPendingBit( WS2812_DMA_CH1_STREAM, WS2812_DMA_CH1_IRQ_FLAG ); // Timer disable
TIM_Cmd( WS2812_TIM, DISABLE );
// DMA disable
DMA_Cmd( WS2812_DMA_CH1_STREAM, DISABLE ); // status auf "ready" setzen
ws2812_dma_status = ;
}
} //--------------------------------------------------------------
// interne Funktion
// ISR vom DMA (CH2)
// (wird aufgerufen, wenn alle Daten uebertragen wurden)
//--------------------------------------------------------------
void WS2812_DMA_CH2_ISR( void )
{
// Test auf Transfer-Complete Interrupt Flag
if ( DMA_GetITStatus( WS2812_DMA_CH2_STREAM, WS2812_DMA_CH2_IRQ_FLAG ) )
{
// Flag zuruecksetzen
DMA_ClearITPendingBit( WS2812_DMA_CH2_STREAM, WS2812_DMA_CH2_IRQ_FLAG ); // Timer disable
TIM_Cmd( WS2812_TIM, DISABLE );
// DMA disable
DMA_Cmd( WS2812_DMA_CH2_STREAM, DISABLE ); // status auf "ready" setzen
ws2812_dma_status = ;
}
} //--------------------------------------------------------------
// interne Funktion
// ISR vom DMA (CH3)
// (wird aufgerufen, wenn alle Daten uebertragen wurden)
//--------------------------------------------------------------
void WS2812_DMA_CH3_ISR( void )
{
// Test auf Transfer-Complete Interrupt Flag
if ( DMA_GetITStatus( WS2812_DMA_CH3_STREAM, WS2812_DMA_CH3_IRQ_FLAG ) )
{
// Flag zuruecksetzen
DMA_ClearITPendingBit( WS2812_DMA_CH3_STREAM, WS2812_DMA_CH3_IRQ_FLAG ); // Timer disable
TIM_Cmd( WS2812_TIM, DISABLE );
// DMA disable
DMA_Cmd( WS2812_DMA_CH3_STREAM, DISABLE ); // status auf "ready" setzen
ws2812_dma_status = ;
}
} //--------------------------------------------------------------
// interne Funktion
// ISR vom DMA (CH4)
// (wird aufgerufen, wenn alle Daten uebertragen wurden)
//--------------------------------------------------------------
void WS2812_DMA_CH4_ISR( void )
{
// Test auf Transfer-Complete Interrupt Flag
if ( DMA_GetITStatus( WS2812_DMA_CH4_STREAM, WS2812_DMA_CH4_IRQ_FLAG ) )
{
// Flag zuruecksetzen
DMA_ClearITPendingBit( WS2812_DMA_CH4_STREAM, WS2812_DMA_CH4_IRQ_FLAG ); // Timer disable
TIM_Cmd( WS2812_TIM, DISABLE );
// DMA disable
DMA_Cmd( WS2812_DMA_CH4_STREAM, DISABLE ); // status auf "ready" setzen
ws2812_dma_status = ;
}
}
78-WS2812-Library (STM32F4)的更多相关文章
- AWR Report 关键参数详细分析
WORKLOAD REPOSITORY report for DB Name DB Id Instance Inst num Startup Time Release RAC CALLDB 12510 ...
- 玩转X-CTR100 l STM32F4 l WS2812全彩LED灯
更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] WS2812B RGB全彩LED灯珠,只需通过一根信号线控制多个 ...
- 0xWS2812 STM32 driver for WS2812(B) RGB LEDs
0xWS2812 STM32 driver for WS2812(B) RGB LEDs 0xWS2812 pronounced "hex-WS2812" This code ai ...
- Linux Dynamic Shared Library && LD Linker
目录 . 动态链接的意义 . 地址无关代码: PIC . 延迟版定(PLT Procedure Linkage Table) . 动态链接相关结构 . 动态链接的步骤和实现 . Linux动态链接器实 ...
- c++ socket 客户端库 socks5 客户端 RudeSocket™ Open Source C++ Socket Library
介绍 一个c++ socket 客户端库 http://www.rudeserver.com/socket/index.html The RudeSocket™ Open Source C++ Soc ...
- Enterprise Library深入解析与灵活应用(2): 通过SqlDependency实现Cache和Database的同步
对于一个真正的企业级的应用来说,Caching肯定是一个不得不考虑的因素,合理.有效地利用Caching对于增强应用的Performance(减少对基于Persistent storage的IO操作) ...
- Android 创建Library Project(库项目)与引用操作
由于在开发过程,为了实现未曾了解的某种效果与特定功能,而求助于网上优秀的开源项目,在使用过程中发现引用开源的Library Project(库项目),的确可以解决很多问题,而且也给出了一种思路,好的软 ...
- tomcat之 Tomcat 7.0.78 单机多实例配置
前言:JDK(JavaDevelopment Kit)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最广泛的javaSDK. JDK是整个Java ...
- DB Query Analyzer 6.04 is distributed, 78 articles concerned have been published
DB Query Analyzer 6.04 is distributed,78 articles concerned have been published DB Query Analyz ...
- ambari2.6.50 openssl 版本问题:SSLError: Failed to connect. Please check openssl library versions. Openssl error upon host registration
I'm trying to register hostnames in Ambari but getting the error below. We tried to run yum update o ...
随机推荐
- State Estimation for Robotics (Tim Barfoot) exercises Answers
Here are some exercises answers for State Estimation for Robotics, which I did in June, 2017. The bo ...
- C型USB能阻止危险充电器通过USB传播恶意软件
C型USB能阻止危险充电器通过USB传播恶意软件 C型USB设备(USB Type-C)的新型身份验证协议可以保护用户免受潜在的充电器损坏的风险,这种新型的USB还能减少被恶意软件的风险.基于密码的认 ...
- 通俗理解决策树中的熵&条件熵&信息增益
参考通俗理解决策树算法中的信息增益 说到决策树就要知道如下概念: 熵:表示一个随机变量的复杂性或者不确定性. 假如双十一我要剁手买一件衣服,但是我一直犹豫着要不要买,我决定买这件事的不确定性(熵)为2 ...
- Linux本地解析文件/etc/hosts说明【原创】
windows的域名本地解析文件hosts是可以一个域名对多个IP,如果有一个IP有问题,可以去解析到其他IP Linux的本地解析文件/etc/hosts,是否也可以这样呢.下面做了个测试 先看一下 ...
- js如何判断一个对象是不是Array?
在开发中,我们经常需要判断某个对象是否为数组类型,在Js中检测对象类型的常见方法都有哪些呢? typeof 操作符 对于Function, String, Number ,Undefined 等几种类 ...
- 在VMware上安装Ubuntu软件步骤与遇到的相关问题及解决方案
图解演示环境版本: 本机系统: WIN10 虚拟机:VMware Workstation 12(中文版) 安装目标:Ubuntu Desktop 12.04 LTS (请点击这里)先下载好iso镜像 ...
- Android BLE设备蓝牙通信框架BluetoothKit
BluetoothKit是一款功能强大的Android蓝牙通信框架,支持低功耗蓝牙设备的连接通信.蓝牙广播扫描及Beacon解析. 关于该项目的详细文档请关注:https://github.com/d ...
- python之Anaconda版本管理
首先安装Anaconda,当其安装成功后,可以在cmd中测试是否安装成功,conda --version conda的环境管理 Conda的环境管理功能允许我们同时安装若干不同版本的Python,并能 ...
- centos redis 自动重启
配置init脚本 对于Centos,有一份https://gist.github.com/1335694 经过修改,如下: ########################## PATH=/usr/l ...
- CSS------制作一个带+-的input框
如图: 代码:(div和input之间要连续写在一起,不能换行) <div style="font-size:36px;margin-top:30px"> <di ...