Untitled
unknown
plain_text
3 years ago
3.0 kB
14
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);
}
}
}
Editor is loading...