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

STM32通过PWM产生频率为20HZ占空比为50%方波,并通过单片机...

[复制链接]
STMCU 发布时间:2020-9-22 10:40
  1. int main(void)
  2. {               
  3.         char str[10];
  4.         delay_init();                     //延时函数初始化          
  5.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  6.         uart_init(115200);         //串口初始化为115200
  7.         LED_Init();                                  //初始化与LED连接的硬件接口
  8.         EXTIX_Init();                 //初始化外部中断输入
  9.         LCD_Init();
  10.         TIM3_PWM_Init(499,7199);
  11.         TIM2_Init(4999,7199);
  12.         LED0=0;                                        //先点亮红灯
  13.         TIM_SetCompare2(TIM3,250);//设置CCR2的寄存器值为250占空比为50%
  14.         LCD_ShowString(45,125,200,30,16,"-----freqency-----");
  15.         LCD_ShowString(130,165,32,30,16,"HZ");
  16.         while(1)
  17.         {            
  18.                 freq=10000.0 / (float)time_of_circle;
  19.                 sprintf(str,"%.2f",freq);
  20.                 LCD_ShowString(50,165,64,30,16,str);
  21.                 LCD_ShowString(45,125,200,30,16,"-----freqency-----");
  22.                 LCD_ShowString(130,165,32,30,16,"HZ");
  23.         }         
  24. }
复制代码

1_meitu_1.jpg

2_meitu_2.jpg





单片机产生频率为20HZ的占空比为50%方波

       通过单片机产生方波很容易,设置寄存器ARR的值就能确定周期。设置CCRx的值就能设置设置占空比。 当CNT寄存值小于CCRx的值时输出低电平,大于CCRx的值时输出高电平,到达ARR的值时溢出。知道基本的原理后通过寄存器初始化和使能相关的寄存器就可以了。

       这次实验采用TIM3 CH2不重映像,同时设置PWM模式为向上计数模式。配置步骤如下:


3_meitu_3.jpg




  • 开启TIM3时钟,并设置PA7为复用输出
  • 初始化TIM3,设置TIM3的ARR和PSC值
  • 设置TIM3_CH2的PWM模式,使能TIM3的CH2输出
  • 使能TIM3
  • 修改TIM3_CCR2来控制占空比


  1. //TIM3 PWM部分初始化
  2. //PWM输出初始化
  3. //arr:自动重装值
  4. //psc:时钟预分频数
  5. void TIM3_PWM_Init(u16 arr,u16 psc)
  6. {  
  7.         GPIO_InitTypeDef GPIO_InitStructure;
  8.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  9.         TIM_OCInitTypeDef  TIM_OCInitStructure;
  10.        

  11.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);        //使能定时器3时钟
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //①使能 GPIO 和 AFIO 复用功能时钟
  13. //        GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PC7   

  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM_CH2
  15.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  16.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  17.         GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA

  18.    //初始化TIM3
  19.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
  20.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
  21.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
  22.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  23.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  24.        
  25.         //初始化TIM3 Channel2 PWM模式         
  26.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
  27.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
  28.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
  29.         TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

  30.         TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器

  31.         TIM_Cmd(TIM3, ENABLE);  //使能TIM3
  32.        
  33. }
复制代码


       以上代码就完成了PWM的初始化,如果要产生20HZ的波形,那么就相当于要没50ms要溢出一次,那么我们可以设置arr的值为499,psc的值为7199。Tout= ((arr+1)*(psc+1))/Tclk=(499+1)* ( 7199+1)/72=50ms 。说明计数到500次为50ms,那么设置CCR2的值为250就可以实现占空比为50%。


单片机测量频率并显示

测量频率的思路有很多种,网上有关于ADC测量电压,也有关于输入捕获的。但是上次电赛校赛,学长用的是外部中断结合定时器中断来实现的,思路也比较简单。就是下降沿触发外部中断,然后打开定时器计数。当再次进入外部中断时停止计数清楚相关的标志位。这样就得到了一个计数次数,通过计数次数就可以计算出电平经历变化用的时间,时间的倒数就是相关的频率。本次实验用的是外部中断三(EXTI3)对应PE3口。



  1. void EXTIX_Init(void)
  2. {

  3.            EXTI_InitTypeDef EXTI_InitStructure;
  4.         NVIC_InitTypeDef NVIC_InitStructure;

  5.     KEY_Init();         //        按键端口初始化

  6.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //使能复用功能时钟
  7.          
  8.    //GPIOE.3          中断线以及中断初始化配置 下降沿触发 //KEY1
  9.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
  10.           EXTI_InitStructure.EXTI_Line=EXTI_Line3;
  11.           EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
  12.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  13.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器

  14.           NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;                        //使能按键KEY1所在的外部中断通道
  15.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2
  16.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;                                        //子优先级1
  17.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  18.           NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  19. }
复制代码
  1. void EXTI3_IRQHandler(void)
  2. {
  3.         if(half_cricle == 0)
  4.         {
  5.                 TIM2->CNT = 0;
  6.                 TIM_Cmd(TIM2, ENABLE);  //使能TIMx       
  7.                 half_cricle = 1;
  8.         }
  9.         else if(half_cricle == 1)
  10.         {
  11.                 time_of_circle = TIM2->CNT;
  12.                 TIM2->CNT = 0;
  13.                 TIM_Cmd(TIM2, ENABLE);  //使能TIMx       
  14.         }
  15.         EXTI_ClearITPendingBit(EXTI_Line3);
  16. }
复制代码





定时器2初始化:

  1. void TIM2_Init(u16 arr,u16 psc)
  2. {
  3.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  4. //        NVIC_InitTypeDef NVIC_InitStructure;

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

  6.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
  7.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
  8.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
  9.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  10.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

  11. //        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

  12. //        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
  13. //        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
  14. //        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  15. //        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  16. //        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器                                                         
  17. }
复制代码


主函数:


  1. int main(void)
  2. {               
  3.         char str[10];
  4.         delay_init();                     //延时函数初始化          
  5.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  6.         uart_init(115200);         //串口初始化为115200
  7.         LED_Init();                                  //初始化与LED连接的硬件接口
  8.         EXTIX_Init();                 //初始化外部中断输入
  9.         LCD_Init();
  10.         TIM3_PWM_Init(499,7199);
  11.         TIM2_Init(4999,7199);
  12.         LED0=0;                                        //先点亮红灯
  13.         TIM_SetCompare2(TIM3,250);//设置CCR2的寄存器值为250占空比为50%
  14.         LCD_ShowString(45,125,200,30,16,"-----freqency-----");
  15.         LCD_ShowString(130,165,32,30,16,"HZ");
  16.         while(1)
  17.         {            
  18.                 freq=10000.0 / (float)time_of_circle;
  19.                 sprintf(str,"%.2f",freq);
  20.                 LCD_ShowString(50,165,64,30,16,str);
  21.                 LCD_ShowString(45,125,200,30,16,"-----freqency-----");
  22.                 LCD_ShowString(130,165,32,30,16,"HZ");
  23.         }         
  24. }
复制代码



       以上就是几个主要的函数,用库函数配置比寄存器配置舒服多了,之前一直整寄存器版本的,现在接触库函数觉得实在是太方便啦!



收藏 评论1 发布时间:2020-9-22 10:40

举报

1个回答
289466080 回答时间:2020-9-22 15:10:51
用cube做个教程

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

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