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 ...
随机推荐
- 20155235 2016-2017-2 《Java程序设计》第8周学习总结
20155235 2016-2017-2 <Java程序设计>第8周学习总结 教材学习内容总结 第十四章 NIO与NIO2 认识NIO NIO概述 Channel架构与操作 Buffer架 ...
- 【三分钟视频教程】iOS开发中 Xcode 报 apple-o linker 错误的#解决方案#
[三分钟视频教程]iOS开发中 Xcode 报 apple-o linker 错误的#解决方案# 同样的道理,指向同一库文件的代码语句如果重复书写,即使重复书写所在的文件名字不同,同样会造成这 ...
- ant+sonar+jacoco代码质量代码覆盖率扫描
使用ant构建的java web项目如何做sonar代码质量扫描?以下就是实际遇到并成功使用的案例一.做sonar扫描的准备工作 1.给web项目增加build.xml构建脚本. 2.下载 ...
- 洛谷 P1563 玩具谜题
如果你想不耗费脑力做出这个题目,往下看: 本萌新看到这个题目,想到了乘法法则,题目中左右方向要判断两次,很耗脑力,和乘法中的正负号判断非常像. 抽象一点:这个人向内向外就是乘法中括号外的正负号,他的左 ...
- vue中,写在methods里的B方法去调A方法的数据,访问不到?
今天在写项目的时候,发现了一个京城性忽略的问题,在vue的methods的方法里面定义了两个方法,如下: getTaskList() { api.growthDetails.taskList({ ap ...
- python 入门基础4 --数据类型及内置方法
今日目录: 零.解压赋值+for循环 一. 可变/不可变和有序/无序 二.基本数据类型及内置方法 1.整型 int 2.浮点型float 3.字符串类型 4.列表类型 三.后期补充内容 零.解压赋值+ ...
- 【译】Asp.Net Identity与Owin,到底谁是谁?
送给正在学习Asp.Net Identity的你 :-) 原文出自 trailmax 的博客AspNet Identity and Owin. Who is who. Recently I have ...
- spirngboot 注解方式注入自定义参数
在代码中 @value("oracle.user") private String user; 在配置文件中 oracle.user=root
- MySQL多线程备份工具mydumper
mydumper是一个针对MySQL和Drizzle的高性能多线程的备份和恢复工具.此工具的开发人员分别来自MySQL.Fackbook.SkySQL公司,目前已经有一些大型产品业务测试并使用了该工具 ...
- Android 隐藏、显示软键盘方法
隐藏软键盘的终极方法: public class SoftKeyboardUtil { /** * 隐藏软键盘(只适用于Activity,不适用于Fragment) */ public static ...