关于TIM1 DMA方式产生单次固定不同频率脉冲不解
本帖最后由 黑皮男 于 2018-3-2 11:49 编辑最近用NUCLEO-F303RE搞了一下TIM1的DMA方式产生固定脉冲。但是参考官方的配置中有一个很不解的地方。在初始化的时候,EGR的UG位被设置了两次,虽然有注释,但实在是不解。DMA启动第一次传输是不是在UG被第一次置位的时候?请各位指点一下。
下面是官方手册的配置
DMA configuration
/* DMA1 clock enable */
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
/* Configure DMA1 Channel5 CR register */
/* Reset DMA1 Channel5 control register */
DMA1_Channel5->CCR = 0;
/* Set CHSEL bits according to DMA Channel 5 */
/* Set DIR bits according to Memory to peripheral direction */
/* Set PINC bit according to DMA Peripheral Increment Disable */
/* Set MINC bit according to DMA Memory Increment Enable */
/* Set PSIZE bits according to Peripheral DataSize = Word */
/* Set MSIZE bits according to Memory DataSize Word */
/* Set CIRC bit according to circular mode */
/* Set PL bits according to very high priority */
/* Set MBURST bits according to single memory burst */
/* Set PBURST bits according to single peripheral burst */
DMA1_Channel5->CCR |= DMA_MEMORY_TO_PERIPH |
DMA_PINC_DISABLE| DMA_MINC_ENABLE|
DMA_PDATAALIGN_WORD| DMA_MDATAALIGN_WORD |
DMA_CIRCULAR | DMA_PRIORITY_HIGH;
/* Write to DMA1 Channel5 number of data’s register */
DMA1_Channel5->CNDTR = 9;
/* Write to DMA1 Channel5 peripheral address register */
DMA1_Channel5->CPAR = (uint32_t)TIM1_DMAR_ADDRESS;
/* Write to DMA1 Channel5 Memory address register */
/* Set the address to the memory buffer “aSRC_Buffer” */
DMA1_Channel5->CMAR = (uint32_t)aSRC_Buffer;
/* Enable DMA1 Channel5 */
DMA1_Channel5->CCR |= (uint32_t)DMA_CCR_EN;
• TIM1 configuration
/* set the Timer prescaler */
Tim1Prescaler= (uint16_t) (SystemCoreClock / 32000000) - 1;
/* Configure the period */
TIM1->ARR = 0xFFFF;
/* Configure the Timer prescaler */
TIM1->PSC = Tim1Prescaler;
/* Configure pulse width */
TIM1->CCR1 = 0xFFF;
/* Select the ClockDivison to 1 */
/* Reset clockDivision bit field */
TIM1->CR1 &= ~ TIM_CR1_CKD;
/* Select DIV1 as clock division*/
TIM1->CR1 |= TIM_CLOCKDIVISION_DIV1;
/* Select the Up-counting for TIM1 counter */
/* Reset mode selection bit fiels*/
TIM1->CR1 &= ~( TIM_CR1_DIR | TIM_CR1_CMS);
/* selct Up-counting mode */
TIM1->CR1 |= TIM_COUNTERMODE_UP;
/* SET PWM1 mode */
/* Reset the Output Compare Mode Bits */
TIM1->CCMR1 &= ~TIM_CCMR1_OC1M;
TIM1->CCMR1 &= ~TIM_CCMR1_CC1S;
/* Select the output compare mode 1*/
TIM1->CCMR1 |= TIM_OCMODE_PWM1;
/* Enable the output compare 1 Preload */
TIM1->CCMR1 |= TIM_CCMR1_OC1PE;
/* Enable auto-reload Preload */
TIM1->CR1 |= TIM_CR1_ARPE;
/* TIM1 DMA Update enable */
TIM1->DIER |= TIM_DMA_UPDATE;
/* Configure of the DMA Base register and the DMA Burst Length */
/* Reset DBA and DBL bit fields */
TIM1->DCR &= ~TIM_DCR_DBA;
TIM1->DCR &= ~TIM_DCR_DBL;
/* Select the DMA base register and DMA burst length */
TIM1->DCR = TIM_DMABase_ARR | TIM_DMABurstLength_3Transfers;
/* Enable UEV by setting UG bit to Load buffer data into preload registers
*/
TIM1->EGR |= TIM_EGR_UG;
/* wait until the RESET of UG bit*/
while((TIM1->EGR & TIM_EGR_UG) == SET){}
/* Enable UEV by setting UG bit to load data from preload to active
registers */
TIM1->EGR |= TIM_EGR_UG;
/* Enable the TIM1 Main Output */
TIM1->BDTR |= TIM_BDTR_MOE;
/* Enable CC1 output*/
TIM1->CCER |= TIM_CCER_CC1E;
/* Enable the TIM Counter */
TIM1->CR1 |= TIM_CR1_CEN;
DMA启动传输应该是UG被第二次置位的时候。
起用了缓存,你的第29行用了,TIM1->CR1 |= TIM_CR1_ARPE;
因此,就像注释38行、43行说的那样,第一次是把数据从buffer加载到preload寄存器,第二次是把preload寄存器中的数据加载到active寄存器寄存器。
看的好复杂。采用Tick中断产生脉冲比这个简单多了,并且频率仅由Tick控制。想想是吗? TIM1_EGR为事件触发寄存器。
UG位是事件更新位,由软件置1,硬件自动清零。
当置1时,重新初始化定时器计数器并生成寄存器的更新。
请注意预分频计数器也被清零(但预分频比不受影响)。
我个人理解为:刚上电时,TIM1_EGR的数据全为零,
通过UG位置1来判断系统预加载是否已经完成。
而第二次 TIM1->EGR |= TIM_EGR_UG;
是为了计数器清零的。 zhjb1 发表于 2018-3-7 09:09
看的好复杂。采用Tick中断产生脉冲比这个简单多了,并且频率仅由Tick控制。想想是吗? ...
你说的这个频率不能很高,太高的话中断响应不过来,不过高级定时器的话可以达到很高频率,但是频率切换之间的时间间隔会相对较长 无薪税绵 发表于 2018-3-7 10:31
TIM1_EGR为事件触发寄存器。
UG位是事件更新位,由软件置1,硬件自动清零。
当置1时,重新初始化定时器计 ...
按理来说,两次置位UG的效果应该相同,都会重新开始计数吧。有点迷惑。还有一个问题就是定时器刚启动的时候,DMA传输是在定时器启动前还是第一次计数溢出后开始传输的,还是定时器启动前才开始传输的,从现象来看,启动前就已经出发了传输。 硬件刚上电时,其电压尚未稳定,系统时钟也未稳定,
所以一般在程序启动时,会加入一定的延时时间,
作为让系统稳定的过程。
而第一次UG置位,正常情况下是相当于清零,
但是也是防止系统未预加载成功时,作为延时用的。
第二次置位,其实就是纯淬的清零动作了。
你可以试试,注释掉第二句,其实也是可以运行的,
只是在特殊的情况下(比如:未预加载成功时),
就会出现问题了。
第二个问题,其实toofree大神已经解释的很清楚了:
DMA启动传输应该是UG被第二次置位的时候。
第一次是把数据从buffer加载到preload寄存器,
第二次是把preload寄存器中的数据加载到active寄存器寄存器。
页:
[1]