单片机
返回首页

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

2019-10-14 来源:eefocus

精确输出脉冲数控制电机,使用stm32单片机的pwm功能实现,精确控制脉冲个数


单片机源程序如下:


#include

#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 rn',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;

                }  

        }         

}


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章