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

用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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版