精确输出脉冲数控制电机,使用stm32单片机的pwm功能实现,精确控制脉冲个数
单片机源程序如下:
- #include <stm32f10x_lib.h>
- #include "sys.h"
- #include "usart.h"
- #include "delay.h"
- #include "led.h"
- #include "exti.h"
- #include "key.h"
- #define MOTOR_DIR PBout(11)// PB11
- #define MOTOR_EN PEout(15)// PE15
- u16 i;
- u16 fre;
- u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
- u16 PUL_CNT;
- void Motor_Set()
- {
- RCC->APB2ENR|=1<<3; //使能PORTB时钟
- GPIOB->CRH&=0XFFFF0FFF;
- GPIOB->CRH|=0X00003000; //PB11 推挽输出
- GPIOB->ODR|=(1<<11); //PB11 输出高
- RCC->APB2ENR|=1<<6; //使能PORTE时钟
- GPIOE->CRH&=0X0FFFFFFF;
- GPIOE->CRH|=0X30000000; //PE15 推挽输出
- GPIOE->ODR|=(1<<15); //PE15 输出高
- MOTOR_EN=0; //不使能
- }
- void Timer3_Init(u16 arr,u16 psc)
- {
- RCC->APB2ENR|=1<<2; //使能PORTA时钟
- RCC->APB2ENR|=1<<3; //使能PORTB时钟
- RCC->APB2ENR|=1<<5; //使能PORTD时钟
- GPIOB->CRL&=0XFF0FFFFF; //PB5输出
- GPIOB->CRL|=0X00B00000; //复用功能输出
- GPIOA->CRL&=0x00ffffff;
- GPIOA->CRL|=0xBB000000;
- GPIOA->ODR|=3<<6;
- GPIOB->CRL&=0xffffff00;
- GPIOB->CRL|=0x000000BB;
- GPIOB->ODR|=3;
- RCC->APB1ENR|=1<<1;//TIM3时钟使能
- TIM3->CR1|=1<<4;//向下计数
- TIM3->CCMR1=0x6868;//通道1、2PWM模式1,预装载使能
- TIM3->CCMR2=0x6868;//通道3、4PWM模式1,预装载使能
-
- TIM3->CCR1=100;
- TIM3->CCR2=200;
- TIM3->CCR3=200;
- TIM3->CCR4=100; //4k->250
- TIM3->ARR=arr; //设定计数器自动重装值//刚好0.1ms
- TIM3->PSC=psc; //预分频器7200,得到10Khz的计数时钟
- // TIM3->ARR=1000; //设定计数器自动重装值 1000=1ms 10000=10ms(1~10ms对应1000~100hz)
- // TIM3->PSC=72; //预分频器72,得到1Mhz的计数时钟
- TIM3->CCER=0X1111;//打开四个通道,允许输出,有效电平为高
- TIM3->CR1|=1<<7;
- TIM3->EGR|=1;
- //这两个东东要同时设置才可以使用中断
- TIM3->DIER|=1<<0; //允许更新中断
- TIM3->DIER|=1<<6; //允许触发中断
- TIM3->CR1|=0x01; //使能定时器3
- }
- void Timer4_Init(u16 arr,u16 psc)
- {
- RCC->APB1ENR|=1<<2;//TIM4时钟使能
- TIM4->ARR=arr; //设定计数器自动重装值//刚好1ms
- TIM4->PSC=psc; //预分频器7200,得到10Khz的计数时钟
- //这两个东东要同时设置才可以使用中断
- TIM4->DIER|=1<<0; //允许更新中断
- TIM4->DIER|=1<<6; //允许触发中断
-
- TIM4->CR1|=0x01; //使能定时器4
- MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//抢占1,子优先级3,组2
- }
- void TIM4_IRQHandler(void)
- {
- if(TIM4->SR&0X0001)//溢出中断
- {
- LED2=!LED2;
- }
- TIM4->SR&=~(1<<0);//清除中断标志位
- }
- void Timer2_Init(u16 arr,u16 psc)
- {
- RCC->APB1ENR|=1<<0;//TIM4时钟使能
- TIM2->ARR=arr; //设定计数器自动重装值//刚好1ms
- TIM2->PSC=psc; //预分频器7200,得到10Khz的计数时钟
- //这两个东东要同时设置才可以使用中断
- TIM2->DIER|=1<<0; //允许更新中断
- TIM2->DIER|=1<<6; //允许触发中断
-
- TIM2->CR1&=0xfe; //不使能定时器2
- // TIM2->CR1|=0x01; //使能定时器2
- MY_NVIC_Init(1,3,TIM2_IRQChannel,2);//抢占1,子优先级3,组2
- }
- void TIM2_IRQHandler(void) //1s到
- {
- if(TIM2->SR&0X0001)//溢出中断
- {
- EXTI->IMR &=~(1<<0); //关闭外部中断
- TIM2->CR1&=0xfe; //不使能定时器2
- fre=TIM5CH1_CAPTURE_VAL/2; //计算出频率
- printf("%d \r\n",fre);
- TIM5CH1_CAPTURE_VAL=0;
- LED1=!LED1;
- EXTI->IMR |= (1<<0); //打开外部中断
- }
- TIM2->SR&=~(1<<0);//清除中断标志位
- }
- //定时器3中断服务程序
- void TIM3_IRQHandler(void)
- {
- if(TIM3->SR&0X0001)//溢出中断
- {
-
- }
- TIM3->SR&=~(1<<0);//清除中断标志位
- }
-
- //外部中断0服务程序
- void EXTI0_IRQHandler(void)
- {
- TIM2->CR1|=0x01; //使能定时器2
- TIM5CH1_CAPTURE_VAL ++;
- PUL_CNT ++;
- if(TIM5CH1_CAPTURE_VAL%500==0)
- LED3 = !LED3;
- EXTI->PR=1<<0; //清除LINE0上的中断标志位
- }
-
- int main(void)
- {
- u16 Motor_cnt;
- Stm32_Clock_Init(9); //系统时钟设置
- delay_init(72); //延时初始化
- uart_init(72,115200); //串口初始化
- LED_Init(); //初始化与LED连接的硬件接口
- KEY_Init(); //按键
- Timer3_Init(1000-1,72-1); //1MHZ 周期1MS 定时器3产生PWM
- EXTIX_Init(); //外部中断
- Motor_Set(); //电机参数设置
- Timer4_Init(2000,7200);
- Timer2_Init(10000-1,7200-1);
- LED1=0;TIM3->CR1&=0xfe;
- while(1)
- {
- //delay_ms(100);
- if(PUL_CNT==1600) //800个脉冲一圈
- { PUL_CNT=0;
- MOTOR_EN=0;
- TIM3->CR1&=0xfe;
- }
- if(KEY3==0)
- {
- LED0=0;
- while(KEY3==0); LED0=1;
- MOTOR_DIR = !MOTOR_DIR;
- }
- if(KEY1==0)
- {
- LED0=0;TIM5CH1_CAPTURE_VAL=0;
- while(KEY1==0); LED0=1;
- MOTOR_EN = 1;//!MOTOR_EN;
- TIM3->CR1|=0x01;
- TIM3->ARR=1000;
- LED2 = !LED2;
- }
- if(KEY2==0)
- {
- LED0=0;MOTOR_EN=1; TIM5CH1_CAPTURE_VAL=0;
- while(KEY2==0); LED0=1;
- for(Motor_cnt=1000;Motor_cnt>250;Motor_cnt--)
- { if(Motor_cnt<252)
- Motor_cnt=249;
- TIM3->ARR=Motor_cnt;
- delay_ms(5);
- }
- LED3 = !LED3;
- }
- }
- }
复制代码
所有资料51hei提供下载:
PWM实现精确输出脉冲数控制电机.rar
(350.48 KB, 下载次数: 167)
|