STM32F103输出固定数量脉冲用于控制步进电机

    科技2022-08-11  111

    因为前段时间需要用STM32F103控制步进电机,所以写了了可用于控住GPIO口输出固定数量脉冲的函数,可直接输入脉冲数,并且可以调节PWM的频率(每个脉冲的周期)。 参考了网上大神的指导,我的思路是:用两个定时器(一个用于PWM输出,一个用于中断PWM输出),通过对PWM的周期和输出时间的控制,来达到输出固定脉冲数的目的。 下面为主要代码: #include <sys.h> #include <pwn.h> #include <interrupt.h> #include <step.h> //输出固定脉冲数量 //speed为输出脉冲的频率 //pulse为输出脉冲数量 //在调脉冲频率时,需同时调x void pulse_putput(u16 speed, u16 pulse) { TIM2_init(pulse*10); //设置脉冲数量(10为speed/100) TIM_Cmd(TIM2, ENABLE); //使能TIM4 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能更新中断 TIM3_PWM_Init(speed); //设置PWM输出的频率 TIM_Cmd(TIM3, ENABLE); //使能定时器3 }

    然后就是PWM的初始化代码(这一段是基础的PWM初始化)

    //TIM3 PWN²¿·Ö³õʼ»¯ //PWNÊä³ö³õʼ»¯ //arr: ×Ô¶¯ÖØ×°ÔØ //psc: ʱÖÓÔ¤·ÖƵ void TIM3_PWM_Init(u16 arr) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //ʹÄܶ¨Ê±Æ÷3ʱÖÓ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //ÖØÓ³ÉäTIM3_CH2->PB5 //ÉèÖøÃÒý½ÅΪ¸´ÓÃÊä³ö¹¦ÄÜ£¬Êä³öTIM3 CH2µÄPWNÂö³å²¨ÐÎ GPIOB.5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //¸´ÓÃÍÆÍìÊä³ö GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //³õʼ»¯GPIO //³õʼ»¯TIM3 TIM_TimeBaseStructure.TIM_Period = arr-1; //ÉèÖÃÔÚ×Ô¶¯ÖØ×°ÔØÖÜÆÚÖµ TIM_TimeBaseStructure.TIM_Prescaler = 71; //ÉèÖÃÔ¤·ÖƵֵ TIM_TimeBaseStructure.TIM_ClockDivision = 0; //ÉèÖÃʱÖӷָTDTS = Tck_tiim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMÏòÉϼÆÊýģʽ TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //³õʼ»¯TIMx //³õʼ»¯TIM3 Channel2 PWNģʽ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //Ñ¡ÔñPWNģʽ2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //±È½ÏÊä³ö TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //Êä³ö¼«ÐÔ¸ß TIM_OC2Init(TIM3, &TIM_OCInitStructure); //³õʼ»¯ÍâÉèTIM3 OC2 TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //ʹÄÜÔ¤×°ÔØ¼Ä´æÆ÷ TIM_SetCompare2(TIM3, arr/4); TIM_Cmd(TIM3, ENABLE); //ʹÄÜTIM3 }

    定时器中断初始化

    #include <interrupt.h> #include "sys.h" //通用定时器2中断初始化 void TIM2_init(u16 arr) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //定时器TIM2初始化 TIM_TimeBaseStructure.TIM_Period = arr-1; TIM_TimeBaseStructure.TIM_Prescaler = 7200-1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0); TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); //中断优先级设置 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM2, ENABLE); } //定时器2中断服务程序 void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_CtrlPWMOutputs(TIM3, DISABLE); TIM_Cmd(TIM3, DISABLE); TIM_Cmd(TIM2, DISABLE); TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); } }

    程序的思维图如下 仅为个人拙见!

    献上工程文件(KEIL,STM32F103VET6芯片)

    百度网盘链接:https://pan.baidu.com/s/1jcsudApm-fGemTKgDYPnhA 提取码:ky18 复制这段内容后打开百度网盘手机App,操作更方便哦

    本人为新手,有不对的地方欢迎指正!

    侵删,谢谢

    Processed: 0.013, SQL: 8