#include "ws2812.h" #include "ch32v20x.h" u8 colors[12*3] = { 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 0, 255, 0, 255,255, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 0, 255, 0, 255, 0, 255,255 }; u8 pbuf[12*3*8]; // = {15, 30, 30, 15, 22, 22, 0, 0, 45, 45, 22, 22}; void fuckballs() { u32 idx = 0; for (int i = 0; i < 12 * 3; i++) { for(int j = 0; j < 4; j++) { if (colors[i] & (1 << j)) { pbuf[idx++] = 29; } else { pbuf[idx++] = 14; } } } } void ws2812_init() { fuckballs(); // Enable TIM1 and GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE); // TIM1_CH1 - PA8 GPIO_InitTypeDef gpio_init; gpio_init.GPIO_Mode = GPIO_Mode_AF_PP; gpio_init.GPIO_Speed = GPIO_Speed_50MHz; gpio_init.GPIO_Pin = GPIO_Pin_8; GPIO_Init(GPIOA, &gpio_init); // GPIO_SetBits(GPIOA, GPIO_Pin_8); TIM_TimeBaseInitTypeDef timebase_init; TIM_TimeBaseStructInit(&timebase_init); timebase_init.TIM_Prescaler = 0; timebase_init.TIM_Period = 43; // 0 - 45 where 45 is 36MHz / 45 = 800kHz timebase_init.TIM_ClockDivision = TIM_CKD_DIV1; timebase_init.TIM_CounterMode = TIM_CounterMode_Up; timebase_init.TIM_RepetitionCounter = 0x0000; TIM_TimeBaseInit(TIM1, &timebase_init); // Reload the CNT register with period? TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_OCInitTypeDef oc_init; TIM_OCStructInit(&oc_init); oc_init.TIM_OCMode = TIM_OCMode_PWM2; oc_init.TIM_OutputState = TIM_OutputState_Enable; oc_init.TIM_OutputNState = TIM_OutputNState_Disable; oc_init.TIM_Pulse = 0; oc_init.TIM_OCPolarity = TIM_OCPolarity_High; oc_init.TIM_OCNPolarity = TIM_OCPolarity_Low; oc_init.TIM_OCIdleState = TIM_OCIdleState_Reset; oc_init.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OC1Init(TIM1, &oc_init); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable); // TIM_OC1FastConfig(TIM1, ENABLE); // TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable); // TIM_CtrlPWMOutputs(TIM1, ENABLE); // TIM_Cmd(TIM1, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_InitTypeDef dma_init; DMA_StructInit(&dma_init); dma_init.DMA_PeripheralBaseAddr = (u32)(&(TIM1->CH1CVR)); dma_init.DMA_MemoryBaseAddr = (u32)&pbuf[0]; dma_init.DMA_DIR = DMA_DIR_PeripheralDST; dma_init.DMA_BufferSize = 12; dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dma_init.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte; dma_init.DMA_Mode = DMA_Mode_Normal; dma_init.DMA_Priority = DMA_Priority_VeryHigh; dma_init.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &dma_init); DMA_Cmd(DMA1_Channel5, ENABLE); TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); // TIM_SetCompare1(TIM1, 14); // TIM_Cmd(TIM1, ENABLE); // DMA_Cmd(DMA1_Channel5, DISABLE); while(1) { // DMA_ClearFlag(DMA1_FLAG_HT5); // DMA_ClearFlag(DMA1_FLAG_TC5); // DMA_Cmd(DMA1_Channel5, ENABLE); // TIM_Cmd(TIM1, ENABLE); DMA_Cmd(DMA1_Channel5, DISABLE); TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable); TIM_Cmd(TIM1, DISABLE); // TIM_DMACmd(TIM1, TIM_DMA_Update, DISABLE); Delay_Ms(100); // DMA_Cmd(DMA1_Channel5, ENABLE); // TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable); // TIM_Cmd(TIM1, ENABLE); // TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE); DMA_ClearFlag(DMA1_FLAG_TC5); // DMA_ClearFlag(DMA1_FLAG_HT5); DMA_SetCurrDataCounter(DMA1_Channel5, 12*3*8); DMA_Cmd(DMA1_Channel5, ENABLE); TIM_SetCounter(TIM1, 0); TIM_Cmd(TIM1, ENABLE); TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable); // Delay_Ms(100); while(!DMA_GetITStatus(DMA1_IT_TC5)); // Delay_Ms(10); } }