各位大佬好,我使用PWM+DMA的方式驱动RGB,实现简单的流水灯效果,但是灯效太快。通过delay的调节速度,效果不理想,甚至没有流水效果。代码如下:
#include "ch32v10x.h"
#define T0H 30
#define T1H 60
#define LED_NUM 16
#define DATA_NUM 24
u16 RGB[DATA_NUM *LED_NUM] ;
void TIM1_PWMOUTPUT_Init(u16 arr, u16 psc, u16 ccp)
{
GPIO_InitTypeDef GPIO_InitStruct ; //GPIO结构体与TIMBase结构体未初始化,暂时没看出问题
TIM_OCInitTypeDef TIM_OCInitStruct = {0} ; // PWM结构体必须初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct = {0} ; //这个结构体不初始化,无法点亮灯 具体原因未知
//时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
//引脚
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
//TIM1
TIM_TimeBaseInitStruct.TIM_Period = arr - 1;
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
//PWM
TIM_OCInitStruct.TIM_Pulse = ccp;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
// TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStruct);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
}
void DMA1_Init()
{
DMA_InitTypeDef DMA_InitStruct ; //如果这个结构体初始化,第一个灯将会最后亮
//时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA
DMA_DeInit(DMA1_Channel2);
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32)&(TIM1->CH1CVR);
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)RGB;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; //地址不变将会卡在dma数组的0号位置
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = DATA_NUM;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStruct);
TIM_DMACmd(TIM1, TIM_DMA_CC1, ENABLE);
}
void Reset()
{
}
void COlors(u16 num, u32 rgb)
{
u8 i,j;
for(j = 0; j < num; j++)
{
for(i = 0; i <8; i++) //GRB格式发送,数组已对GRB编码顺序,改为RGB顺序
{ //数组需从24后开始,不然第一个灯亮不了
RGB[j * 24 + i + 8] = ((rgb >> 8 >> 8 >> i) & 0x1) ? T1H : T0H; //GREEN
RGB[j *24 + i] = ((rgb >> 8 >> i) & 0x1) ? T1H : T0H; //RED
RGB[j * 24 + i +16] = ((rgb >> i) & 0x1) ? T1H : T0H; //BLUE
}
}
}
void PWM_Show(u16 num)
{
DMA_SetCurrDataCounter(DMA1_Channel2, num * DATA_NUM);
DMA_Cmd(DMA1_Channel2, ENABLE);
TIM_Cmd(TIM1, ENABLE);
while(DMA_GetFlagStatus(DMA1_FLAG_TC2) != SET);
DMA_Cmd(DMA1_Channel2, DISABLE);
TIM_Cmd(TIM1, DISABLE);
DMA_ClearFlag(DMA1_FLAG_TC2);
}
u8 i;
int main(void)
{
Delay_Init();
TIM1_PWMOUTPUT_Init(90, 0, 0);
DMA1_Init();
while(1)
{
for(i = 0; i < 16; i++)
{
COlors(i+1, 0xff0000);
PWM_Show(i+1);
Delay_Ms(10);
}
for(i = 0; i < 16; i++)
{
COlors(i+1, 0x00ff00);
PWM_Show(i+1);
Delay_Ms(10);
}
for(i = 0; i < 16; i++)
{
COlors(i+1, 0x0000ff);
PWM_Show(i+1);
Delay_Ms(10);
}
}
}
请问程序有哪些可以改进的,谢谢各位大佬
|