因为前段时间需要用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,操作更方便哦
本人为新手,有不对的地方欢迎指正!
侵删,谢谢
来源:oschina
链接:https://my.oschina.net/u/4365323/blog/4661336