#ifndef WS2812B #define WS2812B #ifdef STM32F10X_MD #include #include #endif #if defined(STM32F303xE) || defined(STM32F303xD) || defined(STM32F303xC) #include #include #endif #define WS_ARR (SystemCoreClock/800000) // TimeReload for 800kHz #define WS_T0H (SystemCoreClock/800000/3) // ca. 40µs #define WS_T1H ((SystemCoreClock/800000/3)*2) // ca. 80µs #define WS_BREAK 50 // 50*1.25µs BreakTime #ifdef STM32F10X_MD #define DMA_CCR_MINC DMA_CCR1_MINC #define DMA_CCR_DIR DMA_CCR1_DIR #define DMA_CCR_EN DMA_CCR1_EN #define DMA_CCR_CIRC DMA_CCR1_CIRC #endif template class Ws2812 { uint8_t pixbuf[pixelCount*24+WS_BREAK]; int iDimmValue=255; public: Ws2812() { Clear(); } void Clear() { memset(pixbuf, 0, sizeof(pixbuf)); for (int n=0; n=pixelCount) nPixel=nPixel%pixelCount; uint8_t rgb[3]; rgb[0]=g*iDimmValue/256; rgb[1]=r*iDimmValue/256; rgb[2]=b*iDimmValue/256; int pos=nPixel*24; for (int n=0; n<3; n++) { uint8_t u=rgb[n]; for (int x=0; x<8; x++) { if ((u & (1<<(7-x)))!=0) pixbuf[pos]=WS_T1H; else pixbuf[pos]=WS_T0H; pos++; } } } void Init() { #ifdef STM32F10X_MD // Enable Port A, B and alternate functions SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN + RCC_APB2ENR_AFIOEN); // PA8 = Timer 1 channel 1 alternate function output MODIFY_REG(GPIOA->CRH, GPIO_CRH_CNF8 + GPIO_CRH_MODE8, GPIO_CRH_CNF8_1 + GPIO_CRH_MODE8_0); #endif #if defined(STM32F303xE) || defined(STM32F303xD) || defined(STM32F303xC) // Enable Port A SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOAEN); // PA8 = TIM1_CH1 alternate function 6 (see data sheet) MODIFY_REG(GPIOA->AFR[1], GPIO_AFRH_AFRH0, 6UL<MODER, GPIO_MODER_MODER8, GPIO_MODER_MODER8_1); #endif SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN); // 800khz Takt TIM1->ARR=WS_ARR; // 1.25µs TIM1->CCR1=0; // Timer 1 channel 1 compare mode = PWM1 with the required preload buffer enabled MODIFY_REG(TIM1->CCMR1, TIM_CCMR1_OC1M + TIM_CCMR1_OC1PE, TIM_CCMR1_OC1M_2 + TIM_CCMR1_OC1M_1 + TIM_CCMR1_OC1PE); // Channel 1 enable SET_BIT(TIM1->CCER,TIM_CCER_CC1E); // Output On SET_BIT(TIM1->BDTR, TIM_BDTR_MOE); // DMA SET_BIT(RCC->AHBENR,RCC_AHBENR_DMA1EN); // DMA Request bei Update SET_BIT(TIM1->DIER, TIM_DIER_UDE); // Timer On SET_BIT(TIM1->CR1, TIM_CR1_CEN + TIM_CR1_ARPE); // DMA Errorflags loeschen DMA1->IFCR=DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 | DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5; // TIM1_UP DMA Request is DMA1 Channel 5 #define DMA_CH DMA1_Channel5 DMA_CH->CCR=0; // EN muss 0 sein zum Konfigurieren DMA_CH->CMAR=(uint32_t)&pixbuf[0]; // Source DMA_CH->CPAR=(uint32_t)&TIM1->CCR1; // Destination DMA_CH->CNDTR=sizeof(pixbuf); // Count Bytes DMA_CH->CCR= (0b00<<10) // MSIZE 8bit | (0b01<<8) // PSIZE 16bit | DMA_CCR_MINC // Memory increment | DMA_CCR_DIR // Memory to Perifer | DMA_CCR_CIRC // Ciricular ; SET_BIT(DMA_CH->CCR, DMA_CCR_EN); // Enable DMA } }; #endif