stepper.h
#ifndef __STEPMOTOR_H
#define __STEPMOTOR_H
#include "sys.h"
#include "stm32f4xx_tim.h"
//使用定时器8 C6、C7/C8/C9
//端口定义
#define STEPMOTOR1_DIR PGout(5) // DS0
#define STEPMOTOR1_ENA PGout(6)// DS1
/*---------------------- 配置宏 ------------------------*/
#define STEPMOTOR1_DIR_PIN GPIO_Pin_5 // KEY 引脚
#define STEPMOTOR1_DIR_PORT GPIOG // KEY GPIO端口
#define STEPMOTOR1_DIR_CLK RCC_AHB1Periph_GPIOG // KEY GPIO端口时钟
#define STEPMOTOR1_DIR_CLK_ENA() {RCC_AHB1PeriphClockCmd( STEPMOTOR1_DIR_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能
#define STEPMOTOR1_ENA_PIN GPIO_Pin_6 // KEY 引脚
#define STEPMOTOR1_ENA_PORT GPIOG // KEY GPIO端口
#define STEPMOTOR1_ENA_CLK RCC_AHB1Periph_GPIOG // KEY GPIO端口时钟
#define STEPMOTOR1_ENA_CLK_ENA() {RCC_AHB1PeriphClockCmd( STEPMOTOR1_ENA_CLK ,ENABLE);}//根据实际修改:时钟线,时钟使能
#define CW 0 //正转
#define CCW 1 //反转
extern u32 Toggle_Pulse[4];
void stepmotor1234_gpio_Init(void);//初始化
void stepmotor1234_timer8_Init(u32 arr,u32 psc);//初始化
#endif
stepper.c
#include "stepmotor.h"
u32 Toggle_Pulse[4]={900,500,500,500};
void stepmotor1234_gpio_Init(void)//初始化
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
STEPMOTOR1_DIR_CLK_ENA(); //初始化KEY时钟
GPIO_InitStructure.GPIO_Pin = STEPMOTOR1_DIR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(STEPMOTOR1_DIR_PORT, &GPIO_InitStructure);
STEPMOTOR1_ENA_CLK_ENA(); //初始化KEY时钟
GPIO_InitStructure.GPIO_Pin = STEPMOTOR1_ENA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(STEPMOTOR1_ENA_PORT, &GPIO_InitStructure);
}
//(1) TIM_OCMode:比较输出模式选择,总共有八种,常用的为PWM1/PWM2。它设定CCMRx寄存器OCxM[2:0]位的值。
//(2) TIM_OutputState:比较输出使能,决定最终的输出比较信号OCx是否通过外部引脚输出。它设定TIMx_CCER寄存器CCxE/CCxNE位的值。
//(3) TIM_OutputNState:比较互补输出使能,决定OCx的互补信号OCxN是否通过外部引脚输出。它设定CCER寄存器CCxNE位的值。
//(4) TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器CCR的值,决定脉冲宽度。可设置范围为0至65535。
//(5) TIM_OCPolarity:比较输出极性,可选OCx为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定CCER寄存器的CCxP位的值。
//(6) TIM_OCNPolarity:比较互补输出极性,可选OCxN为高电平有效或低电平有效。它设定TIMx_CCER寄存器的CCxNP位的值。
//(7) TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出1或输出0,即在空闲状态(BDTR_MOE位为0)时,经过死区时间后定时器通道输出高电平或低电平。它设定CR2寄存器的OISx位的值。
//(8) TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出1或输出0,即在空闲状态(BDTR_MOE位为0)时,经过死区时间后定时器互补通道输出高电平或低电平,
//设定值必须与TIM_OCIdleState相反。它设定是CR2寄存器的OISxN位的
void stepmotor1234_timer8_Init(u32 arr,u32 psc)//初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE); //TIM1时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使能PORTA时钟
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8); //GPIOA8复用为定时器1
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8); //GPIOA8复用为定时器1
GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_TIM8); //GPIOA8复用为定时器1
GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_TIM8); //GPIOA8复用为定时器1
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 |GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9; //GPIOA8--
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //上拉 GPIO_PuPd_DOWN; //下拉
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化PA8
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频0
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值 65535最大值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // ((uint16_t)0x0000)
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //20201020
TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);//初始化定时器8
//-------------------
//选择定时器模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
//输出极性:TIM输出比较极性低TIM_OCPolarity_High
TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_Low;
// TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出1或输出0
TIM_OCInitStructure.TIM_OCIdleState= TIM_OCIdleState_Reset ;// ((uint16_t)0x0000)
TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Set;//((uint16_t)0x0000)
TIM_OCInitStructure.TIM_Pulse =Toggle_Pulse[0];
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//
TIM_OC1Init(TIM8, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Disable);
//禁止使能TIM1在CCR1上的预装载寄存器
TIM_OC1FastConfig(TIM8, TIM_OCFast_Disable);
TIM_OCInitStructure.TIM_Pulse=Toggle_Pulse[1];
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;//
TIM_OC2Init(TIM8, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Disable); //使能TIM1在CCR1上的预装载寄存器
//
TIM_OCInitStructure.TIM_Pulse=Toggle_Pulse[2];
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//
TIM_OC3Init(TIM8, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Disable); //使能TIM1在CCR1上的预装载寄存器
TIM_OCInitStructure.TIM_Pulse=Toggle_Pulse[3];
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//
TIM_OC4Init(TIM8, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Disable); //使能TIM1在CCR1上的预装载寄存器
//
// 不对定时器做任何分频,并且让它满计数,即计数周期为65535。接下去再设置个
// 通道的的工作模式为输出比较翻转模式,设置通道1的比较值为CCR1_Val、CCR3_Val、CCR3_Val、CCR4_Val,
// 它们的值在OCToggle.h中定义。然后打开个通道的输出比较事件的中断。最后在打开定时器。这样的话,
// 定时器这段就配置完成了。
//主函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn; //TIM8中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级1级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_ARRPreloadConfig(TIM8,DISABLE);//ARPE使能
TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);//清除标志位TIM_IT_CC1
TIM_ITConfig(TIM8, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);//中断标志
TIM_Cmd(TIM8, ENABLE);//打开定时器8,
TIM_CtrlPWMOutputs(TIM8, ENABLE); //20201020
}
void TIM8_CC_IRQHandler(void)
{
static u16 capture = 0;
if (TIM_GetITStatus(TIM8, TIM_IT_CC1) != RESET)//通道1检测到比较事件
{
STEPMOTOR1_DIR=!STEPMOTOR1_DIR;
TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);//清除标志位TIM_IT_CC1
capture = TIM_GetCapture1(TIM8);
TIM_SetCompare1(TIM8, capture + Toggle_Pulse[0]);//重新设置比较值
}
if (TIM_GetITStatus(TIM8, TIM_IT_CC2) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM8, TIM_IT_CC2);//清除标志位
STEPMOTOR1_ENA=!STEPMOTOR1_ENA;
capture = TIM_GetCapture2(TIM8);
TIM_SetCompare2(TIM8, capture + Toggle_Pulse[1]);//重新设置比较值
}
if (TIM_GetITStatus(TIM8, TIM_IT_CC3) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM8, TIM_IT_CC3);//清除标志位
capture = TIM_GetCapture3(TIM8);
TIM_SetCompare3(TIM8, capture + Toggle_Pulse[2]);//重新设置比较值
}
if (TIM_GetITStatus(TIM8, TIM_IT_CC4) != RESET)//通道1检测到比较事件
{
TIM_ClearITPendingBit(TIM8, TIM_IT_CC4);//清除标志位
capture = TIM_GetCapture4(TIM8);
TIM_SetCompare4(TIM8, capture + Toggle_Pulse[3]);//重新设置比较值
}
}
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "oled.h"
#include "key.h"
#include "EXTI.h"
#include "timer.h"
#include "pwm.h"
#include "dcmotor.h"
#include "linesensor.h"
#include "stepmotor.h"
extern u32 Toggle_Pulse[4];
//全局变量,存储按键键码
u8 GLOKEYVAL=0;
u8 pwmflag=0;
u8 pwmaddsubflag=0;
int main(void)
{
int shuzi=987;
u8 keyval=0;
float aa=123.456;
float vvtemp=0.2;
delay_init(168);
//LED_Init();
OLED_Init();
TIMER14_CH1_PWM1_Init(500-1,84-1);//初始化 2khz F9
KEY_Init();
//EXTIX_Init();
TIMER13_Init(200-1,8400-1);
//定时器时钟 84M,分频系数 8400,所以 84M/8400=10Khz ===0.1MS
//的计数频率,计数 5000 次为 500ms
// TIM1_PWM_Init(500-1,84-1);//1US*500=500US====实际250us 300/500=0.6
delay_ms(30);
OLED_Clear();
LineSensor_Init();
TIM1_PWM_Init(600-1,84-1);
DCMotor1Init();
DCMotor2Init();
DCMotor3Init();
DCMotor4Init();
TIM_Cmd(TIM13,ENABLE);
TIM_Cmd(TIM14, DISABLE);
Toggle_Pulse[0]=100;
Toggle_Pulse[1]=1000;
stepmotor1234_gpio_Init();
stepmotor1234_timer8_Init(65535,168-1);//
//168分频,168MHz/168=1Mhz,1us计算一次,那么计算Toggle_Pulse[0]=100次,100*1us=100us
//反转一次电平。那么得到周期是100+100=200us
while(1)
{
}
}
注意,高级定时器挂在APB2总线上;是168M时钟;