Untitled

mail@pastecode.io avatar
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);
			}

		}

	}