Untitled
unknown
plain_text
2 years ago
3.0 kB
9
Indexable
extern void SysClockConfig(void); #include "stm32f4xx.h" #include "delay.h" #include "math.h" #include "stdint.h" #define CH3 ((1<<26)|(1<<25)) #define M_SI32 (1<<13) #define P_SI32 (1<<11) #define M_INC (1<<10) #define Cir (1<<8) #define M2P (1<<6) #define PFCTRL (1<<5) #define AF01 (0x01) volatile uint8_t finished; #define MAX_LED 24 uint8_t LED_Data[MAX_LED][4]; uint8_t LED_Mod[MAX_LED][4]; // for brightness uint16_t pwmData[(24*MAX_LED)+50]; uint16_t indx=0; uint32_t color; void WS2812_init(){ RCC->AHB1ENR|=RCC_AHB1ENR_GPIOAEN; GPIOA->MODER|=GPIO_MODER_MODE0_1; GPIOA->MODER&=~GPIO_MODER_MODE0_0; GPIOA->AFR[0]|=(AF01<<0); //init timer; RCC->APB1ENR|=RCC_APB1ENR_TIM2EN; //enable clock access to tim2 TIM2->PSC=0; //set prescaller to 0 (no divider) TIM2->ARR=90-1; //set the maximum count value TIM2->CNT=0; //reset the current count TIM2->DIER|=TIM_DIER_CC1DE; TIM2->DMAR|=0x01; TIM2->CCMR1|=TIM_CCMR1_OC1M_2|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1PE; //configure the pin as PWM TIM2->CCER|=TIM_CCER_CC1E; //enable channel1 and //init dma RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN; DMA1_Stream5->CR&=~DMA_SxCR_EN; while((DMA1_Stream5->CR)&DMA_SxCR_EN){;} DMA1_Stream5->CR=CH3|M_SI32|P_SI32|M_INC|M2P|DMA_SxCR_TCIE; NVIC_EnableIRQ(DMA1_Stream5_IRQn); } void WS2812_display(uint8_t LEDnum, uint8_t Red, uint8_t Green, uint8_t Blue, uint8_t brightness) { LED_Data[LEDnum][0] = LEDnum; LED_Data[LEDnum][1] = Green; LED_Data[LEDnum][2] = Red; LED_Data[LEDnum][3] = Blue; #define PI 3.14159265 if (brightness > 45) brightness = 45; for (int i=0; i<MAX_LED; i++) { LED_Mod[i][0] = LED_Data[i][0]; for (int j=1; j<4; j++) { float angle = 90-brightness; // in degrees angle = angle*PI / 180; // in rad LED_Mod[i][j] = (LED_Data[i][j])/(tan(angle)); } } for (int i= 0; i<MAX_LED; i++) { color = ((LED_Mod[i][1]<<16) | (LED_Mod[i][2]<<8) | (LED_Mod[i][3])); for (int i=23; i>=0; i--) { if (color&(1<<i)) { pwmData[indx] = 60; // 2/3 of 90 } else {pwmData[indx] = 30;} // 1/3 of 90 indx++; } } for (int i=0; i<50; i++) { pwmData[indx] = 0; indx++; } DMA1_Stream5->PAR=(uint32_t)(&TIM2->CCR1); DMA1_Stream5->M0AR=(uint32_t)(&pwmData); DMA1_Stream5->NDTR=(uint16_t)indx; DMA1->HIFCR|=DMA_HIFCR_CTCIF5; DMA1_Stream5->CR|=DMA_SxCR_EN; TIM2->CR1|=TIM_CR1_CEN; //enable timer while(finished==0); finished=0; } void DMA1_Stream5_IRQHandler(void) { if(DMA_HISR_TCIF5&DMA1->HISR) { finished=1; TIM2->CR1&=~TIM_CR1_CEN; DMA1->HIFCR|=DMA_HIFCR_CTCIF5; } } int main(void) { SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); SysClockConfig();//set clock speed to 72MHz systick_init_ms(72000000); //initialize systick to generate 1ms interrupt for delay WS2812_init(); for (int i=0;i<MAX_LED;i++){ WS2812_display(i,0,0,0,0);} WS2812_display(1,255,255,255,22); while(1) { for(int i=0;i<45;i++) { WS2812_display(1,255,255,255,i); delay(50); } } }