新手上路
- 积分
- 43
- 金钱
- 43
- 注册时间
- 2021-2-21
- 在线时间
- 16 小时
|
10金钱
楼主的程序有一个按键控制步进电机的正反转,程序同时带有两个直流电机的驱动模块,直流电机的程序基本没影响,但因程序是之前写的,现在回过头来重新改进发现之前的程序已经不能驱动步进电机了,修改不当后程序彻底瘫痪,求助大神帮忙查查问题和改进方法,主要代码如下:
main.c:
#define a 0.8 //步进电机转动360度丝杠运动的距离
#define X 200 //上位机传输十进制数值坐标
#define max 500 //最大有效距离
/*
细分:4 脉冲/转:800 开关关
细分:8 脉冲/转:1600 关开关
细分:16 脉冲/转:3200 关关开
细分:32 脉冲/转:6400 关关关
*/
int main(void)
{
int N;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
Motor_12_Config(); //298电机驱动初始化 Motor_Init();//直线电机的初使化
//Motor_3_Config();
Key_GPIO_Config();//按键端口初始化
delay_init(); //延时函数初始化
// uart_init(115200); //串口初始化为115200
delay_ms(10000);
KEY_Init();//按键初始化 Key1_GPIO_Config(); //按键初始化
//Motor_Init(); //电机IO初始化
N=(X/a)*1600;
while(1)
{
Motor_1_PRun(); //正转
Motor_2_PRun();
delay_ms(10000); //转五秒
delay_ms(10000);
delay_ms(10000);
Motor_1_STOP(); //停止
Motor_2_STOP();
delay_ms(10000); //停三秒
delay_ms(10000);
delay_ms(10000);
Cycle1(N);
delay_ms(100);
Cycle2(N);
delay_ms(100);
}
}
bsp_tb6600.c:
#include "bsp_tb6600.h"
#include "timer.h"
/* 共阴极接法,高电平有效
A9为脉冲输出,脉冲频率控制步进电机转动速度;
A10为高低电平输出,高电平为正转,低电平为反转;
A11为使能,高电平脉冲和方向不受控制,低电平受控制*/
#define time 25
/********** 驱动器 端口定义 **************
//ENA+(DRIVER_OE) PA11 (TIM1_CH1) 使能
//DRIVER_DIR PA10 (TIM1_CH2) 方向
//STEP_PULSE PA9 (TIM1_CH2) 脉冲
******************************************/
static void TB6600_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //端口配置结构体
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //翻转速度为50Mhz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
GPIO_ResetBits(GPIOA,GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11); //A9、A10、A11置0
}
//控制步进电机正转
void Cycle1(int N)//X为到达指定位置需要多少个脉冲
{
TB6600_Config();
GPIO_SetBits(GPIOA,GPIO_Pin_10);
while(N!=0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_9);
SysTick_Delay_Us(100);
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
SysTick_Delay_Us(100);
N--;
}
}
//控制步进电机反转
void Cycle2(int N)//X为到达指定位置需要多少个脉冲
{
TB6600_Config();
GPIO_ResetBits(GPIOA,GPIO_Pin_10);
while(N!=0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_9);
SysTick_Delay_Us(100);
GPIO_ResetBits(GPIOA,GPIO_Pin_9);
SysTick_Delay_Us(100);
N--;
}
}
bsp_systick.c:
#include "bsp_SysTick.h"
#include "core_cm3.h"
#include "misc.h"
static __IO u32 TimingDelay;
/**
* @brief 启动系统滴答定时器 SysTick
* @param 无
* @retval 无
*/
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms中断一次
* SystemFrequency / 100000 10us中断一次
* SystemFrequency / 1000000 1us中断一次
*/
// if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0库版本
if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0库版本
{
/* Capture error */
while (1);
}
}
/**
* @brief us延时程序,10us为一个单位
* @param
* @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
* @retval 无
*/
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
// 使能滴答定时器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(TimingDelay != 0);
}
/**
* @brief 获取节拍程序
* @param 无
* @retval 无
* @attention 在 SysTick 中断函数 SysTick_Handler()调用
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
#if 0
// 这个 固件库函数 在 core_cm3.h中
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// reload 寄存器为24bit,最大值为2^24
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
// 配置 reload 寄存器的初始值
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
// 配置中断优先级为 1<<4-1 = 15,优先级为最低
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
// 配置 counter 计数器的值
SysTick->VAL = 0;
// 配置systick 的时钟为 72M
// 使能中断
// 使能systick
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
#endif
// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)
void SysTick_Delay_Us( __IO uint32_t us)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000000);
for(i=0;i<us;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
while( !((SysTick->CTRL)&(1<<16)) );
}
// 关闭SysTick定时器
SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Delay_Ms( __IO uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for(i=0;i<ms;i++)
{
// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
// 当置1时,读取该位会清0
while( !((SysTick->CTRL)&(1<<16)) );
}
// 关闭SysTick定时器
SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
/*********************************************END OF FILE**********************/
timer.c:
#include "timer.h"
#include "usart.h"
//通用定时器1中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器1!
void TIM1_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM1中断,允许更新中断
//设置优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIMx外设
}
//定时器1中断服务程序
void TIM1_UP_IRQHandler(void) //TIM1中断
{
if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
}
}
//TIM1 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); //使能定时器1时钟
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
//GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
//设置该引脚为复用输出功能,输出TIM1 CH2的PWM脉冲波形 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO
//初始化TIM1
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //高级定时器特有
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM1 Channel2 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 OC2
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR2上的预装载寄存器
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE); //高级定时器必须有的一句,使能PWM输出
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
如需要查看其他部分的代码,评论我补充,谢谢各位大神!!!
|
|