asd397198334 发表于 2018-7-17 09:50:59

用DMA方式控制PWM脉冲个数

我需要用到stm32f103+THB6128的方案驱动步进电机,只需控制脉冲就行,要实现多颗电机运动、加减速这两个功能,所以打算用DMA传输数据到TIM1的TIMx_ARR寄存器,数组元素个数即脉冲数,在keil的仿真下输出的脉冲个数和数组元素个数是一样的,但实际用示波器测得并不是,且用该种方式得到的脉冲频率很低,程序配置如下,应该怎么改呢
#include "dma_tim.h"

#define TIM1_CCR1_Address    ((uint32_t)0x40012C34) //TIM1通道1比较寄存器
#define TIM1_CCR2_Address    ((uint32_t)0x40012C38) //TIM1通道2比较寄存器
#define TIM1_ARR_Address    ((uint32_t)0x40012C2C)//TIM1自动装载寄存器
#define TIM1_DMAR_ADDRESS   ((uint32_t)0x40012C4C)
//uint16_t SRC_Buffer = {50,50,50,50,50,50,0};//送到ARP或CCR寄存器的值,这里数组有7个元素,则输出7个占空比50/Period的脉冲
u16 ARR_Buffer = {0};//频率数组 单位Hz
#define SIZE_MEASURE50 //DMA通道元素个数
void TIM1_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStruct;       
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
        TIM_OCInitTypeDef TIM_OCInitStruct;       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);   

        TIM_Cmd(TIM1,DISABLE); //设置前先关闭定时器
        //IO口定义
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //PE11TIM1_CH2DMA1_CH3
       
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽模式
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
        GPIO_Init(GPIOE,&GPIO_InitStruct);
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //用重映射时必须打开AFIO时钟
        GPIO_PinRemapConfig(GPIO_FullRemap_TIM1,ENABLE);//TIM1完全重映射
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);         //开启TIM1的时钟 TIM1和TIM8在APB2总线上 最大工作72M
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//TIM_CKD_DIV1 = 0
        TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//设置为向上计数模式
        TIM_TimeBaseInitStruct.TIM_Period = Period-1;//设置自动重装计数器值 填入值要减1 载入DMA模式也需要这条语句
        TIM_TimeBaseInitStruct.TIM_Prescaler =Prescaler-1;//设置TIMx的预分频系数 填入值要减1
        TIM_TimeBaseInit(TIM1 ,&TIM_TimeBaseInitStruct);
               
        TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:脉冲宽度调制模式
        TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
        TIM_OCInitStruct.TIM_Pulse = 50; //占空比
       
        TIM_OC2Init(TIM1, &TIM_OCInitStruct);
        TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);
       
        TIM_ARRPreloadConfig(TIM1,ENABLE); //允许在定时器工作时向ARR缓存器写入新值
       
        TIM_Cmd(TIM1,ENABLE);
        TIM_CtrlPWMOutputs( TIM1, ENABLE ); /* Main Output Enable */
       
//允许CCR1 DMA请求
        TIM_DMACmd(TIM1,TIM_DMA_CC2, ENABLE); //通道2占空比DMA允许
}

void DMA_Configuration(void)
{
        DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体

//DMA clock enable DMA时钟开启
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

//DMA Channel2
DMA_DeInit(DMA1_Channel3);//复位DMA1通道3         
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_ARR_Address;//定义DMA通道外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ARR_Buffer;//把measure_dma首址赋给DMA存储器基址;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = SIZE_MEASURE;//DMA_BUFFER_SIZE;//定义DMA缓冲区大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable;// DMA_MemoryInc_Disable;//当前存储器地址也不变化
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//定义存储器数据宽度16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA_Mode_Circular;//DMA通道操作模式-位环形缓冲模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//不允许DMA通道存储器到存储器传输
DMA_Init(DMA1_Channel3, &DMA_InitStructure);//初始化DMA通道3   
       
//DMA Channel3 enable
        DMA_ClearFlag( DMA1_IT_TC3 );
DMA_ITConfig( DMA1_Channel3, DMA_IT_TC , ENABLE ); //使能DMA传输完成中断 半满和全满中断| DMA_IT_HT
}

void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
        DMA_Cmd(DMA_CHx, DISABLE );   
        DMA_SetCurrDataCounter(DMA_CHx,SIZE_MEASURE);//DMA通道的DMA缓存的大小
        DMA_Cmd(DMA_CHx, ENABLE);
}       
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
}

asd397198334 发表于 2018-7-17 15:38:09

调试了一早上现在可以以1K左右频率控制电机了,而且脉冲数可控,但是有个问题就是DMA传输完一次数据后,我再次调用MYDMA_Enable(DMA1_Channel3);函数,PWM的频率和个数会变得不正常,需要再次配置一次void TIM1_Configuration(void)才正常,不只为何

l12345678901234 发表于 2020-3-10 11:27:58

请问您解决了吗,我也遇到相同问题
页: [1]
查看完整版本: 用DMA方式控制PWM脉冲个数