你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

用DMA方式控制PWM脉冲个数

[复制链接]
asd397198334 提问时间:2018-7-17 09:50 /
悬赏2ST金币未解决
我需要用到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[7] = {50,50,50,50,50,50,0};//送到ARP或CCR寄存器的值,这里数组有7个元素,则输出7个占空比50/Period的脉冲
u16 ARR_Buffer[1000] = {0};//频率数组 单位Hz
#define SIZE_MEASURE  50 //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); //PE11  TIM1_CH2  DMA1_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 );
}

仿真波形,脉冲个数=50

仿真波形,脉冲个数=50
收藏 4 评论2 发布时间:2018-7-17 09:50

举报

2个回答
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
请问您解决了吗,我也遇到相同问题

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版