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

【经验分享】STM32F103单片机PWM功能实现

[复制链接]
STMCU小助手 发布时间:2022-3-19 20:46
  PWM模式也叫脉冲宽度调制模式,它可以产生一个频率和占空比可调的方波。由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。在硬件电路中,PWM波产生通常是由一个三角波和参考值送入比较器中,然后比较器输出的就是PWM波。

P_~R{DX]CL00QJ@NO~F0}38.png

V1是三角波发生器,幅度为5V,频率为1K,V2是直流源,电压为3V,将这两个波形送入到比较器中,然后比较器输出的就是PWM波。输出波形如下:

U[]WA5[8`W@ESN3180US0}R.png

当V1的电压值大于V2时,比较器输出高电平。当V1电压值小于V2时,比较器输出的就是低电平。改变V2的值,就可以改变占空比。

NQ$CU2@XD]Q`[9%P%K0.png

  在单片机中寄存器ARR的值就相当于V1的值,CCR的值就相当于V2的值。当ARR和CCR寄存器的值设置好之后,计时器在计数的过程中计数器值就会实时和这两个值比较,当计数器值小于CCR时,输出低电平,当计数器值大于CCR值时,输出高电平。当计数器的值等于ARR时,计数器就会清零。

  在设置PWM计数模式的时候,一般有三种模式,向上计数模式、向下计数模式、中央对齐模式。

  向上计数模式:指的是计数器从0开始递增计数,当计数值等于ARR时,计数器清0,然后从0开始重新递增计数。

5B`QVR%IN$XH8IHK87KBU2Y.png

  向下计数模式:指的是计数器从ARR开始递减计数,当计数值等于0时,计数器值重新设置为ARR,然后从ARR开始重新递减计数。

%0TQS)XLS8[MB4BB8WSE0Y6.png

  中央对齐模式:指的是计数器0开始递增计数,当计数值等于ARR时,计时器开始递减计数。当计数器值减到0时,又开始递增计数。

XJXOR8AI]4LC{I$HN~JL%LI.png

  一般情况下用的比较多的就是向上计数模式,因为这种模式比较简单,理解起来也更容易一点。下面就通过代码来实现PWM的输出功能。

  1. void TIM3_PWM_Init(u16 arr, u16 psc)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  5.     TIM_OCInitTypeDef TIM_OCInitStructure;

  6.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);                                                        //使能定时器3时钟
  7.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);        //使能GPIO和AFIO复用功能模块时钟

  8.     GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);        //Timer3部分重映射 TIM3_CH2(PA7)--->PB5  TIM3_CH1(PA6)-->PB4

  9.     //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形        GPIOB.5
  10.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  11.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  12.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  14.     //初始化TIM3
  15.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  16.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  17.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  18.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  19.     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  20.     //初始化TIM3_CH2  PWM 模式
  21.     TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  22.     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  23.     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  24.     TIM_OC2Init(TIM3, &TIM_OCInitStructure);
  25.     //使能TIM3在CCR2上的预装载寄存器
  26.     TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
  27.     //使能TIM3
  28.     TIM_Cmd(TIM3, ENABLE);
  29. }
  30. void TIM1_PWM_Init(u16 arr, u16 psc)
  31. {
  32.     GPIO_InitTypeDef GPIO_InitStructure;
  33.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  34.     TIM_OCInitTypeDef TIM_OCInitSturcture;
  35.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE);

  36.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  37.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  38.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  39.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  40.     TIM_TimeBaseInitStructure.TIM_Period = arr;
  41.     TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
  42.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  43.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  44.     TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
  45.     TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);

  46.     TIM_OCInitSturcture.TIM_OCMode = TIM_OCMode_PWM2;
  47.     TIM_OCInitSturcture.TIM_OutputState = TIM_OutputState_Enable;
  48.     TIM_OCInitSturcture.TIM_OCPolarity = TIM_OCPolarity_High;
  49.     TIM_OC1Init(TIM1, &TIM_OCInitSturcture);

  50.         
  51.     TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

  52.     TIM_Cmd(TIM1, ENABLE);                                //使能计数器
  53.     TIM_CtrlPWMOutputs(TIM1,ENABLE);        //主输出使能
  54. }
复制代码

  这里通过两个定时器输出2路PWM波。使用的计数模式都为向上计数模式。PWM模式为PWM2模式。

C)0QR8F~JE@77SIGEYZPF.png

  接下来在主程序中设置PWM的频率和占空比。

  1. int main(void)
  2. {
  3.     u16 led_pwm_val=0;
  4.     u8 dir=1;
  5.     delay_init();       //延时函数初始化
  6.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  7.     LED_Init();
  8.     TIM3_PWM_Init(899,0);        //不分频。PWM频率=72000000/900=80Khz
  9.     TIM1_PWM_Init(899,0);
  10.     while(1)
  11.     {
  12.                 delay_ms(10);
  13.                 if(dir) led_pwm_val++;
  14.                 else led_pwm_val--;
  15.                
  16.                 if(led_pwm_val>300) dir=0;
  17.                 if(led_pwm_val==0) dir=1;
  18.                 TIM_SetCompare2(TIM3,led_pwm_val);
  19.                 TIM_SetCompare1(TIM1,led_pwm_val);
  20.     }
  21. }
复制代码

  在主函数中向初始化函数中传递两个参数,第一个参数是设置ARR值,第二个参数是设置时钟的分频系数。这里设置的ARR值为900,系统会自动给设置的值加1(因为ARR的值至少为1),所以设置值为899时,系统真正写入ARR寄存器的值是899+1,然后时钟分频系数设置为0,也就是默认时钟频率72MHz不分频。这样PWM的频率就为系统时钟除以自动装载的值。设置的PWM频率为 72MHz/900=80K。

  要改变占空比时通过TIM_SetCompare()函数来设置,这个函数内部设置的就是CCR寄存器的值。
代码中设置的是CCR的值从0增加到300,然后又减到0。将PWM的输出端口接上一个LED灯,就可看到这个LED灯从亮到灭慢慢变化,实现了类似于呼吸灯的效果。

收藏 评论0 发布时间:2022-3-19 20:46

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版