用DMA把内存数组拷贝到TIM4的CC3通道输出PWM。打了波形发现数据个数不对,会多会少。代码如下:
void Init(void)
{
GPIO_InitPara GPIO_InitStructure = {
.GPIO_Mode = GPIO_MODE_AF_PP,
.GPIO_Speed = GPIO_SPEED_10MHZ
};
TIMER_BaseInitPara TIM_TimeBaseStructure;
TIMER_OCInitPara TIM_OCInitStructure;
DMA_InitPara DMA_InitStructure;
NVIC_InitPara NVIC_InitStructure;
RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_DMA1, ENABLE);
RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_TIMER4, ENABLE);
RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_GPIOB, ENABLE);
/* GPIO Config */
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_8;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* TIM Config */
TIMER_BaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIMER_Prescaler = 0;
TIM_TimeBaseStructure.TIMER_CounterMode = TIMER_COUNTER_UP;
TIM_TimeBaseStructure.TIMER_Period = WS2812_TOTAL_CNT - 1; //800kHz
TIM_TimeBaseStructure.TIMER_ClockDivision = TIMER_CDIV_DIV1;
TIM_TimeBaseStructure.TIMER_RepetitionCounter = 1;
TIMER_BaseInit(TIMER4, &TIM_TimeBaseStructure);
TIMER_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIMER_OCMode = TIMER_OC_MODE_PWM1;
TIM_OCInitStructure.TIMER_OCIdleState = TIMER_OC_IDLE_STATE_RESET;
TIM_OCInitStructure.TIMER_OCNIdleState = TIMER_OCN_IDLE_STATE_RESET;
TIM_OCInitStructure.TIMER_OCPolarity = TIMER_OC_POLARITY_HIGH;
TIM_OCInitStructure.TIMER_OCNPolarity = TIMER_OCN_POLARITY_HIGH;
TIM_OCInitStructure.TIMER_OutputState = TIMER_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.TIMER_OutputNState = TIMER_OUTPUTN_STATE_DISABLE;
TIM_OCInitStructure.TIMER_Pulse = 0;
TIMER_OC3_Init(TIMER4, &TIM_OCInitStructure);
TIMER_CARLPreloadConfig(TIMER4, ENABLE);
TIMER_OC3_Preload(TIMER4, TIMER_OC_PRELOAD_ENABLE);
TIMER_DMACmd(TIMER4, TIMER_DMA_CH3, ENABLE);
/* DMA Config */
DMA_DeInit(DMA1_CHANNEL5);
DMA_ParaInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(TIMER4->CHCC3);
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)s_uRBGBits;
DMA_InitStructure.DMA_DIR = DMA_DIR_PERIPHERALDST;
DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_ENABLE;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PERIPHERALDATASIZE_HALFWORD;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MEMORYDATASIZE_BYTE;
DMA_InitStructure.DMA_Mode = DMA_MODE_NORMAL;
DMA_InitStructure.DMA_Priority = DMA_PRIORITY_VERYHIGH;
DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
DMA_Init(DMA1_CHANNEL5, &DMA_InitStructure);
DMA_INTConfig(DMA1_CHANNEL5, DMA_INT_TC, ENABLE);
/* NVIC Config */
NVIC_InitStructure.NVIC_IRQ = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQPreemptPriority = 0;
NVIC_InitStructure.NVIC_IRQSubPriority = 0;
NVIC_InitStructure.NVIC_IRQEnable = ENABLE;
NVIC_Init(&NVIC_InitStructure);
s_ptTIMDMASem1 = OSSemCreate(0);
TIMER_Enable(TIMER4, ENABLE);
DMA_Enable(DMA1_CHANNEL5, DISABLE);
}
void SendSeq(uint32_t memAddr, uint32_t len)
{
uint8_t os_err = 0;
DMA_Channelx->MBAR = (uint32_t)memAddr;
DMA_Channelx->RCNT = len;
DMA_Enable(DMA_Channelx, ENABLE);
OSSemPend(s_ptTIMDMASem1, 10, &os_err);
}
void DMA1_Channel5_IRQHandler (void)
{
if (DMA_GetIntBitState(DMA1_INT_TC5) == SET) {
OSIntEnter();
TIMER4->CHCC3 = 0; //Reset code
DMA_ClearIntBitState(DMA1_INT_TC5);
DMA_Enable(DMA1_CHANNEL5, DISABLE);
OSSemPost(s_ptTIMDMASem1);
OSIntExit();
}
}
|