本帖最后由 Volftooth 于 2015-7-17 14:25 编辑
我想使用 TIM4 的 DMA burst 来同时更新 CCR1 和 CCR2 的值、
在手册中有一段话是这么写的:
按照他的意思来说如果要对每一个 CCRx 寄存器更新两次或者多次的话、就需要设置 DMA->CNDTR 为 N*x(N 为次数、x 为 CCR 寄存器数量)、
而且更新的时候每次 DMA 都会自动从数组中取 x 个数填到对应的 CCRx 里面去、
那么问题就来了:DMA->CNDTR 如果没有减到 0 的话 DMA 会停下来吗?
按照上面说、DBL 设为 3、CNDTR 设为 6、第一次 DMA 请求时会从 6 个数组中取前三个填到 CCR1,2,3 中、第二次 DMA 请求会取后三个填到 CCR1,2,3 中、
那么此时 CNDTR 并没有到 0 啊、也就是 DMA 还会继续给 DMAR 发数据、然后覆盖掉前面的 CCRx 中的值、
实在不明白、
在程序中验证如果把 CNDTR 改为倍数的话就会有问题:
程序中 DBL=2 CNDTR=2 时、输出和预期符合、输出低电平 100us、高电平 810us 的 PWM 波、
如果将 CNDTR 修改为 4、那么输出就变成了、低 400us、高 510us 的 PWM 波、
代码如下:
uint16_t dfo3_freq_buffer[DFO_FREQ_BUFFER_SIZE] = {7200,14400,21600,28800,36000,43200,50400,57600,64800};
void DFO34_Initializing()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_10);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_10);
TIM4->ARR = 65536 - 1;
TIM4->PSC = 0;
TIM4->EGR = TIM_EGR_UG;
TIM4->CR2 &= ~TIM_CR2_CCDS;
TIM4->CR1 &= ~(TIM_CR1_CMS | TIM_CR1_DIR | TIM_CR1_CKD);
TIM4->CR1 |= TIM_CR1_ARPE | TIM_CR1_URS | TIM_CounterMode_Up;
TIM4->DIER |= TIM_DIER_UDE;
TIM4->CCMR1 &= ~(TIM_CCMR1_OC1M | TIM_CCMR1_OC1CE | TIM_CCMR1_OC1PE | TIM_CCMR1_OC1FE | TIM_CCMR1_CC1S);
TIM4->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1/* | TIM_CCMR1_OC2PE*/ | TIM_CCMR1_OC1CE;
TIM4->CCMR1 &= ~(TIM_CCMR1_OC2M | TIM_CCMR1_OC2CE | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2FE | TIM_CCMR1_CC2S);
TIM4->CCMR1 |= TIM_CCMR1_OC2M_0 | TIM_CCMR1_OC2M_1/* | TIM_CCMR1_OC2PE*/ | TIM_CCMR1_OC2CE;
TIM4->CCR1 = 1;
TIM4->CCR2 = 1;
TIM4->CCER &= ~(TIM_CCER_CC1NP | TIM_CCER_CC1E | TIM_CCER_CC1P);
TIM4->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1P;
TIM4->CCER &= ~(TIM_CCER_CC2NP | TIM_CCER_CC2E | TIM_CCER_CC2P);
TIM4->CCER |= TIM_CCER_CC2E | TIM_CCER_CC2P;
TIM4->DCR = 2 << 8 | TIM_DMABase_CCR1;
DMA1_Channel7->CNDTR = 2;
DMA1_Channel7->CPAR = (uint32_t)&TIM4->DMAR;
DMA1_Channel7->CMAR = (uint32_t)dfo3_freq_buffer;
DMA1_Channel7->CCR =
DMA_M2M_Disable |
DMA_Priority_Low |
DMA_MemoryDataSize_HalfWord |
DMA_PeripheralDataSize_HalfWord |
DMA_MemoryInc_Enable |
DMA_PeripheralInc_Disable |
DMA_Mode_Normal |
DMA_DIR_PeripheralDST |
DMA_CCR_EN;
TIM4->CR1 |= TIM_CR1_CEN;
}
UPDATE:
PWM 波时间不对的问题自己找到了、因为 DBL 的实际传送次数是 DBL + 1 的、我上面写了二实际从传了三次、将 28800 传给了 CCR1、所以低电平是 400us 没问题、
然后看起来 burst 是将 DMA 给暂停了、等下一次有请求来的时候再传剩下的数据、但还是不明白其中的作用原理。。。。
|