高级会员

- 积分
- 597
- 金钱
- 597
- 注册时间
- 2019-8-22
- 在线时间
- 173 小时
|
10金钱
本帖最后由 CKJJJJ 于 2020-3-30 14:47 编辑
参照一个大佬的代码,改自己想要的效果。只要频率调大了,波形就有问题。占空比明明设置了固定,但占空比却会变化,最终波形没了,只剩高电平(第二个图是第一个图的放大图)
#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基本就会有问题不稳定,那就是计数太小了 后面变小 前面变大
|