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)的更多相关文章

  1. AWR Report 关键参数详细分析

    WORKLOAD REPOSITORY report for DB Name DB Id Instance Inst num Startup Time Release RAC CALLDB 12510 ...

  2. 玩转X-CTR100 l STM32F4 l WS2812全彩LED灯

    更多塔克创新资讯欢迎登陆[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      WS2812B RGB全彩LED灯珠,只需通过一根信号线控制多个 ...

  3. 0xWS2812 STM32 driver for WS2812(B) RGB LEDs

    0xWS2812 STM32 driver for WS2812(B) RGB LEDs 0xWS2812 pronounced "hex-WS2812" This code ai ...

  4. Linux Dynamic Shared Library && LD Linker

    目录 . 动态链接的意义 . 地址无关代码: PIC . 延迟版定(PLT Procedure Linkage Table) . 动态链接相关结构 . 动态链接的步骤和实现 . Linux动态链接器实 ...

  5. c++ socket 客户端库 socks5 客户端 RudeSocket™ Open Source C++ Socket Library

    介绍 一个c++ socket 客户端库 http://www.rudeserver.com/socket/index.html The RudeSocket™ Open Source C++ Soc ...

  6. Enterprise Library深入解析与灵活应用(2): 通过SqlDependency实现Cache和Database的同步

    对于一个真正的企业级的应用来说,Caching肯定是一个不得不考虑的因素,合理.有效地利用Caching对于增强应用的Performance(减少对基于Persistent storage的IO操作) ...

  7. Android 创建Library Project(库项目)与引用操作

    由于在开发过程,为了实现未曾了解的某种效果与特定功能,而求助于网上优秀的开源项目,在使用过程中发现引用开源的Library Project(库项目),的确可以解决很多问题,而且也给出了一种思路,好的软 ...

  8. tomcat之 Tomcat 7.0.78 单机多实例配置

    前言:JDK(JavaDevelopment Kit)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最广泛的javaSDK. JDK是整个Java ...

  9. 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 ...

  10. 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 ...

随机推荐

  1. python爬虫-图片批量下载

    # 爬起摄图网的图片批量下载# coding:utf-8 import requests from bs4 import BeautifulSoup from scipy.misc import im ...

  2. nested exception is com.svorx.core.dao.PersistenceException

    在quartz定时执行任务的时候,hibernate报错,在只读事务中进行了update语句: [ERROR] 2018/08/03 10:35:00,827 org.quartz.core.JobR ...

  3. 在pycharm和tensorflow环境下运行nmt

    目的是在pycharm中调试nmt代码,主要做了如下工作: 配置pycharm编译环境 在File->Settings->Project->Project Interpreter 设 ...

  4. MySql 死锁时的一种解决办法【转】

    转自:http://blog.csdn.net/mchdba/article/details/38313881 之前也遇到一次,今天又遇到了这个问题,所以这次必须解决,网上找到这篇文章帮了大忙,方便以 ...

  5. Spring bean 配置

    1.传统的创建对象的方式:JedisMall tardition=new JedisMall(); 这样是在程序运行时创建,表示当前模块已经不知不觉和new出的对象耦合了,而我们通常都是更高层次的抽象 ...

  6. js async await 终极异步解决方案

    既然有了promise 为什么还要有async await ? 当然是promise 也不是完美的异步解决方案,而 async await 的写法看起来更加简单且容易理解. 回顾 Promise Pr ...

  7. 014_mac下的端口查看

    一. 使用netstat去过滤listen效果不怎么理想. $ netstat -an|grep -i --color "listen" tcp6 0 0 ::1.5601 *.* ...

  8. 获取同一接口多个实现类的bean

    @Service("taskExecutorFactory") public class TaskExecutorFactory implements ApplicationCon ...

  9. MySQL自定义函数和存储过程的区别:

    自定义函数和存储过程的区别: 1)一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强.存储过程,功能强大,可以执行包括修改表等一系列数据库操作:用户定义函数不能用于执行一组修改全局 ...

  10. mapreduce的组件介绍

    第一部分:重要的组件 Combiner •什么是Combiner •combine函数把一个map函数产生的<key,value>对(多个key, value)合并成一个新的<key ...