stm32关于输出PWM.docx

上传人:b****2 文档编号:24485261 上传时间:2023-05-28 格式:DOCX 页数:13 大小:18.02KB
下载 相关 举报
stm32关于输出PWM.docx_第1页
第1页 / 共13页
stm32关于输出PWM.docx_第2页
第2页 / 共13页
stm32关于输出PWM.docx_第3页
第3页 / 共13页
stm32关于输出PWM.docx_第4页
第4页 / 共13页
stm32关于输出PWM.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

stm32关于输出PWM.docx

《stm32关于输出PWM.docx》由会员分享,可在线阅读,更多相关《stm32关于输出PWM.docx(13页珍藏版)》请在冰豆网上搜索。

stm32关于输出PWM.docx

stm32关于输出PWM

STM32定时器产生PWM

我先用STM32的通用定时器用PWM模式产生四路相同占空比,不同频率的PWM波,配置如下:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟

       TIM_InternalClockConfig(TIM2);//使用内部时钟

 

       TIM_BaseInitStructure.TIM_Prescaler=3;//设置TIM时钟频率除数的预分频值

      TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择计数器模式

      TIM_BaseInitStructure.TIM_Period=1799;//设置下一个更新事件装入活动的自动重装载寄存器周期的值

      TIM_BaseInitStructure.TIM_ClockDivision=0;//设置时钟分割

 

       TIM_TimeBaseInit(TIM2,&TIM_BaseInitStructure);

      

       //通道1

       TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择定时器模式

      TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//选择输出比较状态

      TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Disable;//选择互补输出比较状态

      TIM_OCInitStructure.TIM_Pulse=CCR1_Val;//设置了待装入捕获比较器的脉冲值

      TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出极性

      TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;//设置互补输出极性

      TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;//选择空闲状态下得非工作状态

      TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;//选择互补空闲状态下得非工作状态

       TIM_OC1Init(TIM2,&TIM_OCInitStructure);

       TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);

 

       //通道2  

      TIM_OCInitStructure.TIM_Pulse=CCR2_Val;//设置了待装入捕获比较器的脉冲值

       TIM_OC2Init(TIM2,&TIM_OCInitStructure);

       TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);

 

       //通道3

       TIM_OCInitStructure.TIM_Pulse=CCR3_Val;//设置了待装入捕获比较器的脉冲值

       TIM_OC3Init(TIM2,&TIM_OCInitStructure);

       TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);

 

       //通道4

       TIM_OCInitStructure.TIM_Pulse=CCR4_Val;//设置了待装入捕获比较器的脉冲值

       TIM_OC4Init(TIM2,&TIM_OCInitStructure);

       TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);

 

       TIM_Cmd(TIM2,ENABLE);

       TIM_CtrlPWMOutputs(TIM2,ENABLE);

用pwm模式输出的频率和占空比是固定的,不可调,要想输出频率可调,占空比可调,必须得使用比较输出模式。

这点资料是在STM32全国巡回研讨会上看到的,如图:

所以,接下来我就写了一个程序通过输出比较模式产生一路PWM波,这个波的频率和占空比都由自己确定,函数配置如下:

       TIM_BaseInitStructure.TIM_Prescaler=3;//设置TIM时钟频率除数的预分频值(18M)

      TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择计数器模式

      TIM_BaseInitStructure.TIM_Period=1800;//设置下一个更新事件装入活动的自动重装载寄存器周期的值

      TIM_BaseInitStructure.TIM_ClockDivision=0;//设置时钟分割

       TIM_TimeBaseInit(TIM2,&TIM_BaseInitStructure);

       //通道1

       TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;//选择定时器模式

      TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//选择输出比较状态

      TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Disable;//选择互补输出比较状态

      TIM_OCInitStructure.TIM_Pulse=CCR1_Val1;//设置了待装入捕获比较器的脉冲值

      TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出极性

      TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;//设置互补输出极性

      TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;//选择空闲状态下得非工作状态

      TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;//选择互补空闲状态下得非工作状态

       TIM_OC1Init(TIM2,&TIM_OCInitStructure);

       TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Disable);

       TIM_ARRPreloadConfig(TIM2,ENABLE);

       TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);

       TIM_Cmd(TIM2,ENABLE);

             

}

 

 

voidTIM2_IRQHandler(void)

{

       TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);

       if(n==1)

       {

              n=0;

              TIM_SetCompare1(TIM2,CCR1_Val2);

       }

       else

       {

              n=1;

             TIM_SetCompare1(TIM2,CCR1_Val1);

       }                                    

}

通过改变比较寄存器(CCR1)中的值,改变PWM的占空比,在每次匹配中断中改变CCR1的值。

上面程序实现的是产生一路频率为10K占空比为40%的PWM波。

有了上面的思想我就想产生四路不同频率不同占空比的PWM波,经过反复思考光配函数似乎不能实现,在网上去查了的,很多网友也说不能实现,有一个网友给了一个提示:

软件模拟。

刚开始没明白什么意思,于是还是自己继续配置库函数,在这个过程中一直有两个疑问:

每次中断中,CCR寄存器的值都在循环的增加,CCR的寄存器不可能是无限大吧?

就算是无限大,计数器也不是无限大呀,他只能记到65535。

初步确定使用匹配中断不行,我有想过同时使用溢出中断和匹配中断,但这样四路PWM波只能是固定的,频率和占空比不能调。

大概说一下怎样用溢出中断和匹配中断实现四路固定的PWM波,把计数器寄存器(CNT)的值装最大周期的那个PWM波,当一次计数完成算一下三路小点周期数,在匹配中断中对应的设个变量,CCR就改变几次,溢出中断来了就再次给计数器装初值,同时四个比较寄存器从装初值,这样很麻烦,理论上可以实现,但我考虑到最终不能实现我的要求,就没有去验证。

所以产生四路频率可调占空比可调,用一个定时器似乎不能实现,就一直卡到这里,我又在想飞哥说能实现,就肯定能实现,我又在网上找资料,还是没找到,只是有人题四路,软模拟,于是我就思考用软模拟实现,最后在一个师兄的指点下,确实用软件模拟一个中间比较寄存器能实现,思路大概是这样子的,首先让比较寄存器装满,也就是最大值(65535),然后通过改变模拟比较寄存器的值,每次匹配中断只需把模拟比较寄存器的值去比较就行,具体方案看程序。

unsignedchar  Cnt[4];//一个数组,这个数组的每个元素对应一个通道,用来判断装PWM得高电平还是低电平数

unsignedint  T[4];//周期数组

unsignedint  R[4];//模拟的比较寄存器数组,一样的每个通道对应一个数组元素

unsignedint  Rh[4];//模拟的PWM高电平比较寄存器

unsignedint  Rl[4];//模拟的PWM低电平比较寄存器

unsignedcharF[4];//占空比数组

unsignedintCCR1,CCR2,CCR3,CCR4;

 

voidInit(void)

{

       unsignedchari=0;      

       for(i=0;i<4;i++)

       {

              Cnt[i]=0;

              T[i]  =0;

              R[i]  =0;

              Rh[i]=0;

              Rl[i]=0;

              F[i]  =0;

       }    

       //t的范围为(0~65536)    

       T[0]=450;        //F=40K

       T[1]=600;        //F=30K

       T[2]=900;        //F=20K

       T[3]=1800;   //F=10K

       //F(占空比)的范围为(0~100)

       F[0]=40;

       F[1]=30;

       F[2]=20;

       F[3]=10;     

       for(i=0;i<4;i++)

       {

              Rh[i]=(T[i]*F[i])/100;

              Rl[i]=T[i]-Rh[i];

       }    

       R[0]=Rl[0];

       R[1]=Rl[1];

       R[2]=Rl[2];

       R[3]=Rl[3];

      

       CCR1=R[0];

       CCR2=R[1];

       CCR3=R[2];

       CCR4=R[3];

}

对应的数组初始化

 

voidRCC_Configuration(void)

{

       RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);

}

时钟配置

voidGPIO_Configuration(void)

{

       GPIO_InitTypeDefGPIO_InitStructure;

   //Key1PA0Key3PA8

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;

      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

       GPIO_Init(GPIOA,&GPIO_InitStructure);

       //Key2PC13

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;

      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

       GPIO_Init(GPIOC,&GPIO_InitStructure);

       //KeyPD3

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;

      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

       GPIO_Init(GPIOD,&GPIO_InitStructure);

       //TIM3CH1CH2

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;

      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

       GPIO_Init(GPIOA,&GPIO_InitStructure);

       //TIM3CH3CH4

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;

      GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

      GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

       GPIO_Init(GPIOB,&GPIO_InitStructure);

}

管脚配置

voidNVIC_Configuration(void)

{

       NVIC_InitTypeDefNVIC_InitStructure;

       #ifdefVECT_TAB_RAM

       NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);

       #else

       NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);

       #endif

       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 

       NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQChannel;

      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;

      NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

      NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

 

       NVIC_Init(&NVIC_InitStructure);     

}

中断配置

voidTIM_Configuration(void)

{

       TIM_TimeBaseInitTypeDefTIM_BaseInitStructure;

       TIM_OCInitTypeDefTIM_OCInitStructure;

 

       TIM_InternalClockConfig(TIM3);

 

       TIM_BaseInitStructure.TIM_Prescaler=3;//4分频,18M

      TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;

      TIM_BaseInitStructure.TIM_Period=65535;

      TIM_BaseInitStructure.TIM_ClockDivision=0;

      TIM_BaseInitStructure.TIM_RepetitionCounter=0;

       TIM_TimeBaseInit(TIM3,&TIM_BaseInitStructure);

 

       TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

      TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;

      TIM_OCInitStructure.TIM_Pulse=CCR1;

      TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

       TIM_OC1Init(TIM3,&TIM_OCInitStructure);

       TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);

       TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

 

       TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

       TIM_OCInitStructure.TIM_Pulse=CCR2;

       TIM_OC2Init(TIM3,&TIM_OCInitStructure);

       TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);

       TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);

 

     TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

       TIM_OCInitStructure.TIM_Pulse=CCR3;

       TIM_OC3Init(TIM3,&TIM_OCInitStructure);

       TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Disable);

       TIM_ClearITPendingBit(TIM3,TIM_IT_CC3);

 

       TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

       TIM_OCInitStructure.TIM_Pulse=CCR4;

       TIM_OC4Init(TIM3,&TIM_OCInitStructure);

       TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Disable);

       TIM_ClearITPendingBit(TIM3,TIM_IT_CC4);

 

       TIM_Cmd(TIM3,ENABLE);

       TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

       TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE);

}

 

voidTIM3_IRQHandler(void)

{

       if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!

=RESET)

       {

              TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

              Cnt[0]=(~Cnt[0])&0x01;

              if(Cnt[0]==0x01)  

                     R[0]+=Rl[0];

              else

                     R[0]+=Rh[0];

              if(R[0]>65535)

                     R[0]=R[0]-65535;

              CCR1=R[0];

              TIM_SetCompare1(TIM3,CCR1);

       }

       if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!

=RESET)

       {

              TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);

              Cnt[1]=(

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1