找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9922|回复: 5
打印 上一主题 下一主题
收起左侧

STM32 PWM实现精确输出脉冲数控制电机

[复制链接]
跳转到指定楼层
楼主
ID:228828 发表于 2017-8-22 17:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
精确输出脉冲数控制电机,使用stm32单片机的pwm功能实现,精确控制脉冲个数

单片机源程序如下:
  1. #include <stm32f10x_lib.h>
  2. #include "sys.h"
  3. #include "usart.h"               
  4. #include "delay.h"       
  5. #include "led.h"
  6. #include "exti.h"
  7. #include "key.h"
  8. #define MOTOR_DIR PBout(11)// PB11
  9. #define MOTOR_EN  PEout(15)// PE15
  10. u16 i;
  11. u16 fre;
  12. u16        TIM5CH1_CAPTURE_VAL;        //输入捕获值
  13. u16 PUL_CNT;
  14. void Motor_Set()
  15. {
  16.         RCC->APB2ENR|=1<<3;    //使能PORTB时钟                    
  17.         GPIOB->CRH&=0XFFFF0FFF;
  18.         GPIOB->CRH|=0X00003000;  //PB11 推挽输出            
  19.     GPIOB->ODR|=(1<<11);      //PB11 输出高
  20.         RCC->APB2ENR|=1<<6;    //使能PORTE时钟                    
  21.         GPIOE->CRH&=0X0FFFFFFF;
  22.         GPIOE->CRH|=0X30000000;  //PE15 推挽输出            
  23.     GPIOE->ODR|=(1<<15);      //PE15 输出高
  24.         MOTOR_EN=0; //不使能
  25. }          
  26. void Timer3_Init(u16 arr,u16 psc)
  27. {
  28.         RCC->APB2ENR|=1<<2;    //使能PORTA时钟
  29.         RCC->APB2ENR|=1<<3;    //使能PORTB时钟
  30.         RCC->APB2ENR|=1<<5;    //使能PORTD时钟
  31.         GPIOB->CRL&=0XFF0FFFFF;        //PB5输出
  32.         GPIOB->CRL|=0X00B00000;        //复用功能输出           

  33.         GPIOA->CRL&=0x00ffffff;
  34.         GPIOA->CRL|=0xBB000000;
  35.         GPIOA->ODR|=3<<6;
  36.         GPIOB->CRL&=0xffffff00;
  37.         GPIOB->CRL|=0x000000BB;
  38.         GPIOB->ODR|=3;
  39.         RCC->APB1ENR|=1<<1;//TIM3时钟使能
  40.         TIM3->CR1|=1<<4;//向下计数
  41.         TIM3->CCMR1=0x6868;//通道1、2PWM模式1,预装载使能
  42.         TIM3->CCMR2=0x6868;//通道3、4PWM模式1,预装载使能
  43.        
  44.         TIM3->CCR1=100;
  45.         TIM3->CCR2=200;
  46.         TIM3->CCR3=200;
  47.         TIM3->CCR4=100; //4k->250
  48.         TIM3->ARR=arr;  //设定计数器自动重装值//刚好0.1ms   
  49.         TIM3->PSC=psc;  //预分频器7200,得到10Khz的计数时钟
  50. //        TIM3->ARR=1000;  //设定计数器自动重装值  1000=1ms                  10000=10ms(1~10ms对应1000~100hz)
  51. //        TIM3->PSC=72;  //预分频器72,得到1Mhz的计数时钟
  52.         TIM3->CCER=0X1111;//打开四个通道,允许输出,有效电平为高
  53.         TIM3->CR1|=1<<7;
  54.         TIM3->EGR|=1;
  55.                 //这两个东东要同时设置才可以使用中断
  56.         TIM3->DIER|=1<<0;   //允许更新中断                               
  57.         TIM3->DIER|=1<<6;   //允许触发中断
  58.         TIM3->CR1|=0x01;    //使能定时器3  
  59. }

  60. void Timer4_Init(u16 arr,u16 psc)
  61. {
  62.         RCC->APB1ENR|=1<<2;//TIM4时钟使能   
  63.         TIM4->ARR=arr;  //设定计数器自动重装值//刚好1ms   
  64.         TIM4->PSC=psc;  //预分频器7200,得到10Khz的计数时钟
  65.         //这两个东东要同时设置才可以使用中断
  66.         TIM4->DIER|=1<<0;   //允许更新中断   
  67.         TIM4->DIER|=1<<6;   //允许触发中断
  68.                
  69.         TIM4->CR1|=0x01;    //使能定时器4
  70.         MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//抢占1,子优先级3,组2         
  71. }
  72. void TIM4_IRQHandler(void)
  73. {
  74.         if(TIM4->SR&0X0001)//溢出中断
  75.         {
  76.                 LED2=!LED2;                                     
  77.         }      
  78.         TIM4->SR&=~(1<<0);//清除中断标志位   
  79. }
  80. void Timer2_Init(u16 arr,u16 psc)
  81. {
  82.         RCC->APB1ENR|=1<<0;//TIM4时钟使能   
  83.         TIM2->ARR=arr;  //设定计数器自动重装值//刚好1ms   
  84.         TIM2->PSC=psc;  //预分频器7200,得到10Khz的计数时钟
  85.         //这两个东东要同时设置才可以使用中断
  86.         TIM2->DIER|=1<<0;   //允许更新中断   
  87.         TIM2->DIER|=1<<6;   //允许触发中断
  88.                
  89.         TIM2->CR1&=0xfe;    //不使能定时器2
  90. //        TIM2->CR1|=0x01;    //使能定时器2
  91.         MY_NVIC_Init(1,3,TIM2_IRQChannel,2);//抢占1,子优先级3,组2       
  92. }
  93. void TIM2_IRQHandler(void)        //1s到
  94. {
  95.         if(TIM2->SR&0X0001)//溢出中断
  96.         {
  97.                 EXTI->IMR &=~(1<<0); //关闭外部中断
  98.                 TIM2->CR1&=0xfe;    //不使能定时器2
  99.                 fre=TIM5CH1_CAPTURE_VAL/2; //计算出频率
  100.                 printf("%d \r\n",fre);
  101.                 TIM5CH1_CAPTURE_VAL=0;
  102.                 LED1=!LED1;       
  103.                 EXTI->IMR |= (1<<0); //打开外部中断                                        
  104.         }      
  105.         TIM2->SR&=~(1<<0);//清除中断标志位   
  106. }
  107. //定时器3中断服务程序
  108. void TIM3_IRQHandler(void)
  109. {                                                                   
  110.         if(TIM3->SR&0X0001)//溢出中断
  111.         {       
  112.                                                                                                                        
  113.         }                                  
  114.         TIM3->SR&=~(1<<0);//清除中断标志位             
  115. }
  116.                                
  117. //外部中断0服务程序
  118. void EXTI0_IRQHandler(void)
  119. {
  120.         TIM2->CR1|=0x01;    //使能定时器2
  121.         TIM5CH1_CAPTURE_VAL ++;
  122.         PUL_CNT ++;
  123.         if(TIM5CH1_CAPTURE_VAL%500==0)
  124.         LED3 = !LED3;         
  125.         EXTI->PR=1<<0;  //清除LINE0上的中断标志位  
  126. }
  127.                                        
  128. int main(void)
  129. {       
  130.         u16 Motor_cnt;
  131.         Stm32_Clock_Init(9); //系统时钟设置
  132.         delay_init(72);             //延时初始化
  133.         uart_init(72,115200);  //串口初始化
  134.         LED_Init();                           //初始化与LED连接的硬件接口
  135.         KEY_Init();                        //按键
  136.         Timer3_Init(1000-1,72-1);                //1MHZ 周期1MS  定时器3产生PWM
  137.         EXTIX_Init();                //外部中断
  138.         Motor_Set();                //电机参数设置
  139.         Timer4_Init(2000,7200);

  140.         Timer2_Init(10000-1,7200-1);

  141.         LED1=0;TIM3->CR1&=0xfe;
  142.            while(1)
  143.         {
  144.                 //delay_ms(100);
  145.                 if(PUL_CNT==1600)  //800个脉冲一圈
  146.                 {        PUL_CNT=0;
  147.                         MOTOR_EN=0;
  148.                         TIM3->CR1&=0xfe;                                                    
  149.                 }
  150.                 if(KEY3==0)
  151.                 {       
  152.                         LED0=0;
  153.                         while(KEY3==0);        LED0=1;
  154.                         MOTOR_DIR = !MOTOR_DIR;
  155.                 }
  156.                 if(KEY1==0)
  157.                 {       
  158.                         LED0=0;TIM5CH1_CAPTURE_VAL=0;
  159.                         while(KEY1==0);        LED0=1;
  160.                         MOTOR_EN = 1;//!MOTOR_EN;
  161.                         TIM3->CR1|=0x01;
  162.                         TIM3->ARR=1000;
  163.                         LED2 = !LED2;
  164.                 }
  165.                 if(KEY2==0)
  166.                 {
  167.                         LED0=0;MOTOR_EN=1; TIM5CH1_CAPTURE_VAL=0;
  168.                         while(KEY2==0);        LED0=1;
  169.                         for(Motor_cnt=1000;Motor_cnt>250;Motor_cnt--)
  170.                         {        if(Motor_cnt<252)
  171.                                         Motor_cnt=249;
  172.                                 TIM3->ARR=Motor_cnt;
  173.                                 delay_ms(5);       
  174.                         }
  175.                         LED3 = !LED3;
  176.                 }  
  177.         }         
  178. }
复制代码

所有资料51hei提供下载:
PWM实现精确输出脉冲数控制电机.rar (350.48 KB, 下载次数: 166)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:473308 发表于 2019-10-12 18:01 | 只看该作者
学习了
回复

使用道具 举报

板凳
ID:473308 发表于 2019-10-14 13:52 | 只看该作者
感谢!!!
回复

使用道具 举报

地板
ID:548664 发表于 2019-10-19 18:40 | 只看该作者
学习一下
回复

使用道具 举报

5#
ID:579329 发表于 2019-10-21 14:19 | 只看该作者
谢谢楼主分享!
回复

使用道具 举报

6#
ID:461428 发表于 2019-10-23 17:22 来自手机 | 只看该作者
位带操作实在看着费解
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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