用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();
- }
- }
|