OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2612|回复: 4

TIM8+DMA2的通道3输出1MHZ的PWM,波形有问题

[复制链接]

7

主题

25

帖子

0

精华

高级会员

Rank: 4

积分
597
金钱
597
注册时间
2019-8-22
在线时间
173 小时
发表于 2020-3-30 14:18:27 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 CKJJJJ 于 2020-3-30 14:47 编辑

参照一个大佬的代码,改自己想要的效果。只要频率调大了,波形就有问题。占空比明明设置了固定,但占空比却会变化,最终波形没了,只剩高电平(第二个图是第一个图的放大图)
1.png 2.png
#define PWM_TIMx                         TIM8
#define PWM_TIM_APBxClock_CMD            RCC_APB2PeriphClockCmd
#define PWM_TIM_CLK                      RCC_APB2Periph_TIM8
#define PWM_TIM_GPIO_CLK                 (RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO )

void TIM_Dma_Pwm_Pulse_Output_Init(u16 arr,u16 psc)
{
    GPIO_InitTypeDef         GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef        TIM_OCInitStructure;
    DMA_InitTypeDef          DMA_InitStructure;
    NVIC_InitTypeDef         NVIC_InitStructure;

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);                  //设置缺省值,这一步最好加上防止放到串口初始化后出问题
    TIM_OCStructInit(&TIM_OCInitStructure);                          //设置缺省值,这一步最好加上防止放到串口初始化后出问题
    //TIM_ICStructInit(&TIM_ICInitStructure);                        //设置缺省值,这一步最好加上防止放到串口初始化后出问题

    PWM_TIM_APBxClock_CMD(PWM_TIM_CLK, ENABLE);                                //使能定时器时钟
    PWM_TIM_GPIO_APBxClock_CMD(PWM_TIM_GPIO_CLK, ENABLE);        //使能GPIO外设和AFIO复用功能模块时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    //初始化TIM
    TIM_TimeBaseStructure.TIM_Period = arr;                              //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc;                            //设置用来作为TIMx时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;              //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;          //TIM向上计数模式
    TIM_TimeBaseInit(PWM_TIMx, &TIM_TimeBaseStructure);


    //初始化TIM3 Channe1 PWM模式
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                    //选择定时器模式:TIM脉冲宽度调制模式2
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        //比较输出使能
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;             //输出极性:TIM输出比较极性高
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    TIM_OC1Init(PWM_TIMx, &TIM_OCInitStructure);                     //初始化通道1
    TIM_OC1PreloadConfig(PWM_TIMx, TIM_OCPreload_Enable);            //使能TIM在通道1上的预装载寄存器

/*******DMA2_CH3  ---- TIM8_CH1 *********/
    DMA_DeInit(DMA2_Channel3);                                                 //将DMA的通道1寄存器重设为缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&PWM_TIMx->CCR1;           //DMA外设基地址
    DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)&Duty1;                                                //DMA内存基地址
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST;          //DMA_DIR_PeripheralSRC:从外设读  DMA_DIR_PeripheralDST:从内存读
    DMA_InitStructure.DMA_BufferSize         = 0;                              //DMA通道的DMA缓存的大小,实测不加1少一个,应该是最后一个还没输出就中断关闭定时器了,+1就好了
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;      //外设地址寄存器不变
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Disable;                      //内存地址寄存器递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度为8位
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;    //数据宽度为8位
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;                //工作在正常模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;            //DMA通道 x拥有中优先级
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;           
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);                               //根据DMA_InitStruct中指定的参数初始化DMA的通道所标识的寄存器
    DMA_Cmd(DMA2_Channel3, ENABLE);                                            //DMA使能

    TIM_DMACmd(PWM_TIMx,TIM_DMA_CC1, ENABLE);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    DMA_ClearFlag(DMA2_Channel3_IRQn);                                         //清除DMA所有标志
    DMA_ITConfig(DMA2_Channel3,DMA_IT_TC,ENABLE);                              //开传输完成中断

    TIM_SetCompare1(PWM_TIMx,0);       //通道1
    TIM_CtrlPWMOutputs(PWM_TIMx, ENABLE);//高级定时器用
    TIM_Cmd(PWM_TIMx, ENABLE);         //使能TIM

void TIM_Dma_Pwm_Pulse_Output1(u8 Duty,u16 Pls_Num)
{
        //TIM_Cmd(PWM_TIMx, DISABLE);
        Duty1=(PWM_TIMx->ARR+1)*Duty/100;                                     //计算占空比
    TIM_SetCompare1(PWM_TIMx,Duty1);                        //占空比填入比较寄存器

    DMA_Cmd(DMA2_Channel3, DISABLE);                        //DMA失能才能设置
    DMA_SetCurrDataCounter(DMA2_Channel3,Pls_Num+1);        //设置DMA长度,即脉冲数量
    DMA_Cmd(DMA2_Channel3, ENABLE);                         //开启
    //TIM_Cmd(PWM_TIMx, ENABLE);
}

void DMA2_Channel3_IRQHandler(void)                                                        //脉冲输出完毕,关闭输出
{
    if(DMA_GetITStatus(DMA2_FLAG_TC3))
    {
        TIM_SetCompare1(PWM_TIMx, 0);
        DMA_ClearFlag(DMA2_Channel3_IRQn);
        DMA_ClearFlag(DMA2_FLAG_GL3);
    }
}

主函数main
TIM_Dma_Pwm_Pulse_Output_Init(2-1,72-1);//硬件初始化默认周期=2*72/72000000=2us
        while(1)
        {
                TIM_Dma_Pwm_Pulse_Output1(50, 1000);
                delay_ms(5);        
}



最佳答案

查看完整内容[请看2#楼]

你还没搞定呀 我给你改的定时器1的 代码肯定可以 TIM_Dma_Pwm_Pulse_Output_Init(2-1,72-1);---->TIM_Dma_Pwm_Pulse_Output_Init(12-1,12-1);试试,你那就计数两个数还没开始就结束了,中断都反应不过来 你都不听我的,让你先低频逐步高频,看到啥时候出问题 后面72-1 前面到4基本就会有问题不稳定,那就是计数太小了 后面变小 前面变大
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2020-3-30 14:18:28 | 显示全部楼层
本帖最后由 nashui_sx 于 2020-3-30 16:03 编辑

你还没搞定呀  我给你改的定时器1的  代码肯定可以   TIM_Dma_Pwm_Pulse_Output_Init(2-1,72-1);---->TIM_Dma_Pwm_Pulse_Output_Init(12-1,12-1);试试,你那就计数两个数还没开始就结束了,中断都反应不过来
你都不听我的,让你先低频逐步高频,看到啥时候出问题   后面72-1  前面到4基本就会有问题不稳定,那就是计数太小了  后面变小 前面变大
QQ截图20200330143513.png

回复

使用道具 举报

6

主题

412

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
2711
金钱
2711
注册时间
2019-8-14
在线时间
414 小时
发表于 2020-3-30 15:45:44 | 显示全部楼层
帮顶~~
回复

使用道具 举报

7

主题

25

帖子

0

精华

高级会员

Rank: 4

积分
597
金钱
597
注册时间
2019-8-22
在线时间
173 小时
 楼主| 发表于 2020-3-30 16:01:30 | 显示全部楼层

虽然还没解决,不过谢谢老哥助攻
回复

使用道具 举报

7

主题

25

帖子

0

精华

高级会员

Rank: 4

积分
597
金钱
597
注册时间
2019-8-22
在线时间
173 小时
 楼主| 发表于 2020-3-31 09:25:57 | 显示全部楼层
nashui_sx 发表于 2020-3-30 16:01
你还没搞定呀  我给你改的定时器1的  代码肯定可以   TIM_Dma_Pwm_Pulse_Output_Init(2-1,72-1);---->TIM_D ...

解决了,谢谢老哥
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-24 06:53

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表