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 ...
随机推荐
- (F. MST Unification)最小生成树
题目链接:http://codeforces.com/contest/1108/problem/F 题目大意:给你n个点和m条边,然后让你进行一些操作使得这个图的最小生成树唯一,每次的操作是给某一条边 ...
- mybatis关联查询数据模型分析——(七)
1. 数据模型分析思路 1.每张表记录的数据内容 分模块对每张表记录的内容进行熟悉,相当 于你学习系统 需求(功能)的过程. 2.每张表重要的字段设置 非空字段.外键字段 3.数据库级别表与表 ...
- 利用VBS下载EXE文件手法记录
1.信息来源 疑似朝鲜通过鱼叉攻击韩国统一部记者的APT事件整理 https://mp.weixin.qq.com/s/4IFV31MBNbANnCVaJj7ZPQ https://twitter.c ...
- css实现导航切换
css实现导航切换 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <title>css实现导航切换&l ...
- wpf 如果列表加载超多数据变的卡顿时,使用VirtualizingStackPanel
如果列表加载超多数据变的卡顿时 <ListBox > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Virt ...
- MySQL锁分类
相对其他数据库而言,MySQL的锁机制比较简单,基最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB ...
- LOJ 10155 - 「一本通 5.2 例 3」数字转换
前言 从现在开始,这个博客要写一些题解了.起初,开这个博客只是好玩一样,没事就写写CSS.JS,然后把博客前端搞成了现在这个样子.以前博客只是偶尔记录一些东西,刷题也从来不记录,最近受一些学长的影响, ...
- Asp.Net Core WebAPI入门整理(一)
一.Asp.Net Core WebAPI 1.目前版本是v1.1 2.默认路由处理和Asp.Net WebAPI有些 区别了,现在使用的是控制器路由[Route("api/Menu&qu ...
- 安装配置tomcat,java运行环境
1.下载JDK,安装 官网下载地址:http://java.sun.com/javase/downloads/index.jsp 下载后,安装,选择你想把JDK安装的目录: 比如:JDK安装目录:E: ...
- weblogic在64位windows的设置
最近遇到一些问题,需要调整weblogic的内存用于做压力测试,weblogic默认的内存是远远不能满足当前测试需求.由于服务器是64位8G的内存,但是在服务器上安装的jdk和weblogic都是32 ...