引脚
PUL+ <—> VCC(+3.3v)
PUL- <—> PA6
DIR+ <—> VCC(+3.3v)
DIR- <—> PB12
ENA+ <—> VCC(+3.3v)
ENA- <—> PB15
按键:
控制使能:PE6
控制方向:PE5
这里没用到PWM
这里按键用了按键3和按键4来控制使能和方向,按键1和2控制PWM脉冲没用到。
bsp_motor_control.c
#include "key.h"
#include "usart.h"
#include "delay.h"
#include "bsp_motor_control.h"
uint8_t KEY3_EN_Or_DisEN_Switch_Times = 0;//按键切换电机使能次数标志位
uint8_t ZhengXiang_Or_FanXiang_Switch_Times = 0;//按键切换电机方向次数标志位
//uint8_t Direction = 1;//电机方向标志位,默认正向。
//uint8_t Motor_EN = 0;//电机使能标标志位,默认失能。
/**
* @brief 电机驱动模块使能引脚的配置函数
* @param 无
* @retval 无
*/
void Motor_EN_GPIO_Configuration(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启电机使能引脚的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( Motor_EN_GPIO_CLK , ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = Motor_EN_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(Motor_EN_GPIO_PORT, &GPIO_InitStructure);
/* 初始时让电机使能引脚输出低电平,失能 */
GPIO_ResetBits(Motor_EN_GPIO_PORT, Motor_EN_GPIO_PIN);
}
void Motor_Direction_GPIO_Configuration(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启电机使能引脚的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( Motor_Dir_GPIO_CLK , ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = Motor_Dir_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(Motor_Dir_GPIO_PORT, &GPIO_InitStructure);
/* 初始时让电机方向引脚输出低电平,正方向 */
GPIO_ResetBits(Motor_Dir_GPIO_PORT, Motor_Dir_GPIO_PIN);
}
void Motor_Pulse_GPIO_Configuration(void)
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启电机脉冲引脚的GPIO外设时钟*/
RCC_APB2PeriphClockCmd( Motor_Pulse_GPIO_CLK , ENABLE);
/*选择要控制的GPIO引脚*/
GPIO_InitStructure.GPIO_Pin = Motor_Pulse_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIO*/
GPIO_Init(Motor_Pulse_GPIO_PORT, &GPIO_InitStructure);
/* 初始时让电机脉冲引脚输出低电平*/
GPIO_ResetBits(Motor_Pulse_GPIO_PORT, Motor_Pulse_GPIO_PIN);
}
void Motor_GPIO_Configuration(void)
{
Motor_EN_GPIO_Configuration();
Motor_Direction_GPIO_Configuration();
Motor_Pulse_GPIO_Configuration();
}
//电机使能还是失能
void EN_Or_DisEN_Motor(void)
{
KEY3_EN_Or_DisEN_Switch_Times++;
if(KEY3_EN_Or_DisEN_Switch_Times%2==0)
{
//按键按下偶数次,电机失能
//Motor_EN=0;/* EN=0,电机失能 */
Motor_Dis_EN();//EN引脚输出低电平时,电机失能。
printf("电机已失能. \r\n");
}
else
{
//按键按下奇数次,电机使能
//Motor_EN=1;/* EN=1,电机使能 */
Motor_EN();//EN引脚输出高电平时,电机使能
printf("电机已使能. \r\n");
printf("电机开始工作.... \r\n");
Motor_Work();
}
}
//电机正向还是反向转
void ZhengXiang_Or_FanXiang_Motor(void)
{
ZhengXiang_Or_FanXiang_Switch_Times++;
if(ZhengXiang_Or_FanXiang_Switch_Times%2==0)//按键按下偶数次,
{
//按键按下偶数次,电机正转
//Direction = 0;/* 正向转 */
printf("电机正向转. \r\n");//Dir引脚输出低电平时,电机正向转
Motor_ZhengZhuan();
}
else
{
//按键按下奇数次,电机反转
//Direction = 1;/* Direction=0,反向转 */
Motor_FanZhuan();//Dir引脚输出高电平时,电机反向转
printf("电机反向转. \r\n");
}
}
/**
* @brief MCU使用GPIO引脚模拟输出方波
* @param tim 方波周期 单位MS 周期越短频率越高,转速越快 细分为1时最少10ms
* @param angle 需要转动的角度值
* @param subdivide 细分值
*/
void MCU_Output_Pulse(int tim,float angle,float subdivide)
{
int n,i;
/*根据细分数求得步距角被分成多少个方波*/
n=(int)(angle/(1.8/subdivide));
/*模拟方波*/
//算一下输出的方波频率:假设tim = 1000,一个周期就是1000us,也就是1ms,产生的频率就是1000Hz
for(i=0;i<n;i++)
{
Pulse_Pin_Output_High();
delay_us(tim/2);
Pulse_Pin_Output_Low();
delay_us(tim/2);
}
Motor_Dis_EN();
}
void Motor_Work(void)
{
MCU_Output_Pulse(1000,360,32);
}
bsp_motor_control.h
**
#include "stm32f10x.h"
#ifndef _BSP_MOTOR_CONTROL_H_
#define _BSP_MOTOR_CONTROL_H_
// 电机使能引脚
#define Motor_EN_GPIO_PORT GPIOB /* GPIO端口 */
#define Motor_EN_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define Motor_EN_GPIO_PIN GPIO_Pin_15 /* 连接GPIOB15 */
// 电机方向引脚
#define Motor_Dir_GPIO_PORT GPIOB /* GPIO端口 */
#define Motor_Dir_GPIO_CLK RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define Motor_Dir_GPIO_PIN GPIO_Pin_12 /* 连接GPIOB12 */
// 电机脉冲引脚
#define Motor_Pulse_GPIO_PORT GPIOA /* GPIO端口 */
#define Motor_Pulse_GPIO_CLK RCC_APB2Periph_GPIOA /* GPIO端口时钟 */
#define Motor_Pulse_GPIO_PIN GPIO_Pin_6 /* 连接GPIOA6 */
//电机使能引脚的配置函数
void Motor_EN_GPIO_Configuration(void);
//电机方向引脚的配置函数
void Motor_Direction_GPIO_Configuration(void);
//电机脉冲引脚的配置函数
void Motor_Pulse_GPIO_Configuration(void);
//电机引脚的配置函数
void Motor_GPIO_Configuration(void);
#define Motor_EN() GPIO_SetBits(Motor_EN_GPIO_PORT, Motor_EN_GPIO_PIN) /* GPIO端口 */
#define Motor_Dis_EN() GPIO_ResetBits(Motor_EN_GPIO_PORT, Motor_EN_GPIO_PIN)
#define Motor_FanZhuan() GPIO_SetBits(Motor_Dir_GPIO_PORT, Motor_Dir_GPIO_PIN) /* GPIO端口 */
#define Motor_ZhengZhuan() GPIO_ResetBits(Motor_Dir_GPIO_PORT, Motor_Dir_GPIO_PIN)
#define Pulse_Pin_Output_High() GPIO_SetBits(Motor_Pulse_GPIO_PORT, Motor_Pulse_GPIO_PIN) /* GPIO端口 */
#define Pulse_Pin_Output_Low() GPIO_ResetBits(Motor_Pulse_GPIO_PORT, Motor_Pulse_GPIO_PIN)
//电机使能
void EN_Or_DisEN_Motor(void);
//电机正向还是反向转
void ZhengXiang_Or_FanXiang_Motor(void);
//参数设定完毕,电机工作
void Motor_Work(void);
#endif /* _BSP_MOTOR_CONTROL_H_ */
**
key.c
#include "key.h"
#include "delay.h"
//按键初始化函数
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(KEY1_PWM_Add_GPIO_CLK|KEY2_PWM_Reduce_GPIO_CLK|KEY3_Motor_EN_GPIO_CLK,ENABLE);//使能PORTA,PORTC时钟
GPIO_InitStructure.GPIO_Pin = KEY1_PWM_Add_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_PWM_Add_GPIO_PORT , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY2_PWM_Reduce_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_PWM_Reduce_GPIO_PORT , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY3_Motor_EN_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY3_Motor_EN_GPIO_PORT , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = KEY4_Motor_Direction_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(KEY3_Motor_EN_GPIO_PORT , &GPIO_InitStructure);
}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//返回值:
//0,没有任何按键按下
//KEY1_PWM_Add_PRES,KEY1_PWM_Add按下
//KEY2_PWM_Reduce_PRES,KEY2_PWM_Reduce按下
//KEY3_Motor_EN_PRES,KEY3_Motor_EN按下
//注意此函数有响应优先级,KEY0>KEY1>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY1_PWM_Add==1||KEY2_PWM_Reduce==1||KEY3_Motor_EN==0||KEY4_Motor_Direction==0))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY1_PWM_Add==1) return KEY1_PWM_Add_PRES;
else if(KEY2_PWM_Reduce==1) return KEY2_PWM_Reduce_PRES;
else if(KEY3_Motor_EN==0) return KEY3_Motor_EN_PRES;
else if(KEY4_Motor_Direction==0) return KEY4_Motor_Direction_PRES;
}else if(KEY1_PWM_Add==0&&KEY2_PWM_Reduce==0&&KEY3_Motor_EN==1&&KEY4_Motor_Direction==1)key_up=1;
return 0;// 无按键按下
}
key.h
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
//控制PWM加
#define KEY1_PWM_Add_GPIO_CLK RCC_APB2Periph_GPIOA
#define KEY1_PWM_Add_GPIO_PORT GPIOA
#define KEY1_PWM_Add_GPIO_PIN GPIO_Pin_0
//控制PWM减
#define KEY2_PWM_Reduce_GPIO_CLK RCC_APB2Periph_GPIOC
#define KEY2_PWM_Reduce_GPIO_PORT GPIOC
#define KEY2_PWM_Reduce_GPIO_PIN GPIO_Pin_13
//控制电机引脚使能还是失能
#define KEY3_Motor_EN_GPIO_CLK RCC_APB2Periph_GPIOE
#define KEY3_Motor_EN_GPIO_PORT GPIOE
#define KEY3_Motor_EN_GPIO_PIN GPIO_Pin_6
//控制电机正转还是反转
#define KEY4_Motor_Direction_GPIO_CLK RCC_APB2Periph_GPIOE
#define KEY4_Motor_Direction_GPIO_PORT GPIOE
#define KEY4_Motor_Direction_GPIO_PIN GPIO_Pin_5
#define KEY1_PWM_Add GPIO_ReadInputDataBit(KEY1_PWM_Add_GPIO_PORT,KEY1_PWM_Add_GPIO_PIN)
#define KEY2_PWM_Reduce GPIO_ReadInputDataBit(KEY2_PWM_Reduce_GPIO_PORT,KEY2_PWM_Reduce_GPIO_PIN)
#define KEY3_Motor_EN GPIO_ReadInputDataBit(KEY3_Motor_EN_GPIO_PORT,KEY3_Motor_EN_GPIO_PIN)
#define KEY4_Motor_Direction GPIO_ReadInputDataBit(KEY4_Motor_Direction_GPIO_PORT,KEY4_Motor_Direction_GPIO_PIN)
#define KEY1_PWM_Add_PRES 3
#define KEY2_PWM_Reduce_PRES 4
#define KEY3_Motor_EN_PRES 2
#define KEY4_Motor_Direction_PRES 1
void KEY_Init(void);//IO初始化
u8 KEY_Scan(u8 mode);
#endif
main.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "bsp_motor_control.h"
void device_Init(void)
{
delay_init(); //延时函数初始化
LED_GPIO_Config();
LED1_ON;
KEY_Init();
Motor_GPIO_Configuration();
uart_init(115200);
printf("步进电机 IO 口模拟控制. \r\n");
}
int main(void)
{
u8 t=0;
device_Init();
while(1)
{
t=KEY_Scan(0); //得到键值
switch(t)
{
case KEY1_PWM_Add_PRES:
break;
case KEY2_PWM_Reduce_PRES:
break;
case KEY3_Motor_EN_PRES:
EN_Or_DisEN_Motor();
break;
case KEY4_Motor_Direction_PRES:
ZhengXiang_Or_FanXiang_Motor();
break;
default:
delay_ms(10);
}
}
}
/*********************************************END OF FILE**********************/